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