15ffd83dbSDimitry Andric //===- OpenMP/OMPContext.h ----- OpenMP context helper functions - C++ -*-===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric /// \file 95ffd83dbSDimitry Andric /// 105ffd83dbSDimitry Andric /// This file provides helper functions and classes to deal with OpenMP 115ffd83dbSDimitry Andric /// contexts as used by `[begin/end] declare variant` and `metadirective`. 125ffd83dbSDimitry Andric /// 135ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 145ffd83dbSDimitry Andric 15fe6060f1SDimitry Andric #ifndef LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 16fe6060f1SDimitry Andric #define LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 175ffd83dbSDimitry Andric 18*81ad6265SDimitry Andric #include "llvm/ADT/APInt.h" 195ffd83dbSDimitry Andric #include "llvm/ADT/BitVector.h" 20*81ad6265SDimitry Andric #include "llvm/ADT/DenseMap.h" 21*81ad6265SDimitry Andric #include "llvm/ADT/DenseMapInfo.h" 225ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPConstants.h" 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric namespace llvm { 25*81ad6265SDimitry Andric class Triple; 265ffd83dbSDimitry Andric namespace omp { 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric /// OpenMP Context related IDs and helpers 295ffd83dbSDimitry Andric /// 305ffd83dbSDimitry Andric ///{ 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric /// IDs for all OpenMP context selector trait sets (construct/device/...). 335ffd83dbSDimitry Andric enum class TraitSet { 345ffd83dbSDimitry Andric #define OMP_TRAIT_SET(Enum, ...) Enum, 355ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPKinds.def" 365ffd83dbSDimitry Andric }; 375ffd83dbSDimitry Andric 385ffd83dbSDimitry Andric /// IDs for all OpenMP context selector trait (device={kind/isa...}/...). 395ffd83dbSDimitry Andric enum class TraitSelector { 405ffd83dbSDimitry Andric #define OMP_TRAIT_SELECTOR(Enum, ...) Enum, 415ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPKinds.def" 425ffd83dbSDimitry Andric }; 435ffd83dbSDimitry Andric 445ffd83dbSDimitry Andric /// IDs for all OpenMP context trait properties (host/gpu/bsc/llvm/...) 455ffd83dbSDimitry Andric enum class TraitProperty { 465ffd83dbSDimitry Andric #define OMP_TRAIT_PROPERTY(Enum, ...) Enum, 475ffd83dbSDimitry Andric #define OMP_LAST_TRAIT_PROPERTY(Enum) Last = Enum 485ffd83dbSDimitry Andric #include "llvm/Frontend/OpenMP/OMPKinds.def" 495ffd83dbSDimitry Andric }; 505ffd83dbSDimitry Andric 515ffd83dbSDimitry Andric /// Parse \p Str and return the trait set it matches or TraitSet::invalid. 525ffd83dbSDimitry Andric TraitSet getOpenMPContextTraitSetKind(StringRef Str); 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric /// Return the trait set for which \p Selector is a selector. 555ffd83dbSDimitry Andric TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric /// Return the trait set for which \p Property is a property. 585ffd83dbSDimitry Andric TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); 595ffd83dbSDimitry Andric 605ffd83dbSDimitry Andric /// Return a textual representation of the trait set \p Kind. 615ffd83dbSDimitry Andric StringRef getOpenMPContextTraitSetName(TraitSet Kind); 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric /// Parse \p Str and return the trait set it matches or 645ffd83dbSDimitry Andric /// TraitSelector::invalid. 655ffd83dbSDimitry Andric TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str); 665ffd83dbSDimitry Andric 675ffd83dbSDimitry Andric /// Return the trait selector for which \p Property is a property. 685ffd83dbSDimitry Andric TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property); 695ffd83dbSDimitry Andric 705ffd83dbSDimitry Andric /// Return a textual representation of the trait selector \p Kind. 715ffd83dbSDimitry Andric StringRef getOpenMPContextTraitSelectorName(TraitSelector Kind); 725ffd83dbSDimitry Andric 73e8d8bef9SDimitry Andric /// Parse \p Str and return the trait property it matches in the set \p Set and 74e8d8bef9SDimitry Andric /// selector \p Selector or TraitProperty::invalid. 75e8d8bef9SDimitry Andric TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, 76e8d8bef9SDimitry Andric TraitSelector Selector, 77e8d8bef9SDimitry Andric StringRef Str); 785ffd83dbSDimitry Andric 795ffd83dbSDimitry Andric /// Return the trait property for a singleton selector \p Selector. 805ffd83dbSDimitry Andric TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector); 815ffd83dbSDimitry Andric 82e8d8bef9SDimitry Andric /// Return a textual representation of the trait property \p Kind, which might 83e8d8bef9SDimitry Andric /// be the raw string we parsed (\p RawString) if we do not translate the 84e8d8bef9SDimitry Andric /// property into a (distinct) enum. 85e8d8bef9SDimitry Andric StringRef getOpenMPContextTraitPropertyName(TraitProperty Kind, 86e8d8bef9SDimitry Andric StringRef RawString); 875ffd83dbSDimitry Andric 885ffd83dbSDimitry Andric /// Return a textual representation of the trait property \p Kind with selector 895ffd83dbSDimitry Andric /// and set name included. 905ffd83dbSDimitry Andric StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); 915ffd83dbSDimitry Andric 925ffd83dbSDimitry Andric /// Return a string listing all trait sets. 935ffd83dbSDimitry Andric std::string listOpenMPContextTraitSets(); 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric /// Return a string listing all trait selectors for \p Set. 965ffd83dbSDimitry Andric std::string listOpenMPContextTraitSelectors(TraitSet Set); 975ffd83dbSDimitry Andric 985ffd83dbSDimitry Andric /// Return a string listing all trait properties for \p Set and \p Selector. 995ffd83dbSDimitry Andric std::string listOpenMPContextTraitProperties(TraitSet Set, 1005ffd83dbSDimitry Andric TraitSelector Selector); 1015ffd83dbSDimitry Andric ///} 1025ffd83dbSDimitry Andric 1035ffd83dbSDimitry Andric /// Return true if \p Selector can be nested in \p Set. Also sets 1045ffd83dbSDimitry Andric /// \p AllowsTraitScore and \p RequiresProperty to true/false if the user can 1055ffd83dbSDimitry Andric /// specify a score for properties in \p Selector and if the \p Selector 1065ffd83dbSDimitry Andric /// requires at least one property. 1075ffd83dbSDimitry Andric bool isValidTraitSelectorForTraitSet(TraitSelector Selector, TraitSet Set, 1085ffd83dbSDimitry Andric bool &AllowsTraitScore, 1095ffd83dbSDimitry Andric bool &RequiresProperty); 1105ffd83dbSDimitry Andric 1115ffd83dbSDimitry Andric /// Return true if \p Property can be nested in \p Selector and \p Set. 1125ffd83dbSDimitry Andric bool isValidTraitPropertyForTraitSetAndSelector(TraitProperty Property, 1135ffd83dbSDimitry Andric TraitSelector Selector, 1145ffd83dbSDimitry Andric TraitSet Set); 1155ffd83dbSDimitry Andric 1165ffd83dbSDimitry Andric /// Variant match information describes the required traits and how they are 1175ffd83dbSDimitry Andric /// scored (via the ScoresMap). In addition, the required consturct nesting is 1185ffd83dbSDimitry Andric /// decribed as well. 1195ffd83dbSDimitry Andric struct VariantMatchInfo { 120e8d8bef9SDimitry Andric /// Add the trait \p Property to the required trait set. \p RawString is the 121e8d8bef9SDimitry Andric /// string we parsed and derived \p Property from. If \p Score is not null, it 122e8d8bef9SDimitry Andric /// recorded as well. If \p Property is in the `construct` set it is recorded 123e8d8bef9SDimitry Andric /// in-order in the ConstructTraits as well. 124e8d8bef9SDimitry Andric void addTrait(TraitProperty Property, StringRef RawString, 125e8d8bef9SDimitry Andric APInt *Score = nullptr) { 126e8d8bef9SDimitry Andric addTrait(getOpenMPContextTraitSetForProperty(Property), Property, RawString, 127e8d8bef9SDimitry Andric Score); 1285ffd83dbSDimitry Andric } 1295ffd83dbSDimitry Andric /// Add the trait \p Property which is in set \p Set to the required trait 130e8d8bef9SDimitry Andric /// set. \p RawString is the string we parsed and derived \p Property from. If 131e8d8bef9SDimitry Andric /// \p Score is not null, it recorded as well. If \p Set is the `construct` 132e8d8bef9SDimitry Andric /// set it is recorded in-order in the ConstructTraits as well. 133e8d8bef9SDimitry Andric void addTrait(TraitSet Set, TraitProperty Property, StringRef RawString, 134e8d8bef9SDimitry Andric APInt *Score = nullptr) { 1355ffd83dbSDimitry Andric if (Score) 1365ffd83dbSDimitry Andric ScoreMap[Property] = *Score; 137e8d8bef9SDimitry Andric 138e8d8bef9SDimitry Andric // Special handling for `device={isa(...)}` as we do not match the enum but 139e8d8bef9SDimitry Andric // the raw string. 140e8d8bef9SDimitry Andric if (Property == TraitProperty::device_isa___ANY) 141e8d8bef9SDimitry Andric ISATraits.push_back(RawString); 142e8d8bef9SDimitry Andric 1435ffd83dbSDimitry Andric RequiredTraits.set(unsigned(Property)); 1445ffd83dbSDimitry Andric if (Set == TraitSet::construct) 1455ffd83dbSDimitry Andric ConstructTraits.push_back(Property); 1465ffd83dbSDimitry Andric } 1475ffd83dbSDimitry Andric 1485ffd83dbSDimitry Andric BitVector RequiredTraits = BitVector(unsigned(TraitProperty::Last) + 1); 149e8d8bef9SDimitry Andric SmallVector<StringRef, 8> ISATraits; 1505ffd83dbSDimitry Andric SmallVector<TraitProperty, 8> ConstructTraits; 1515ffd83dbSDimitry Andric SmallDenseMap<TraitProperty, APInt> ScoreMap; 1525ffd83dbSDimitry Andric }; 1535ffd83dbSDimitry Andric 1545ffd83dbSDimitry Andric /// The context for a source location is made up of active property traits, 1555ffd83dbSDimitry Andric /// e.g., device={kind(host)}, and constructs traits which describe the nesting 1565ffd83dbSDimitry Andric /// in OpenMP constructs at the location. 1575ffd83dbSDimitry Andric struct OMPContext { 1585ffd83dbSDimitry Andric OMPContext(bool IsDeviceCompilation, Triple TargetTriple); 159e8d8bef9SDimitry Andric virtual ~OMPContext() = default; 1605ffd83dbSDimitry Andric addTraitOMPContext1615ffd83dbSDimitry Andric void addTrait(TraitProperty Property) { 1625ffd83dbSDimitry Andric addTrait(getOpenMPContextTraitSetForProperty(Property), Property); 1635ffd83dbSDimitry Andric } addTraitOMPContext1645ffd83dbSDimitry Andric void addTrait(TraitSet Set, TraitProperty Property) { 1655ffd83dbSDimitry Andric ActiveTraits.set(unsigned(Property)); 1665ffd83dbSDimitry Andric if (Set == TraitSet::construct) 1675ffd83dbSDimitry Andric ConstructTraits.push_back(Property); 1685ffd83dbSDimitry Andric } 1695ffd83dbSDimitry Andric 170e8d8bef9SDimitry Andric /// Hook for users to check if an ISA trait matches. The trait is described as 171e8d8bef9SDimitry Andric /// the string that got parsed and it depends on the target and context if 172e8d8bef9SDimitry Andric /// this matches or not. matchesISATraitOMPContext173e8d8bef9SDimitry Andric virtual bool matchesISATrait(StringRef) const { return false; } 174e8d8bef9SDimitry Andric 1755ffd83dbSDimitry Andric BitVector ActiveTraits = BitVector(unsigned(TraitProperty::Last) + 1); 1765ffd83dbSDimitry Andric SmallVector<TraitProperty, 8> ConstructTraits; 1775ffd83dbSDimitry Andric }; 1785ffd83dbSDimitry Andric 1795ffd83dbSDimitry Andric /// Return true if \p VMI is applicable in \p Ctx, that is, all traits required 1805ffd83dbSDimitry Andric /// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is 1815ffd83dbSDimitry Andric /// true, only the device selector set, if present, are checked. Note that we 1825ffd83dbSDimitry Andric /// still honor extension traits provided by the user. 1835ffd83dbSDimitry Andric bool isVariantApplicableInContext(const VariantMatchInfo &VMI, 1845ffd83dbSDimitry Andric const OMPContext &Ctx, 1855ffd83dbSDimitry Andric bool DeviceSetOnly = false); 1865ffd83dbSDimitry Andric 1875ffd83dbSDimitry Andric /// Return the index (into \p VMIs) of the variant with the highest score 1885ffd83dbSDimitry Andric /// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext. 1895ffd83dbSDimitry Andric int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs, 1905ffd83dbSDimitry Andric const OMPContext &Ctx); 1915ffd83dbSDimitry Andric 1925ffd83dbSDimitry Andric } // namespace omp 1935ffd83dbSDimitry Andric 1945ffd83dbSDimitry Andric template <> struct DenseMapInfo<omp::TraitProperty> { 1955ffd83dbSDimitry Andric static inline omp::TraitProperty getEmptyKey() { 1965ffd83dbSDimitry Andric return omp::TraitProperty(-1); 1975ffd83dbSDimitry Andric } 1985ffd83dbSDimitry Andric static inline omp::TraitProperty getTombstoneKey() { 1995ffd83dbSDimitry Andric return omp::TraitProperty(-2); 2005ffd83dbSDimitry Andric } 2015ffd83dbSDimitry Andric static unsigned getHashValue(omp::TraitProperty val) { 2025ffd83dbSDimitry Andric return std::hash<unsigned>{}(unsigned(val)); 2035ffd83dbSDimitry Andric } 2045ffd83dbSDimitry Andric static bool isEqual(omp::TraitProperty LHS, omp::TraitProperty RHS) { 2055ffd83dbSDimitry Andric return LHS == RHS; 2065ffd83dbSDimitry Andric } 2075ffd83dbSDimitry Andric }; 2085ffd83dbSDimitry Andric 2095ffd83dbSDimitry Andric } // end namespace llvm 210fe6060f1SDimitry Andric #endif // LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 211