xref: /freebsd-src/contrib/llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPContext.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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