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