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