1//===- OpenMP/OMPContext.h ----- OpenMP context helper functions - C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9///
10/// This file provides helper functions and classes to deal with OpenMP
11/// contexts as used by `[begin/end] declare variant` and `metadirective`.
12///
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_FRONTEND_OPENMP_OMPCONTEXT_H
16#define LLVM_FRONTEND_OPENMP_OMPCONTEXT_H
17
18#include "llvm/ADT/APSInt.h"
19#include "llvm/ADT/BitVector.h"
20#include "llvm/ADT/SetVector.h"
21#include "llvm/ADT/SmallSet.h"
22#include "llvm/ADT/Triple.h"
23#include "llvm/Frontend/OpenMP/OMPConstants.h"
24
25namespace llvm {
26namespace omp {
27
28/// OpenMP Context related IDs and helpers
29///
30///{
31
32/// IDs for all OpenMP context selector trait sets (construct/device/...).
33enum class TraitSet {
34#define OMP_TRAIT_SET(Enum, ...) Enum,
35#include "llvm/Frontend/OpenMP/OMPKinds.def"
36};
37
38/// IDs for all OpenMP context selector trait (device={kind/isa...}/...).
39enum class TraitSelector {
40#define OMP_TRAIT_SELECTOR(Enum, ...) Enum,
41#include "llvm/Frontend/OpenMP/OMPKinds.def"
42};
43
44/// IDs for all OpenMP context trait properties (host/gpu/bsc/llvm/...)
45enum class TraitProperty {
46#define OMP_TRAIT_PROPERTY(Enum, ...) Enum,
47#define OMP_LAST_TRAIT_PROPERTY(Enum) Last = Enum
48#include "llvm/Frontend/OpenMP/OMPKinds.def"
49};
50
51/// Parse \p Str and return the trait set it matches or TraitSet::invalid.
52TraitSet getOpenMPContextTraitSetKind(StringRef Str);
53
54/// Return the trait set for which \p Selector is a selector.
55TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector);
56
57/// Return the trait set for which \p Property is a property.
58TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property);
59
60/// Return a textual representation of the trait set \p Kind.
61StringRef getOpenMPContextTraitSetName(TraitSet Kind);
62
63/// Parse \p Str and return the trait set it matches or
64/// TraitSelector::invalid.
65TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str);
66
67/// Return the trait selector for which \p Property is a property.
68TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property);
69
70/// Return a textual representation of the trait selector \p Kind.
71StringRef getOpenMPContextTraitSelectorName(TraitSelector Kind);
72
73/// Parse \p Str and return the trait property it matches in the set \p Set and
74/// selector \p Selector or TraitProperty::invalid.
75TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set,
76 TraitSelector Selector,
77 StringRef Str);
78
79/// Return the trait property for a singleton selector \p Selector.
80TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector);
81
82/// Return a textual representation of the trait property \p Kind, which might
83/// be the raw string we parsed (\p RawString) if we do not translate the
84/// property into a (distinct) enum.
85StringRef getOpenMPContextTraitPropertyName(TraitProperty Kind,
86 StringRef RawString);
87
88/// Return a textual representation of the trait property \p Kind with selector
89/// and set name included.
90StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind);
91
92/// Return a string listing all trait sets.
93std::string listOpenMPContextTraitSets();
94
95/// Return a string listing all trait selectors for \p Set.
96std::string listOpenMPContextTraitSelectors(TraitSet Set);
97
98/// Return a string listing all trait properties for \p Set and \p Selector.
99std::string listOpenMPContextTraitProperties(TraitSet Set,
100 TraitSelector Selector);
101///}
102
103/// Return true if \p Selector can be nested in \p Set. Also sets
104/// \p AllowsTraitScore and \p RequiresProperty to true/false if the user can
105/// specify a score for properties in \p Selector and if the \p Selector
106/// requires at least one property.
107bool isValidTraitSelectorForTraitSet(TraitSelector Selector, TraitSet Set,
108 bool &AllowsTraitScore,
109 bool &RequiresProperty);
110
111/// Return true if \p Property can be nested in \p Selector and \p Set.
112bool isValidTraitPropertyForTraitSetAndSelector(TraitProperty Property,
113 TraitSelector Selector,
114 TraitSet Set);
115
116/// Variant match information describes the required traits and how they are
117/// scored (via the ScoresMap). In addition, the required consturct nesting is
118/// decribed as well.
119struct VariantMatchInfo {
120 /// Add the trait \p Property to the required trait set. \p RawString is the
121 /// string we parsed and derived \p Property from. If \p Score is not null, it
122 /// recorded as well. If \p Property is in the `construct` set it is recorded
123 /// in-order in the ConstructTraits as well.
124 void addTrait(TraitProperty Property, StringRef RawString,
125 APInt *Score = nullptr) {
126 addTrait(getOpenMPContextTraitSetForProperty(Property), Property, RawString,
127 Score);
128 }
129 /// Add the trait \p Property which is in set \p Set to the required trait
130 /// set. \p RawString is the string we parsed and derived \p Property from. If
131 /// \p Score is not null, it recorded as well. If \p Set is the `construct`
132 /// set it is recorded in-order in the ConstructTraits as well.
133 void addTrait(TraitSet Set, TraitProperty Property, StringRef RawString,
134 APInt *Score = nullptr) {
135 if (Score)
136 ScoreMap[Property] = *Score;
137
138 // Special handling for `device={isa(...)}` as we do not match the enum but
139 // the raw string.
140 if (Property == TraitProperty::device_isa___ANY)
141 ISATraits.push_back(RawString);
142
143 RequiredTraits.set(unsigned(Property));
144 if (Set == TraitSet::construct)
145 ConstructTraits.push_back(Property);
146 }
147
148 BitVector RequiredTraits = BitVector(unsigned(TraitProperty::Last) + 1);
149 SmallVector<StringRef, 8> ISATraits;
150 SmallVector<TraitProperty, 8> ConstructTraits;
151 SmallDenseMap<TraitProperty, APInt> ScoreMap;
152};
153
154/// The context for a source location is made up of active property traits,
155/// e.g., device={kind(host)}, and constructs traits which describe the nesting
156/// in OpenMP constructs at the location.
157struct OMPContext {
158 OMPContext(bool IsDeviceCompilation, Triple TargetTriple);
159 virtual ~OMPContext() = default;
160
161 void addTrait(TraitProperty Property) {
162 addTrait(getOpenMPContextTraitSetForProperty(Property), Property);
163 }
164 void addTrait(TraitSet Set, TraitProperty Property) {
165 ActiveTraits.set(unsigned(Property));
166 if (Set == TraitSet::construct)
167 ConstructTraits.push_back(Property);
168 }
169
170 /// Hook for users to check if an ISA trait matches. The trait is described as
171 /// the string that got parsed and it depends on the target and context if
172 /// this matches or not.
173 virtual bool matchesISATrait(StringRef) const { return false; }
174
175 BitVector ActiveTraits = BitVector(unsigned(TraitProperty::Last) + 1);
176 SmallVector<TraitProperty, 8> ConstructTraits;
177};
178
179/// Return true if \p VMI is applicable in \p Ctx, that is, all traits required
180/// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is
181/// true, only the device selector set, if present, are checked. Note that we
182/// still honor extension traits provided by the user.
183bool isVariantApplicableInContext(const VariantMatchInfo &VMI,
184 const OMPContext &Ctx,
185 bool DeviceSetOnly = false);
186
187/// Return the index (into \p VMIs) of the variant with the highest score
188/// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext.
189int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs,
190 const OMPContext &Ctx);
191
192} // namespace omp
193
194template <> struct DenseMapInfo<omp::TraitProperty> {
195 static inline omp::TraitProperty getEmptyKey() {
196 return omp::TraitProperty(-1);
197 }
198 static inline omp::TraitProperty getTombstoneKey() {
199 return omp::TraitProperty(-2);
200 }
201 static unsigned getHashValue(omp::TraitProperty val) {
202 return std::hash<unsigned>{}(unsigned(val));
203 }
204 static bool isEqual(omp::TraitProperty LHS, omp::TraitProperty RHS) {
205 return LHS == RHS;
206 }
207};
208
209} // end namespace llvm
210#endif // LLVM_FRONTEND_OPENMP_OMPCONTEXT_H
211