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 24 namespace llvm { 25 class Triple; 26 namespace omp { 27 28 /// OpenMP Context related IDs and helpers 29 /// 30 ///{ 31 32 /// IDs for all OpenMP context selector trait sets (construct/device/...). 33 enum 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...}/...). 39 enum 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/...) 45 enum 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. 52 TraitSet getOpenMPContextTraitSetKind(StringRef Str); 53 54 /// Return the trait set for which \p Selector is a selector. 55 TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); 56 57 /// Return the trait set for which \p Property is a property. 58 TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); 59 60 /// Return a textual representation of the trait set \p Kind. 61 StringRef getOpenMPContextTraitSetName(TraitSet Kind); 62 63 /// Parse \p Str and return the trait set it matches or 64 /// TraitSelector::invalid. 65 TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str); 66 67 /// Return the trait selector for which \p Property is a property. 68 TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property); 69 70 /// Return a textual representation of the trait selector \p Kind. 71 StringRef 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. 75 TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, 76 TraitSelector Selector, 77 StringRef Str); 78 79 /// Return the trait property for a singleton selector \p Selector. 80 TraitProperty 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. 85 StringRef 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. 90 StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); 91 92 /// Return a string listing all trait sets. 93 std::string listOpenMPContextTraitSets(); 94 95 /// Return a string listing all trait selectors for \p Set. 96 std::string listOpenMPContextTraitSelectors(TraitSet Set); 97 98 /// Return a string listing all trait properties for \p Set and \p Selector. 99 std::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. 107 bool 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. 112 bool 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. 119 struct 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. 157 struct OMPContext { 158 OMPContext(bool IsDeviceCompilation, Triple TargetTriple); 159 virtual ~OMPContext() = default; 160 addTraitOMPContext161 void addTrait(TraitProperty Property) { 162 addTrait(getOpenMPContextTraitSetForProperty(Property), Property); 163 } addTraitOMPContext164 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. matchesISATraitOMPContext173 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. 183 bool 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. 189 int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs, 190 const OMPContext &Ctx); 191 192 } // namespace omp 193 194 template <> 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