xref: /llvm-project/llvm/include/llvm/Frontend/OpenMP/OMPContext.h (revision ed98c1b37661b0795a5e34517941485f0f0688d1)
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