File: | build/llvm-toolchain-snapshot-15~++20220420111733+e13d2efed663/llvm/lib/Frontend/OpenMP/OMPContext.cpp |
Warning: | line 363, column 11 Forming reference to null pointer |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- OMPContext.cpp ------ Collection of helpers for OpenMP contexts ----===// | |||
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 implements helper functions and classes to deal with OpenMP | |||
11 | /// contexts as used by `[begin/end] declare variant` and `metadirective`. | |||
12 | /// | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "llvm/Frontend/OpenMP/OMPContext.h" | |||
16 | #include "llvm/ADT/StringRef.h" | |||
17 | #include "llvm/ADT/StringSwitch.h" | |||
18 | #include "llvm/ADT/Triple.h" | |||
19 | #include "llvm/Support/Debug.h" | |||
20 | #include "llvm/Support/raw_ostream.h" | |||
21 | ||||
22 | #define DEBUG_TYPE"openmp-ir-builder" "openmp-ir-builder" | |||
23 | ||||
24 | using namespace llvm; | |||
25 | using namespace omp; | |||
26 | ||||
27 | OMPContext::OMPContext(bool IsDeviceCompilation, Triple TargetTriple) { | |||
28 | // Add the appropriate device kind trait based on the triple and the | |||
29 | // IsDeviceCompilation flag. | |||
30 | ActiveTraits.set(unsigned(IsDeviceCompilation | |||
31 | ? TraitProperty::device_kind_nohost | |||
32 | : TraitProperty::device_kind_host)); | |||
33 | switch (TargetTriple.getArch()) { | |||
34 | case Triple::arm: | |||
35 | case Triple::armeb: | |||
36 | case Triple::aarch64: | |||
37 | case Triple::aarch64_be: | |||
38 | case Triple::aarch64_32: | |||
39 | case Triple::mips: | |||
40 | case Triple::mipsel: | |||
41 | case Triple::mips64: | |||
42 | case Triple::mips64el: | |||
43 | case Triple::ppc: | |||
44 | case Triple::ppcle: | |||
45 | case Triple::ppc64: | |||
46 | case Triple::ppc64le: | |||
47 | case Triple::x86: | |||
48 | case Triple::x86_64: | |||
49 | ActiveTraits.set(unsigned(TraitProperty::device_kind_cpu)); | |||
50 | break; | |||
51 | case Triple::amdgcn: | |||
52 | case Triple::nvptx: | |||
53 | case Triple::nvptx64: | |||
54 | ActiveTraits.set(unsigned(TraitProperty::device_kind_gpu)); | |||
55 | break; | |||
56 | default: | |||
57 | break; | |||
58 | } | |||
59 | ||||
60 | // Add the appropriate device architecture trait based on the triple. | |||
61 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
62 | if (TraitSelector::TraitSelectorEnum == TraitSelector::device_arch) { \ | |||
63 | if (TargetTriple.getArch() == TargetTriple.getArchTypeForLLVMName(Str)) \ | |||
64 | ActiveTraits.set(unsigned(TraitProperty::Enum)); \ | |||
65 | if (StringRef(Str) == StringRef("x86_64") && \ | |||
66 | TargetTriple.getArch() == Triple::x86_64) \ | |||
67 | ActiveTraits.set(unsigned(TraitProperty::Enum)); \ | |||
68 | } | |||
69 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
70 | ||||
71 | // TODO: What exactly do we want to see as device ISA trait? | |||
72 | // The discussion on the list did not seem to have come to an agreed | |||
73 | // upon solution. | |||
74 | ||||
75 | // LLVM is the "OpenMP vendor" but we could also interpret vendor as the | |||
76 | // target vendor. | |||
77 | ActiveTraits.set(unsigned(TraitProperty::implementation_vendor_llvm)); | |||
78 | ||||
79 | // The user condition true is accepted but not false. | |||
80 | ActiveTraits.set(unsigned(TraitProperty::user_condition_true)); | |||
81 | ||||
82 | // This is for sure some device. | |||
83 | ActiveTraits.set(unsigned(TraitProperty::device_kind_any)); | |||
84 | ||||
85 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
86 | dbgs() << "[" << DEBUG_TYPEdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
87 | << "] New OpenMP context with the following properties:\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
88 | for (unsigned Bit : ActiveTraits.set_bits()) {do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
89 | TraitProperty Property = TraitProperty(Bit);do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
90 | dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
91 | << "\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
92 | }do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false) | |||
93 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { dbgs() << "[" << "openmp-ir-builder" << "] New OpenMP context with the following properties:\n" ; for (unsigned Bit : ActiveTraits.set_bits()) { TraitProperty Property = TraitProperty(Bit); dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) << "\n" ; } }; } } while (false); | |||
94 | } | |||
95 | ||||
96 | /// Return true if \p C0 is a subset of \p C1. Note that both arrays are | |||
97 | /// expected to be sorted. | |||
98 | template <typename T> static bool isSubset(ArrayRef<T> C0, ArrayRef<T> C1) { | |||
99 | #ifdef EXPENSIVE_CHECKS | |||
100 | assert(llvm::is_sorted(C0) && llvm::is_sorted(C1) &&(static_cast <bool> (llvm::is_sorted(C0) && llvm ::is_sorted(C1) && "Expected sorted arrays!") ? void ( 0) : __assert_fail ("llvm::is_sorted(C0) && llvm::is_sorted(C1) && \"Expected sorted arrays!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 101, __extension__ __PRETTY_FUNCTION__)) | |||
101 | "Expected sorted arrays!")(static_cast <bool> (llvm::is_sorted(C0) && llvm ::is_sorted(C1) && "Expected sorted arrays!") ? void ( 0) : __assert_fail ("llvm::is_sorted(C0) && llvm::is_sorted(C1) && \"Expected sorted arrays!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 101, __extension__ __PRETTY_FUNCTION__)); | |||
102 | #endif | |||
103 | if (C0.size() > C1.size()) | |||
104 | return false; | |||
105 | auto It0 = C0.begin(), End0 = C0.end(); | |||
106 | auto It1 = C1.begin(), End1 = C1.end(); | |||
107 | while (It0 != End0) { | |||
108 | if (It1 == End1) | |||
109 | return false; | |||
110 | if (*It0 == *It1) { | |||
111 | ++It0; | |||
112 | ++It1; | |||
113 | continue; | |||
114 | } | |||
115 | ++It0; | |||
116 | } | |||
117 | return true; | |||
118 | } | |||
119 | ||||
120 | /// Return true if \p C0 is a strict subset of \p C1. Note that both arrays are | |||
121 | /// expected to be sorted. | |||
122 | template <typename T> | |||
123 | static bool isStrictSubset(ArrayRef<T> C0, ArrayRef<T> C1) { | |||
124 | if (C0.size() >= C1.size()) | |||
125 | return false; | |||
126 | return isSubset<T>(C0, C1); | |||
127 | } | |||
128 | ||||
129 | static bool isStrictSubset(const VariantMatchInfo &VMI0, | |||
130 | const VariantMatchInfo &VMI1) { | |||
131 | // If all required traits are a strict subset and the ordered vectors storing | |||
132 | // the construct traits, we say it is a strict subset. Note that the latter | |||
133 | // relation is not required to be strict. | |||
134 | if (VMI0.RequiredTraits.count() >= VMI1.RequiredTraits.count()) | |||
135 | return false; | |||
136 | for (unsigned Bit : VMI0.RequiredTraits.set_bits()) | |||
137 | if (!VMI1.RequiredTraits.test(Bit)) | |||
138 | return false; | |||
139 | if (!isSubset<TraitProperty>(VMI0.ConstructTraits, VMI1.ConstructTraits)) | |||
140 | return false; | |||
141 | return true; | |||
142 | } | |||
143 | ||||
144 | static int isVariantApplicableInContextHelper( | |||
145 | const VariantMatchInfo &VMI, const OMPContext &Ctx, | |||
146 | SmallVectorImpl<unsigned> *ConstructMatches, bool DeviceSetOnly) { | |||
147 | ||||
148 | // The match kind determines if we need to match all traits, any of the | |||
149 | // traits, or none of the traits for it to be an applicable context. | |||
150 | enum MatchKind { MK_ALL, MK_ANY, MK_NONE }; | |||
151 | ||||
152 | MatchKind MK = MK_ALL; | |||
153 | // Determine the match kind the user wants, "all" is the default and provided | |||
154 | // to the user only for completeness. | |||
155 | if (VMI.RequiredTraits.test( | |||
156 | unsigned(TraitProperty::implementation_extension_match_any))) | |||
157 | MK = MK_ANY; | |||
158 | if (VMI.RequiredTraits.test( | |||
159 | unsigned(TraitProperty::implementation_extension_match_none))) | |||
160 | MK = MK_NONE; | |||
161 | ||||
162 | // Helper to deal with a single property that was (not) found in the OpenMP | |||
163 | // context based on the match kind selected by the user via | |||
164 | // `implementation={extensions(match_[all,any,none])}' | |||
165 | auto HandleTrait = [MK](TraitProperty Property, | |||
166 | bool WasFound) -> Optional<bool> /* Result */ { | |||
167 | // For kind "any" a single match is enough but we ignore non-matched | |||
168 | // properties. | |||
169 | if (MK == MK_ANY) { | |||
170 | if (WasFound) | |||
171 | return true; | |||
172 | return None; | |||
173 | } | |||
174 | ||||
175 | // In "all" or "none" mode we accept a matching or non-matching property | |||
176 | // respectively and move on. We are not done yet! | |||
177 | if ((WasFound && MK == MK_ALL) || (!WasFound && MK == MK_NONE)) | |||
178 | return None; | |||
179 | ||||
180 | // We missed a property, provide some debug output and indicate failure. | |||
181 | LLVM_DEBUG({do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
182 | if (MK == MK_ALL)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
183 | dbgs() << "[" << DEBUG_TYPE << "] Property "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
184 | << getOpenMPContextTraitPropertyName(Property, "")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
185 | << " was not in the OpenMP context but match kind is all.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
186 | if (MK == MK_NONE)do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
187 | dbgs() << "[" << DEBUG_TYPE << "] Property "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
188 | << getOpenMPContextTraitPropertyName(Property, "")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
189 | << " was in the OpenMP context but match kind is none.\n";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false) | |||
190 | })do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { { if (MK == MK_ALL) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName(Property, "") << " was not in the OpenMP context but match kind is all.\n" ; if (MK == MK_NONE) dbgs() << "[" << "openmp-ir-builder" << "] Property " << getOpenMPContextTraitPropertyName (Property, "") << " was in the OpenMP context but match kind is none.\n" ; }; } } while (false); | |||
191 | return false; | |||
192 | }; | |||
193 | ||||
194 | for (unsigned Bit : VMI.RequiredTraits.set_bits()) { | |||
195 | TraitProperty Property = TraitProperty(Bit); | |||
196 | if (DeviceSetOnly && | |||
197 | getOpenMPContextTraitSetForProperty(Property) != TraitSet::device) | |||
198 | continue; | |||
199 | ||||
200 | // So far all extensions are handled elsewhere, we skip them here as they | |||
201 | // are not part of the OpenMP context. | |||
202 | if (getOpenMPContextTraitSelectorForProperty(Property) == | |||
203 | TraitSelector::implementation_extension) | |||
204 | continue; | |||
205 | ||||
206 | bool IsActiveTrait = Ctx.ActiveTraits.test(unsigned(Property)); | |||
207 | ||||
208 | // We overwrite the isa trait as it is actually up to the OMPContext hook to | |||
209 | // check the raw string(s). | |||
210 | if (Property == TraitProperty::device_isa___ANY) | |||
211 | IsActiveTrait = llvm::all_of(VMI.ISATraits, [&](StringRef RawString) { | |||
212 | return Ctx.matchesISATrait(RawString); | |||
213 | }); | |||
214 | ||||
215 | Optional<bool> Result = HandleTrait(Property, IsActiveTrait); | |||
216 | if (Result.hasValue()) | |||
217 | return Result.getValue(); | |||
218 | } | |||
219 | ||||
220 | if (!DeviceSetOnly) { | |||
221 | // We could use isSubset here but we also want to record the match | |||
222 | // locations. | |||
223 | unsigned ConstructIdx = 0, NoConstructTraits = Ctx.ConstructTraits.size(); | |||
224 | for (TraitProperty Property : VMI.ConstructTraits) { | |||
225 | assert(getOpenMPContextTraitSetForProperty(Property) ==(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Variant context is ill-formed!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Variant context is ill-formed!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 227, __extension__ __PRETTY_FUNCTION__)) | |||
226 | TraitSet::construct &&(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Variant context is ill-formed!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Variant context is ill-formed!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 227, __extension__ __PRETTY_FUNCTION__)) | |||
227 | "Variant context is ill-formed!")(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Variant context is ill-formed!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Variant context is ill-formed!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 227, __extension__ __PRETTY_FUNCTION__)); | |||
228 | ||||
229 | // Verify the nesting. | |||
230 | bool FoundInOrder = false; | |||
231 | while (!FoundInOrder && ConstructIdx != NoConstructTraits) | |||
232 | FoundInOrder = (Ctx.ConstructTraits[ConstructIdx++] == Property); | |||
233 | if (ConstructMatches) | |||
234 | ConstructMatches->push_back(ConstructIdx - 1); | |||
235 | ||||
236 | Optional<bool> Result = HandleTrait(Property, FoundInOrder); | |||
237 | if (Result.hasValue()) | |||
238 | return Result.getValue(); | |||
239 | ||||
240 | if (!FoundInOrder) { | |||
241 | LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Construct property "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] Construct property " << getOpenMPContextTraitPropertyName (Property, "") << " was not nested properly.\n"; } } while (false) | |||
242 | << getOpenMPContextTraitPropertyName(Property, "")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] Construct property " << getOpenMPContextTraitPropertyName (Property, "") << " was not nested properly.\n"; } } while (false) | |||
243 | << " was not nested properly.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] Construct property " << getOpenMPContextTraitPropertyName (Property, "") << " was not nested properly.\n"; } } while (false); | |||
244 | return false; | |||
245 | } | |||
246 | ||||
247 | // TODO: Verify SIMD | |||
248 | } | |||
249 | ||||
250 | assert(isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) &&(static_cast <bool> (isSubset<TraitProperty>(VMI. ConstructTraits, Ctx.ConstructTraits) && "Broken invariant!" ) ? void (0) : __assert_fail ("isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) && \"Broken invariant!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 251, __extension__ __PRETTY_FUNCTION__)) | |||
251 | "Broken invariant!")(static_cast <bool> (isSubset<TraitProperty>(VMI. ConstructTraits, Ctx.ConstructTraits) && "Broken invariant!" ) ? void (0) : __assert_fail ("isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) && \"Broken invariant!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 251, __extension__ __PRETTY_FUNCTION__)); | |||
252 | } | |||
253 | ||||
254 | if (MK == MK_ANY) { | |||
255 | LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPEdo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] None of the properties was in the OpenMP context " "but match kind is any.\n"; } } while (false) | |||
256 | << "] None of the properties was in the OpenMP context "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] None of the properties was in the OpenMP context " "but match kind is any.\n"; } } while (false) | |||
257 | "but match kind is any.\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] None of the properties was in the OpenMP context " "but match kind is any.\n"; } } while (false); | |||
258 | return false; | |||
259 | } | |||
260 | ||||
261 | return true; | |||
262 | } | |||
263 | ||||
264 | bool llvm::omp::isVariantApplicableInContext(const VariantMatchInfo &VMI, | |||
265 | const OMPContext &Ctx, | |||
266 | bool DeviceSetOnly) { | |||
267 | return isVariantApplicableInContextHelper( | |||
268 | VMI, Ctx, /* ConstructMatches */ nullptr, DeviceSetOnly); | |||
269 | } | |||
270 | ||||
271 | static APInt getVariantMatchScore(const VariantMatchInfo &VMI, | |||
272 | const OMPContext &Ctx, | |||
273 | SmallVectorImpl<unsigned> &ConstructMatches) { | |||
274 | APInt Score(64, 1); | |||
275 | ||||
276 | unsigned NoConstructTraits = VMI.ConstructTraits.size(); | |||
277 | for (unsigned Bit : VMI.RequiredTraits.set_bits()) { | |||
278 | TraitProperty Property = TraitProperty(Bit); | |||
279 | // If there is a user score attached, use it. | |||
280 | if (VMI.ScoreMap.count(Property)) { | |||
281 | const APInt &UserScore = VMI.ScoreMap.lookup(Property); | |||
282 | assert(UserScore.uge(0) && "Expect non-negative user scores!")(static_cast <bool> (UserScore.uge(0) && "Expect non-negative user scores!" ) ? void (0) : __assert_fail ("UserScore.uge(0) && \"Expect non-negative user scores!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 282, __extension__ __PRETTY_FUNCTION__)); | |||
283 | Score += UserScore.getZExtValue(); | |||
284 | continue; | |||
285 | } | |||
286 | ||||
287 | switch (getOpenMPContextTraitSetForProperty(Property)) { | |||
288 | case TraitSet::construct: | |||
289 | // We handle the construct traits later via the VMI.ConstructTraits | |||
290 | // container. | |||
291 | continue; | |||
292 | case TraitSet::implementation: | |||
293 | // No effect on the score (implementation defined). | |||
294 | continue; | |||
295 | case TraitSet::user: | |||
296 | // No effect on the score. | |||
297 | continue; | |||
298 | case TraitSet::device: | |||
299 | // Handled separately below. | |||
300 | break; | |||
301 | case TraitSet::invalid: | |||
302 | llvm_unreachable("Unknown trait set is not to be used!")::llvm::llvm_unreachable_internal("Unknown trait set is not to be used!" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 302); | |||
303 | } | |||
304 | ||||
305 | // device={kind(any)} is "as if" no kind selector was specified. | |||
306 | if (Property == TraitProperty::device_kind_any) | |||
307 | continue; | |||
308 | ||||
309 | switch (getOpenMPContextTraitSelectorForProperty(Property)) { | |||
310 | case TraitSelector::device_kind: | |||
311 | Score += (1ULL << (NoConstructTraits + 0)); | |||
312 | continue; | |||
313 | case TraitSelector::device_arch: | |||
314 | Score += (1ULL << (NoConstructTraits + 1)); | |||
315 | continue; | |||
316 | case TraitSelector::device_isa: | |||
317 | Score += (1ULL << (NoConstructTraits + 2)); | |||
318 | continue; | |||
319 | default: | |||
320 | continue; | |||
321 | } | |||
322 | } | |||
323 | ||||
324 | unsigned ConstructIdx = 0; | |||
325 | assert(NoConstructTraits == ConstructMatches.size() &&(static_cast <bool> (NoConstructTraits == ConstructMatches .size() && "Mismatch in the construct traits!") ? void (0) : __assert_fail ("NoConstructTraits == ConstructMatches.size() && \"Mismatch in the construct traits!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 326, __extension__ __PRETTY_FUNCTION__)) | |||
326 | "Mismatch in the construct traits!")(static_cast <bool> (NoConstructTraits == ConstructMatches .size() && "Mismatch in the construct traits!") ? void (0) : __assert_fail ("NoConstructTraits == ConstructMatches.size() && \"Mismatch in the construct traits!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 326, __extension__ __PRETTY_FUNCTION__)); | |||
327 | for (TraitProperty Property : VMI.ConstructTraits) { | |||
328 | assert(getOpenMPContextTraitSetForProperty(Property) ==(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Ill-formed variant match info!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Ill-formed variant match info!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 330, __extension__ __PRETTY_FUNCTION__)) | |||
329 | TraitSet::construct &&(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Ill-formed variant match info!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Ill-formed variant match info!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 330, __extension__ __PRETTY_FUNCTION__)) | |||
330 | "Ill-formed variant match info!")(static_cast <bool> (getOpenMPContextTraitSetForProperty (Property) == TraitSet::construct && "Ill-formed variant match info!" ) ? void (0) : __assert_fail ("getOpenMPContextTraitSetForProperty(Property) == TraitSet::construct && \"Ill-formed variant match info!\"" , "llvm/lib/Frontend/OpenMP/OMPContext.cpp", 330, __extension__ __PRETTY_FUNCTION__)); | |||
331 | (void)Property; | |||
332 | // ConstructMatches is the position p - 1 and we need 2^(p-1). | |||
333 | Score += (1ULL << ConstructMatches[ConstructIdx++]); | |||
334 | } | |||
335 | ||||
336 | LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Variant has a score of " << Scoredo { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] Variant has a score of " << Score << "\n"; } } while (false) | |||
337 | << "\n")do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("openmp-ir-builder")) { dbgs() << "[" << "openmp-ir-builder" << "] Variant has a score of " << Score << "\n"; } } while (false); | |||
338 | return Score; | |||
339 | } | |||
340 | ||||
341 | int llvm::omp::getBestVariantMatchForContext( | |||
342 | const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx) { | |||
343 | ||||
344 | APInt BestScore(64, 0); | |||
345 | int BestVMIIdx = -1; | |||
346 | const VariantMatchInfo *BestVMI = nullptr; | |||
| ||||
347 | ||||
348 | for (unsigned u = 0, e = VMIs.size(); u < e; ++u) { | |||
349 | const VariantMatchInfo &VMI = VMIs[u]; | |||
350 | ||||
351 | SmallVector<unsigned, 8> ConstructMatches; | |||
352 | // If the variant is not applicable its not the best. | |||
353 | if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches, | |||
354 | /* DeviceSetOnly */ false)) | |||
355 | continue; | |||
356 | // Check if its clearly not the best. | |||
357 | APInt Score = getVariantMatchScore(VMI, Ctx, ConstructMatches); | |||
358 | if (Score.ult(BestScore)) | |||
359 | continue; | |||
360 | // Equal score need subset checks. | |||
361 | if (Score.eq(BestScore)) { | |||
362 | // Strict subset are never best. | |||
363 | if (isStrictSubset(VMI, *BestVMI)) | |||
| ||||
364 | continue; | |||
365 | // Same score and the current best is no strict subset so we keep it. | |||
366 | if (!isStrictSubset(*BestVMI, VMI)) | |||
367 | continue; | |||
368 | } | |||
369 | // New best found. | |||
370 | BestVMI = &VMI; | |||
371 | BestVMIIdx = u; | |||
372 | BestScore = Score; | |||
373 | } | |||
374 | ||||
375 | return BestVMIIdx; | |||
376 | } | |||
377 | ||||
378 | TraitSet llvm::omp::getOpenMPContextTraitSetKind(StringRef S) { | |||
379 | return StringSwitch<TraitSet>(S) | |||
380 | #define OMP_TRAIT_SET(Enum, Str) .Case(Str, TraitSet::Enum) | |||
381 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
382 | .Default(TraitSet::invalid); | |||
383 | } | |||
384 | ||||
385 | TraitSet | |||
386 | llvm::omp::getOpenMPContextTraitSetForSelector(TraitSelector Selector) { | |||
387 | switch (Selector) { | |||
388 | #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ | |||
389 | case TraitSelector::Enum: \ | |||
390 | return TraitSet::TraitSetEnum; | |||
391 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
392 | } | |||
393 | llvm_unreachable("Unknown trait selector!")::llvm::llvm_unreachable_internal("Unknown trait selector!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 393); | |||
394 | } | |||
395 | TraitSet | |||
396 | llvm::omp::getOpenMPContextTraitSetForProperty(TraitProperty Property) { | |||
397 | switch (Property) { | |||
398 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
399 | case TraitProperty::Enum: \ | |||
400 | return TraitSet::TraitSetEnum; | |||
401 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
402 | } | |||
403 | llvm_unreachable("Unknown trait set!")::llvm::llvm_unreachable_internal("Unknown trait set!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 403); | |||
404 | } | |||
405 | StringRef llvm::omp::getOpenMPContextTraitSetName(TraitSet Kind) { | |||
406 | switch (Kind) { | |||
407 | #define OMP_TRAIT_SET(Enum, Str) \ | |||
408 | case TraitSet::Enum: \ | |||
409 | return Str; | |||
410 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
411 | } | |||
412 | llvm_unreachable("Unknown trait set!")::llvm::llvm_unreachable_internal("Unknown trait set!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 412); | |||
413 | } | |||
414 | ||||
415 | TraitSelector llvm::omp::getOpenMPContextTraitSelectorKind(StringRef S) { | |||
416 | return StringSwitch<TraitSelector>(S) | |||
417 | #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ | |||
418 | .Case(Str, TraitSelector::Enum) | |||
419 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
420 | .Default(TraitSelector::invalid); | |||
421 | } | |||
422 | TraitSelector | |||
423 | llvm::omp::getOpenMPContextTraitSelectorForProperty(TraitProperty Property) { | |||
424 | switch (Property) { | |||
425 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
426 | case TraitProperty::Enum: \ | |||
427 | return TraitSelector::TraitSelectorEnum; | |||
428 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
429 | } | |||
430 | llvm_unreachable("Unknown trait set!")::llvm::llvm_unreachable_internal("Unknown trait set!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 430); | |||
431 | } | |||
432 | StringRef llvm::omp::getOpenMPContextTraitSelectorName(TraitSelector Kind) { | |||
433 | switch (Kind) { | |||
434 | #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ | |||
435 | case TraitSelector::Enum: \ | |||
436 | return Str; | |||
437 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
438 | } | |||
439 | llvm_unreachable("Unknown trait selector!")::llvm::llvm_unreachable_internal("Unknown trait selector!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 439); | |||
440 | } | |||
441 | ||||
442 | TraitProperty llvm::omp::getOpenMPContextTraitPropertyKind( | |||
443 | TraitSet Set, TraitSelector Selector, StringRef S) { | |||
444 | // Special handling for `device={isa(...)}` as we accept anything here. It is | |||
445 | // up to the target to decide if the feature is available. | |||
446 | if (Set == TraitSet::device && Selector == TraitSelector::device_isa) | |||
447 | return TraitProperty::device_isa___ANY; | |||
448 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
449 | if (Set == TraitSet::TraitSetEnum && Str == S) \ | |||
450 | return TraitProperty::Enum; | |||
451 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
452 | return TraitProperty::invalid; | |||
453 | } | |||
454 | TraitProperty | |||
455 | llvm::omp::getOpenMPContextTraitPropertyForSelector(TraitSelector Selector) { | |||
456 | return StringSwitch<TraitProperty>( | |||
457 | getOpenMPContextTraitSelectorName(Selector)) | |||
458 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
459 | .Case(Str, Selector == TraitSelector::TraitSelectorEnum \ | |||
460 | ? TraitProperty::Enum \ | |||
461 | : TraitProperty::invalid) | |||
462 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
463 | .Default(TraitProperty::invalid); | |||
464 | } | |||
465 | StringRef llvm::omp::getOpenMPContextTraitPropertyName(TraitProperty Kind, | |||
466 | StringRef RawString) { | |||
467 | if (Kind == TraitProperty::device_isa___ANY) | |||
468 | return RawString; | |||
469 | switch (Kind) { | |||
470 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
471 | case TraitProperty::Enum: \ | |||
472 | return Str; | |||
473 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
474 | } | |||
475 | llvm_unreachable("Unknown trait property!")::llvm::llvm_unreachable_internal("Unknown trait property!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 475); | |||
476 | } | |||
477 | StringRef llvm::omp::getOpenMPContextTraitPropertyFullName(TraitProperty Kind) { | |||
478 | switch (Kind) { | |||
479 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
480 | case TraitProperty::Enum: \ | |||
481 | return "(" #TraitSetEnum "," #TraitSelectorEnum "," Str ")"; | |||
482 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
483 | } | |||
484 | llvm_unreachable("Unknown trait property!")::llvm::llvm_unreachable_internal("Unknown trait property!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 484); | |||
485 | } | |||
486 | ||||
487 | bool llvm::omp::isValidTraitSelectorForTraitSet(TraitSelector Selector, | |||
488 | TraitSet Set, | |||
489 | bool &AllowsTraitScore, | |||
490 | bool &RequiresProperty) { | |||
491 | AllowsTraitScore = Set != TraitSet::construct && Set != TraitSet::device; | |||
492 | switch (Selector) { | |||
493 | #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ | |||
494 | case TraitSelector::Enum: \ | |||
495 | RequiresProperty = ReqProp; \ | |||
496 | return Set == TraitSet::TraitSetEnum; | |||
497 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
498 | } | |||
499 | llvm_unreachable("Unknown trait selector!")::llvm::llvm_unreachable_internal("Unknown trait selector!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 499); | |||
500 | } | |||
501 | ||||
502 | bool llvm::omp::isValidTraitPropertyForTraitSetAndSelector( | |||
503 | TraitProperty Property, TraitSelector Selector, TraitSet Set) { | |||
504 | switch (Property) { | |||
505 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
506 | case TraitProperty::Enum: \ | |||
507 | return Set == TraitSet::TraitSetEnum && \ | |||
508 | Selector == TraitSelector::TraitSelectorEnum; | |||
509 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
510 | } | |||
511 | llvm_unreachable("Unknown trait property!")::llvm::llvm_unreachable_internal("Unknown trait property!", "llvm/lib/Frontend/OpenMP/OMPContext.cpp" , 511); | |||
512 | } | |||
513 | ||||
514 | std::string llvm::omp::listOpenMPContextTraitSets() { | |||
515 | std::string S; | |||
516 | #define OMP_TRAIT_SET(Enum, Str) \ | |||
517 | if (StringRef(Str) != "invalid") \ | |||
518 | S.append("'").append(Str).append("'").append(" "); | |||
519 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
520 | S.pop_back(); | |||
521 | return S; | |||
522 | } | |||
523 | ||||
524 | std::string llvm::omp::listOpenMPContextTraitSelectors(TraitSet Set) { | |||
525 | std::string S; | |||
526 | #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ | |||
527 | if (TraitSet::TraitSetEnum == Set && StringRef(Str) != "Invalid") \ | |||
528 | S.append("'").append(Str).append("'").append(" "); | |||
529 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
530 | S.pop_back(); | |||
531 | return S; | |||
532 | } | |||
533 | ||||
534 | std::string | |||
535 | llvm::omp::listOpenMPContextTraitProperties(TraitSet Set, | |||
536 | TraitSelector Selector) { | |||
537 | std::string S; | |||
538 | #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ | |||
539 | if (TraitSet::TraitSetEnum == Set && \ | |||
540 | TraitSelector::TraitSelectorEnum == Selector && \ | |||
541 | StringRef(Str) != "invalid") \ | |||
542 | S.append("'").append(Str).append("'").append(" "); | |||
543 | #include "llvm/Frontend/OpenMP/OMPKinds.def" | |||
544 | if (S.empty()) | |||
545 | return "<none>"; | |||
546 | S.pop_back(); | |||
547 | return S; | |||
548 | } |