1c953409fSJohannes Doerfert //===- OpenMP/OMPContext.h ----- OpenMP context helper functions - C++ -*-===// 2c953409fSJohannes Doerfert // 3c953409fSJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4c953409fSJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5c953409fSJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6c953409fSJohannes Doerfert // 7c953409fSJohannes Doerfert //===----------------------------------------------------------------------===// 8c953409fSJohannes Doerfert /// \file 9c953409fSJohannes Doerfert /// 10c953409fSJohannes Doerfert /// This file provides helper functions and classes to deal with OpenMP 11c953409fSJohannes Doerfert /// contexts as used by `[begin/end] declare variant` and `metadirective`. 12c953409fSJohannes Doerfert /// 13c953409fSJohannes Doerfert //===----------------------------------------------------------------------===// 14c953409fSJohannes Doerfert 15aa5c09beSKazu Hirata #ifndef LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 16aa5c09beSKazu Hirata #define LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 17c953409fSJohannes Doerfert 18*ed98c1b3Sserge-sans-paille #include "llvm/ADT/APInt.h" 196b57d7f5SJohannes Doerfert #include "llvm/ADT/BitVector.h" 20*ed98c1b3Sserge-sans-paille #include "llvm/ADT/DenseMap.h" 21*ed98c1b3Sserge-sans-paille #include "llvm/ADT/DenseMapInfo.h" 22c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPConstants.h" 23c953409fSJohannes Doerfert 24c953409fSJohannes Doerfert namespace llvm { 25*ed98c1b3Sserge-sans-paille class Triple; 26c953409fSJohannes Doerfert namespace omp { 27c953409fSJohannes Doerfert 28c953409fSJohannes Doerfert /// OpenMP Context related IDs and helpers 29c953409fSJohannes Doerfert /// 30c953409fSJohannes Doerfert ///{ 31c953409fSJohannes Doerfert 32c953409fSJohannes Doerfert /// IDs for all OpenMP context selector trait sets (construct/device/...). 33c953409fSJohannes Doerfert enum class TraitSet { 34c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, ...) Enum, 35c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 36c953409fSJohannes Doerfert }; 37c953409fSJohannes Doerfert 38c953409fSJohannes Doerfert /// IDs for all OpenMP context selector trait (device={kind/isa...}/...). 39c953409fSJohannes Doerfert enum class TraitSelector { 40c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, ...) Enum, 41c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 42c953409fSJohannes Doerfert }; 43c953409fSJohannes Doerfert 44c953409fSJohannes Doerfert /// IDs for all OpenMP context trait properties (host/gpu/bsc/llvm/...) 45c953409fSJohannes Doerfert enum class TraitProperty { 46c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, ...) Enum, 476b57d7f5SJohannes Doerfert #define OMP_LAST_TRAIT_PROPERTY(Enum) Last = Enum 48c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 49c953409fSJohannes Doerfert }; 50c953409fSJohannes Doerfert 51c953409fSJohannes Doerfert /// Parse \p Str and return the trait set it matches or TraitSet::invalid. 52c953409fSJohannes Doerfert TraitSet getOpenMPContextTraitSetKind(StringRef Str); 53c953409fSJohannes Doerfert 541228d42dSJohannes Doerfert /// Return the trait set for which \p Selector is a selector. 551228d42dSJohannes Doerfert TraitSet getOpenMPContextTraitSetForSelector(TraitSelector Selector); 561228d42dSJohannes Doerfert 57c953409fSJohannes Doerfert /// Return the trait set for which \p Property is a property. 58c953409fSJohannes Doerfert TraitSet getOpenMPContextTraitSetForProperty(TraitProperty Property); 59c953409fSJohannes Doerfert 60c953409fSJohannes Doerfert /// Return a textual representation of the trait set \p Kind. 61c953409fSJohannes Doerfert StringRef getOpenMPContextTraitSetName(TraitSet Kind); 62c953409fSJohannes Doerfert 63c953409fSJohannes Doerfert /// Parse \p Str and return the trait set it matches or 64c953409fSJohannes Doerfert /// TraitSelector::invalid. 65c953409fSJohannes Doerfert TraitSelector getOpenMPContextTraitSelectorKind(StringRef Str); 66c953409fSJohannes Doerfert 67c953409fSJohannes Doerfert /// Return the trait selector for which \p Property is a property. 68c953409fSJohannes Doerfert TraitSelector getOpenMPContextTraitSelectorForProperty(TraitProperty Property); 69c953409fSJohannes Doerfert 70c953409fSJohannes Doerfert /// Return a textual representation of the trait selector \p Kind. 71c953409fSJohannes Doerfert StringRef getOpenMPContextTraitSelectorName(TraitSelector Kind); 72c953409fSJohannes Doerfert 73ee05167cSJohannes Doerfert /// Parse \p Str and return the trait property it matches in the set \p Set and 74ee05167cSJohannes Doerfert /// selector \p Selector or TraitProperty::invalid. 75ee05167cSJohannes Doerfert TraitProperty getOpenMPContextTraitPropertyKind(TraitSet Set, 76ee05167cSJohannes Doerfert TraitSelector Selector, 77ee05167cSJohannes Doerfert StringRef Str); 78c953409fSJohannes Doerfert 79c953409fSJohannes Doerfert /// Return the trait property for a singleton selector \p Selector. 80c953409fSJohannes Doerfert TraitProperty getOpenMPContextTraitPropertyForSelector(TraitSelector Selector); 81c953409fSJohannes Doerfert 82ee05167cSJohannes Doerfert /// Return a textual representation of the trait property \p Kind, which might 83ee05167cSJohannes Doerfert /// be the raw string we parsed (\p RawString) if we do not translate the 84ee05167cSJohannes Doerfert /// property into a (distinct) enum. 85ee05167cSJohannes Doerfert StringRef getOpenMPContextTraitPropertyName(TraitProperty Kind, 86ee05167cSJohannes Doerfert StringRef RawString); 87c953409fSJohannes Doerfert 88c953409fSJohannes Doerfert /// Return a textual representation of the trait property \p Kind with selector 89c953409fSJohannes Doerfert /// and set name included. 90c953409fSJohannes Doerfert StringRef getOpenMPContextTraitPropertyFullName(TraitProperty Kind); 911228d42dSJohannes Doerfert 921228d42dSJohannes Doerfert /// Return a string listing all trait sets. 931228d42dSJohannes Doerfert std::string listOpenMPContextTraitSets(); 941228d42dSJohannes Doerfert 951228d42dSJohannes Doerfert /// Return a string listing all trait selectors for \p Set. 961228d42dSJohannes Doerfert std::string listOpenMPContextTraitSelectors(TraitSet Set); 971228d42dSJohannes Doerfert 981228d42dSJohannes Doerfert /// Return a string listing all trait properties for \p Set and \p Selector. 991228d42dSJohannes Doerfert std::string listOpenMPContextTraitProperties(TraitSet Set, 1001228d42dSJohannes Doerfert TraitSelector Selector); 101c953409fSJohannes Doerfert ///} 102c953409fSJohannes Doerfert 103c953409fSJohannes Doerfert /// Return true if \p Selector can be nested in \p Set. Also sets 104c953409fSJohannes Doerfert /// \p AllowsTraitScore and \p RequiresProperty to true/false if the user can 105c953409fSJohannes Doerfert /// specify a score for properties in \p Selector and if the \p Selector 106c953409fSJohannes Doerfert /// requires at least one property. 107c953409fSJohannes Doerfert bool isValidTraitSelectorForTraitSet(TraitSelector Selector, TraitSet Set, 108c953409fSJohannes Doerfert bool &AllowsTraitScore, 109c953409fSJohannes Doerfert bool &RequiresProperty); 110c953409fSJohannes Doerfert 111c953409fSJohannes Doerfert /// Return true if \p Property can be nested in \p Selector and \p Set. 112c953409fSJohannes Doerfert bool isValidTraitPropertyForTraitSetAndSelector(TraitProperty Property, 113c953409fSJohannes Doerfert TraitSelector Selector, 114c953409fSJohannes Doerfert TraitSet Set); 115c953409fSJohannes Doerfert 116c953409fSJohannes Doerfert /// Variant match information describes the required traits and how they are 117c953409fSJohannes Doerfert /// scored (via the ScoresMap). In addition, the required consturct nesting is 118c953409fSJohannes Doerfert /// decribed as well. 119c953409fSJohannes Doerfert struct VariantMatchInfo { 120ee05167cSJohannes Doerfert /// Add the trait \p Property to the required trait set. \p RawString is the 121ee05167cSJohannes Doerfert /// string we parsed and derived \p Property from. If \p Score is not null, it 122ee05167cSJohannes Doerfert /// recorded as well. If \p Property is in the `construct` set it is recorded 123ee05167cSJohannes Doerfert /// in-order in the ConstructTraits as well. 124ee05167cSJohannes Doerfert void addTrait(TraitProperty Property, StringRef RawString, 125ee05167cSJohannes Doerfert APInt *Score = nullptr) { 126ee05167cSJohannes Doerfert addTrait(getOpenMPContextTraitSetForProperty(Property), Property, RawString, 127ee05167cSJohannes Doerfert Score); 128c953409fSJohannes Doerfert } 129c953409fSJohannes Doerfert /// Add the trait \p Property which is in set \p Set to the required trait 130ee05167cSJohannes Doerfert /// set. \p RawString is the string we parsed and derived \p Property from. If 131ee05167cSJohannes Doerfert /// \p Score is not null, it recorded as well. If \p Set is the `construct` 132ee05167cSJohannes Doerfert /// set it is recorded in-order in the ConstructTraits as well. 133ee05167cSJohannes Doerfert void addTrait(TraitSet Set, TraitProperty Property, StringRef RawString, 134ee05167cSJohannes Doerfert APInt *Score = nullptr) { 135c953409fSJohannes Doerfert if (Score) 136c953409fSJohannes Doerfert ScoreMap[Property] = *Score; 137ee05167cSJohannes Doerfert 138ee05167cSJohannes Doerfert // Special handling for `device={isa(...)}` as we do not match the enum but 139ee05167cSJohannes Doerfert // the raw string. 140ee05167cSJohannes Doerfert if (Property == TraitProperty::device_isa___ANY) 141ee05167cSJohannes Doerfert ISATraits.push_back(RawString); 142ee05167cSJohannes Doerfert 1436b57d7f5SJohannes Doerfert RequiredTraits.set(unsigned(Property)); 144c953409fSJohannes Doerfert if (Set == TraitSet::construct) 145c953409fSJohannes Doerfert ConstructTraits.push_back(Property); 146c953409fSJohannes Doerfert } 147c953409fSJohannes Doerfert 1486b57d7f5SJohannes Doerfert BitVector RequiredTraits = BitVector(unsigned(TraitProperty::Last) + 1); 149ee05167cSJohannes Doerfert SmallVector<StringRef, 8> ISATraits; 150c953409fSJohannes Doerfert SmallVector<TraitProperty, 8> ConstructTraits; 151c953409fSJohannes Doerfert SmallDenseMap<TraitProperty, APInt> ScoreMap; 152c953409fSJohannes Doerfert }; 153c953409fSJohannes Doerfert 154c953409fSJohannes Doerfert /// The context for a source location is made up of active property traits, 155c953409fSJohannes Doerfert /// e.g., device={kind(host)}, and constructs traits which describe the nesting 156c953409fSJohannes Doerfert /// in OpenMP constructs at the location. 157c953409fSJohannes Doerfert struct OMPContext { 158c953409fSJohannes Doerfert OMPContext(bool IsDeviceCompilation, Triple TargetTriple); 159ee05167cSJohannes Doerfert virtual ~OMPContext() = default; 160c953409fSJohannes Doerfert addTraitOMPContext161c953409fSJohannes Doerfert void addTrait(TraitProperty Property) { 162c953409fSJohannes Doerfert addTrait(getOpenMPContextTraitSetForProperty(Property), Property); 163c953409fSJohannes Doerfert } addTraitOMPContext164c953409fSJohannes Doerfert void addTrait(TraitSet Set, TraitProperty Property) { 1656b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(Property)); 166c953409fSJohannes Doerfert if (Set == TraitSet::construct) 167c953409fSJohannes Doerfert ConstructTraits.push_back(Property); 168c953409fSJohannes Doerfert } 169c953409fSJohannes Doerfert 170ee05167cSJohannes Doerfert /// Hook for users to check if an ISA trait matches. The trait is described as 171ee05167cSJohannes Doerfert /// the string that got parsed and it depends on the target and context if 172ee05167cSJohannes Doerfert /// this matches or not. matchesISATraitOMPContext173ee05167cSJohannes Doerfert virtual bool matchesISATrait(StringRef) const { return false; } 174ee05167cSJohannes Doerfert 1756b57d7f5SJohannes Doerfert BitVector ActiveTraits = BitVector(unsigned(TraitProperty::Last) + 1); 176c953409fSJohannes Doerfert SmallVector<TraitProperty, 8> ConstructTraits; 177c953409fSJohannes Doerfert }; 178c953409fSJohannes Doerfert 179c953409fSJohannes Doerfert /// Return true if \p VMI is applicable in \p Ctx, that is, all traits required 180a19eb1deSJohannes Doerfert /// by \p VMI are available in the OpenMP context \p Ctx. If \p DeviceSetOnly is 181a19eb1deSJohannes Doerfert /// true, only the device selector set, if present, are checked. Note that we 182a19eb1deSJohannes Doerfert /// still honor extension traits provided by the user. 183c953409fSJohannes Doerfert bool isVariantApplicableInContext(const VariantMatchInfo &VMI, 184a19eb1deSJohannes Doerfert const OMPContext &Ctx, 185a19eb1deSJohannes Doerfert bool DeviceSetOnly = false); 186c953409fSJohannes Doerfert 187c953409fSJohannes Doerfert /// Return the index (into \p VMIs) of the variant with the highest score 188c953409fSJohannes Doerfert /// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext. 189c953409fSJohannes Doerfert int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs, 190c953409fSJohannes Doerfert const OMPContext &Ctx); 191c953409fSJohannes Doerfert 192c953409fSJohannes Doerfert } // namespace omp 193c953409fSJohannes Doerfert 194c953409fSJohannes Doerfert template <> struct DenseMapInfo<omp::TraitProperty> { 195c953409fSJohannes Doerfert static inline omp::TraitProperty getEmptyKey() { 196c953409fSJohannes Doerfert return omp::TraitProperty(-1); 197c953409fSJohannes Doerfert } 198c953409fSJohannes Doerfert static inline omp::TraitProperty getTombstoneKey() { 199c953409fSJohannes Doerfert return omp::TraitProperty(-2); 200c953409fSJohannes Doerfert } 201c953409fSJohannes Doerfert static unsigned getHashValue(omp::TraitProperty val) { 202c953409fSJohannes Doerfert return std::hash<unsigned>{}(unsigned(val)); 203c953409fSJohannes Doerfert } 204c953409fSJohannes Doerfert static bool isEqual(omp::TraitProperty LHS, omp::TraitProperty RHS) { 205c953409fSJohannes Doerfert return LHS == RHS; 206c953409fSJohannes Doerfert } 207c953409fSJohannes Doerfert }; 208c953409fSJohannes Doerfert 209c953409fSJohannes Doerfert } // end namespace llvm 210aa5c09beSKazu Hirata #endif // LLVM_FRONTEND_OPENMP_OMPCONTEXT_H 211