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