1097a140dSpatrick //===- OpenMP/OMPContext.h ----- OpenMP context helper functions - C++ -*-===// 2097a140dSpatrick // 3097a140dSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4097a140dSpatrick // See https://llvm.org/LICENSE.txt for license information. 5097a140dSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6097a140dSpatrick // 7097a140dSpatrick //===----------------------------------------------------------------------===// 8097a140dSpatrick /// \file 9097a140dSpatrick /// 10097a140dSpatrick /// This file provides helper functions and classes to deal with OpenMP 11097a140dSpatrick /// contexts as used by `[begin/end] declare variant` and `metadirective`. 12097a140dSpatrick /// 13097a140dSpatrick //===----------------------------------------------------------------------===// 14097a140dSpatrick 1573471bf0Spatrick #ifndef LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 1673471bf0Spatrick #define LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 17097a140dSpatrick 18*d415bd75Srobert #include "llvm/ADT/APInt.h" 19097a140dSpatrick #include "llvm/ADT/BitVector.h" 20*d415bd75Srobert #include "llvm/ADT/DenseMap.h" 21*d415bd75Srobert #include "llvm/ADT/DenseMapInfo.h" 22097a140dSpatrick #include "llvm/Frontend/OpenMP/OMPConstants.h" 23097a140dSpatrick 24097a140dSpatrick namespace llvm { 25*d415bd75Srobert class Triple; 26097a140dSpatrick namespace omp { 27097a140dSpatrick 28097a140dSpatrick /// OpenMP Context related IDs and helpers 29097a140dSpatrick /// 30097a140dSpatrick ///{ 31097a140dSpatrick 32097a140dSpatrick /// IDs for all OpenMP context selector trait sets (construct/device/...). 33097a140dSpatrick enum class TraitSet { 34097a140dSpatrick #define OMP_TRAIT_SET(Enum, ...) Enum, 35097a140dSpatrick #include "llvm/Frontend/OpenMP/OMPKinds.def" 36097a140dSpatrick }; 37097a140dSpatrick 38097a140dSpatrick /// IDs for all OpenMP context selector trait (device={kind/isa...}/...). 39097a140dSpatrick enum class TraitSelector { 40097a140dSpatrick #define OMP_TRAIT_SELECTOR(Enum, ...) Enum, 41097a140dSpatrick #include "llvm/Frontend/OpenMP/OMPKinds.def" 42097a140dSpatrick }; 43097a140dSpatrick 44097a140dSpatrick /// IDs for all OpenMP context trait properties (host/gpu/bsc/llvm/...) 45097a140dSpatrick enum class TraitProperty { 46097a140dSpatrick #define OMP_TRAIT_PROPERTY(Enum, ...) Enum, 47097a140dSpatrick #define OMP_LAST_TRAIT_PROPERTY(Enum) Last = Enum 48097a140dSpatrick #include "llvm/Frontend/OpenMP/OMPKinds.def" 49097a140dSpatrick }; 50097a140dSpatrick 51097a140dSpatrick /// Parse \p Str and return the trait set it matches or TraitSet::invalid. 52097a140dSpatrick TraitSet getOpenMPContextTraitSetKind(StringRef Str); 53097a140dSpatrick 54097a140dSpatrick /// Return the trait set for which \p Selector is a selector. 55097a140dSpatrick TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); 56097a140dSpatrick 57097a140dSpatrick /// Return the trait set for which \p Property is a property. 58097a140dSpatrick TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); 59097a140dSpatrick 60097a140dSpatrick /// Return a textual representation of the trait set \p Kind. 61097a140dSpatrick StringRef getOpenMPContextTraitSetName(TraitSet Kind); 62097a140dSpatrick 63097a140dSpatrick /// Parse \p Str and return the trait set it matches or 64097a140dSpatrick /// TraitSelector::invalid. 65097a140dSpatrick TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str); 66097a140dSpatrick 67097a140dSpatrick /// Return the trait selector for which \p Property is a property. 68097a140dSpatrick TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property); 69097a140dSpatrick 70097a140dSpatrick /// Return a textual representation of the trait selector \p Kind. 71097a140dSpatrick StringRef getOpenMPContextTraitSelectorName(TraitSelector Kind); 72097a140dSpatrick 7373471bf0Spatrick /// Parse \p Str and return the trait property it matches in the set \p Set and 7473471bf0Spatrick /// selector \p Selector or TraitProperty::invalid. 7573471bf0Spatrick TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, 7673471bf0Spatrick TraitSelector Selector, 7773471bf0Spatrick StringRef Str); 78097a140dSpatrick 79097a140dSpatrick /// Return the trait property for a singleton selector \p Selector. 80097a140dSpatrick TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector); 81097a140dSpatrick 8273471bf0Spatrick /// Return a textual representation of the trait property \p Kind, which might 8373471bf0Spatrick /// be the raw string we parsed (\p RawString) if we do not translate the 8473471bf0Spatrick /// property into a (distinct) enum. 8573471bf0Spatrick StringRef getOpenMPContextTraitPropertyName(TraitProperty Kind, 8673471bf0Spatrick StringRef RawString); 87097a140dSpatrick 88097a140dSpatrick /// Return a textual representation of the trait property \p Kind with selector 89097a140dSpatrick /// and set name included. 90097a140dSpatrick StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); 91097a140dSpatrick 92097a140dSpatrick /// Return a string listing all trait sets. 93097a140dSpatrick std::string listOpenMPContextTraitSets(); 94097a140dSpatrick 95097a140dSpatrick /// Return a string listing all trait selectors for \p Set. 96097a140dSpatrick std::string listOpenMPContextTraitSelectors(TraitSet Set); 97097a140dSpatrick 98097a140dSpatrick /// Return a string listing all trait properties for \p Set and \p Selector. 99097a140dSpatrick std::string listOpenMPContextTraitProperties(TraitSet Set, 100097a140dSpatrick TraitSelector Selector); 101097a140dSpatrick ///} 102097a140dSpatrick 103097a140dSpatrick /// Return true if \p Selector can be nested in \p Set. Also sets 104097a140dSpatrick /// \p AllowsTraitScore and \p RequiresProperty to true/false if the user can 105097a140dSpatrick /// specify a score for properties in \p Selector and if the \p Selector 106097a140dSpatrick /// requires at least one property. 107097a140dSpatrick bool isValidTraitSelectorForTraitSet(TraitSelector Selector, TraitSet Set, 108097a140dSpatrick bool &AllowsTraitScore, 109097a140dSpatrick bool &RequiresProperty); 110097a140dSpatrick 111097a140dSpatrick /// Return true if \p Property can be nested in \p Selector and \p Set. 112097a140dSpatrick bool isValidTraitPropertyForTraitSetAndSelector(TraitProperty Property, 113097a140dSpatrick TraitSelector Selector, 114097a140dSpatrick TraitSet Set); 115097a140dSpatrick 116097a140dSpatrick /// Variant match information describes the required traits and how they are 117097a140dSpatrick /// scored (via the ScoresMap). In addition, the required consturct nesting is 118097a140dSpatrick /// decribed as well. 119097a140dSpatrick struct VariantMatchInfo { 12073471bf0Spatrick /// Add the trait \p Property to the required trait set. \p RawString is the 12173471bf0Spatrick /// string we parsed and derived \p Property from. If \p Score is not null, it 12273471bf0Spatrick /// recorded as well. If \p Property is in the `construct` set it is recorded 12373471bf0Spatrick /// in-order in the ConstructTraits as well. 12473471bf0Spatrick void addTrait(TraitProperty Property, StringRef RawString, 12573471bf0Spatrick APInt *Score = nullptr) { 12673471bf0Spatrick addTrait(getOpenMPContextTraitSetForProperty(Property), Property, RawString, 12773471bf0Spatrick Score); 128097a140dSpatrick } 129097a140dSpatrick /// Add the trait \p Property which is in set \p Set to the required trait 13073471bf0Spatrick /// set. \p RawString is the string we parsed and derived \p Property from. If 13173471bf0Spatrick /// \p Score is not null, it recorded as well. If \p Set is the `construct` 13273471bf0Spatrick /// set it is recorded in-order in the ConstructTraits as well. 13373471bf0Spatrick void addTrait(TraitSet Set, TraitProperty Property, StringRef RawString, 13473471bf0Spatrick APInt *Score = nullptr) { 135097a140dSpatrick if (Score) 136097a140dSpatrick ScoreMap[Property] = *Score; 13773471bf0Spatrick 13873471bf0Spatrick // Special handling for `device={isa(...)}` as we do not match the enum but 13973471bf0Spatrick // the raw string. 14073471bf0Spatrick if (Property == TraitProperty::device_isa___ANY) 14173471bf0Spatrick ISATraits.push_back(RawString); 14273471bf0Spatrick 143097a140dSpatrick RequiredTraits.set(unsigned(Property)); 144097a140dSpatrick if (Set == TraitSet::construct) 145097a140dSpatrick ConstructTraits.push_back(Property); 146097a140dSpatrick } 147097a140dSpatrick 148097a140dSpatrick BitVector RequiredTraits = BitVector(unsigned(TraitProperty::Last) + 1); 14973471bf0Spatrick SmallVector<StringRef, 8> ISATraits; 150097a140dSpatrick SmallVector<TraitProperty, 8> ConstructTraits; 151097a140dSpatrick SmallDenseMap<TraitProperty, APInt> ScoreMap; 152097a140dSpatrick }; 153097a140dSpatrick 154097a140dSpatrick /// The context for a source location is made up of active property traits, 155097a140dSpatrick /// e.g., device={kind(host)}, and constructs traits which describe the nesting 156097a140dSpatrick /// in OpenMP constructs at the location. 157097a140dSpatrick struct OMPContext { 158097a140dSpatrick OMPContext(bool IsDeviceCompilation, Triple TargetTriple); 15973471bf0Spatrick virtual ~OMPContext() = default; 160097a140dSpatrick addTraitOMPContext161097a140dSpatrick void addTrait(TraitProperty Property) { 162097a140dSpatrick addTrait(getOpenMPContextTraitSetForProperty(Property), Property); 163097a140dSpatrick } addTraitOMPContext164097a140dSpatrick void addTrait(TraitSet Set, TraitProperty Property) { 165097a140dSpatrick ActiveTraits.set(unsigned(Property)); 166097a140dSpatrick if (Set == TraitSet::construct) 167097a140dSpatrick ConstructTraits.push_back(Property); 168097a140dSpatrick } 169097a140dSpatrick 17073471bf0Spatrick /// Hook for users to check if an ISA trait matches. The trait is described as 17173471bf0Spatrick /// the string that got parsed and it depends on the target and context if 17273471bf0Spatrick /// this matches or not. matchesISATraitOMPContext17373471bf0Spatrick virtual bool matchesISATrait(StringRef) const { return false; } 17473471bf0Spatrick 175097a140dSpatrick BitVector ActiveTraits = BitVector(unsigned(TraitProperty::Last) + 1); 176097a140dSpatrick SmallVector<TraitProperty, 8> ConstructTraits; 177097a140dSpatrick }; 178097a140dSpatrick 179097a140dSpatrick /// Return true if \p VMI is applicable in \p Ctx, that is, all traits required 180097a140dSpatrick /// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is 181097a140dSpatrick /// true, only the device selector set, if present, are checked. Note that we 182097a140dSpatrick /// still honor extension traits provided by the user. 183097a140dSpatrick bool isVariantApplicableInContext(const VariantMatchInfo &VMI, 184097a140dSpatrick const OMPContext &Ctx, 185097a140dSpatrick bool DeviceSetOnly = false); 186097a140dSpatrick 187097a140dSpatrick /// Return the index (into \p VMIs) of the variant with the highest score 188097a140dSpatrick /// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext. 189097a140dSpatrick int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs, 190097a140dSpatrick const OMPContext &Ctx); 191097a140dSpatrick 192097a140dSpatrick } // namespace omp 193097a140dSpatrick 194097a140dSpatrick template <> struct DenseMapInfo<omp::TraitProperty> { 195097a140dSpatrick static inline omp::TraitProperty getEmptyKey() { 196097a140dSpatrick return omp::TraitProperty(-1); 197097a140dSpatrick } 198097a140dSpatrick static inline omp::TraitProperty getTombstoneKey() { 199097a140dSpatrick return omp::TraitProperty(-2); 200097a140dSpatrick } 201097a140dSpatrick static unsigned getHashValue(omp::TraitProperty val) { 202097a140dSpatrick return std::hash<unsigned>{}(unsigned(val)); 203097a140dSpatrick } 204097a140dSpatrick static bool isEqual(omp::TraitProperty LHS, omp::TraitProperty RHS) { 205097a140dSpatrick return LHS == RHS; 206097a140dSpatrick } 207097a140dSpatrick }; 208097a140dSpatrick 209097a140dSpatrick } // end namespace llvm 21073471bf0Spatrick #endif // LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 211