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