1*c953409fSJohannes Doerfert //===- OMPContext.cpp ------ Collection of helpers for OpenMP contexts ----===// 2*c953409fSJohannes Doerfert // 3*c953409fSJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*c953409fSJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5*c953409fSJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*c953409fSJohannes Doerfert // 7*c953409fSJohannes Doerfert //===----------------------------------------------------------------------===// 8*c953409fSJohannes Doerfert /// \file 9*c953409fSJohannes Doerfert /// 10*c953409fSJohannes Doerfert /// This file implements helper functions and classes to deal with OpenMP 11*c953409fSJohannes Doerfert /// contexts as used by `[begin/end] declare variant` and `metadirective`. 12*c953409fSJohannes Doerfert /// 13*c953409fSJohannes Doerfert //===----------------------------------------------------------------------===// 14*c953409fSJohannes Doerfert 15*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPContext.h" 16*c953409fSJohannes Doerfert #include "llvm/ADT/SetOperations.h" 17*c953409fSJohannes Doerfert #include "llvm/ADT/StringSwitch.h" 18*c953409fSJohannes Doerfert #include "llvm/Support/Debug.h" 19*c953409fSJohannes Doerfert #include "llvm/Support/raw_ostream.h" 20*c953409fSJohannes Doerfert 21*c953409fSJohannes Doerfert #define DEBUG_TYPE "openmp-ir-builder" 22*c953409fSJohannes Doerfert 23*c953409fSJohannes Doerfert using namespace llvm; 24*c953409fSJohannes Doerfert using namespace omp; 25*c953409fSJohannes Doerfert 26*c953409fSJohannes Doerfert OMPContext::OMPContext(bool IsDeviceCompilation, Triple TargetTriple) { 27*c953409fSJohannes Doerfert // Add the appropriate device kind trait based on the triple and the 28*c953409fSJohannes Doerfert // IsDeviceCompilation flag. 29*c953409fSJohannes Doerfert ActiveTraits.insert(IsDeviceCompilation ? TraitProperty::device_kind_nohost 30*c953409fSJohannes Doerfert : TraitProperty::device_kind_host); 31*c953409fSJohannes Doerfert switch (TargetTriple.getArch()) { 32*c953409fSJohannes Doerfert case Triple::arm: 33*c953409fSJohannes Doerfert case Triple::armeb: 34*c953409fSJohannes Doerfert case Triple::aarch64: 35*c953409fSJohannes Doerfert case Triple::aarch64_be: 36*c953409fSJohannes Doerfert case Triple::aarch64_32: 37*c953409fSJohannes Doerfert case Triple::mips: 38*c953409fSJohannes Doerfert case Triple::mipsel: 39*c953409fSJohannes Doerfert case Triple::mips64: 40*c953409fSJohannes Doerfert case Triple::mips64el: 41*c953409fSJohannes Doerfert case Triple::ppc: 42*c953409fSJohannes Doerfert case Triple::ppc64: 43*c953409fSJohannes Doerfert case Triple::ppc64le: 44*c953409fSJohannes Doerfert case Triple::x86: 45*c953409fSJohannes Doerfert case Triple::x86_64: 46*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::device_kind_cpu); 47*c953409fSJohannes Doerfert break; 48*c953409fSJohannes Doerfert case Triple::amdgcn: 49*c953409fSJohannes Doerfert case Triple::nvptx: 50*c953409fSJohannes Doerfert case Triple::nvptx64: 51*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::device_kind_gpu); 52*c953409fSJohannes Doerfert break; 53*c953409fSJohannes Doerfert default: 54*c953409fSJohannes Doerfert break; 55*c953409fSJohannes Doerfert } 56*c953409fSJohannes Doerfert 57*c953409fSJohannes Doerfert // Add the appropriate device architecture trait based on the triple. 58*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 59*c953409fSJohannes Doerfert if (TraitSelector::TraitSelectorEnum == TraitSelector::device_arch) \ 60*c953409fSJohannes Doerfert if (TargetTriple.getArch() == TargetTriple.getArchTypeForLLVMName(Str)) \ 61*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::Enum); 62*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 63*c953409fSJohannes Doerfert 64*c953409fSJohannes Doerfert // TODO: What exactly do we want to see as device ISA trait? 65*c953409fSJohannes Doerfert // The discussion on the list did not seem to have come to an agreed 66*c953409fSJohannes Doerfert // upon solution. 67*c953409fSJohannes Doerfert 68*c953409fSJohannes Doerfert // LLVM is the "OpenMP vendor" but we could also interpret vendor as the 69*c953409fSJohannes Doerfert // target vendor. 70*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::implementation_vendor_llvm); 71*c953409fSJohannes Doerfert 72*c953409fSJohannes Doerfert // The user condition true is accepted but not false. 73*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::user_condition_true); 74*c953409fSJohannes Doerfert 75*c953409fSJohannes Doerfert // This is for sure some device. 76*c953409fSJohannes Doerfert ActiveTraits.insert(TraitProperty::device_kind_any); 77*c953409fSJohannes Doerfert 78*c953409fSJohannes Doerfert LLVM_DEBUG({ 79*c953409fSJohannes Doerfert dbgs() << "[" << DEBUG_TYPE 80*c953409fSJohannes Doerfert << "] New OpenMP context with the following properties:\n"; 81*c953409fSJohannes Doerfert for (auto &Property : ActiveTraits) 82*c953409fSJohannes Doerfert dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) 83*c953409fSJohannes Doerfert << "\n"; 84*c953409fSJohannes Doerfert }); 85*c953409fSJohannes Doerfert } 86*c953409fSJohannes Doerfert 87*c953409fSJohannes Doerfert /// Return true if \p C0 is a subset of \p C1. Note that both arrays are 88*c953409fSJohannes Doerfert /// expected to be sorted. 89*c953409fSJohannes Doerfert template <typename T> static bool isSubset(ArrayRef<T> C0, ArrayRef<T> C1) { 90*c953409fSJohannes Doerfert #ifdef EXPENSIVE_CHECKS 91*c953409fSJohannes Doerfert assert(std::is_sorted(C0.begin(), C0.end()) && 92*c953409fSJohannes Doerfert std::is_sorted(C1.begin(), C1.end()) && "Expected sorted arrays!"); 93*c953409fSJohannes Doerfert #endif 94*c953409fSJohannes Doerfert if (C0.size() > C1.size()) 95*c953409fSJohannes Doerfert return false; 96*c953409fSJohannes Doerfert auto It0 = C0.begin(), End0 = C0.end(); 97*c953409fSJohannes Doerfert auto It1 = C1.begin(), End1 = C1.end(); 98*c953409fSJohannes Doerfert while (It0 != End0) { 99*c953409fSJohannes Doerfert if (It1 == End1) 100*c953409fSJohannes Doerfert return false; 101*c953409fSJohannes Doerfert if (*It0 == *It1) { 102*c953409fSJohannes Doerfert ++It0; 103*c953409fSJohannes Doerfert ++It1; 104*c953409fSJohannes Doerfert continue; 105*c953409fSJohannes Doerfert } 106*c953409fSJohannes Doerfert ++It0; 107*c953409fSJohannes Doerfert } 108*c953409fSJohannes Doerfert return true; 109*c953409fSJohannes Doerfert } 110*c953409fSJohannes Doerfert 111*c953409fSJohannes Doerfert /// Return true if \p C0 is a strict subset of \p C1. Note that both arrays are 112*c953409fSJohannes Doerfert /// expected to be sorted. 113*c953409fSJohannes Doerfert template <typename T> 114*c953409fSJohannes Doerfert static bool isStrictSubset(ArrayRef<T> C0, ArrayRef<T> C1) { 115*c953409fSJohannes Doerfert if (C0.size() >= C1.size()) 116*c953409fSJohannes Doerfert return false; 117*c953409fSJohannes Doerfert return isSubset<T>(C0, C1); 118*c953409fSJohannes Doerfert } 119*c953409fSJohannes Doerfert 120*c953409fSJohannes Doerfert static bool isStrictSubset(const VariantMatchInfo &VMI0, 121*c953409fSJohannes Doerfert const VariantMatchInfo &VMI1) { 122*c953409fSJohannes Doerfert // If all required traits are a strict subset and the ordered vectors storing 123*c953409fSJohannes Doerfert // the construct traits, we say it is a strict subset. Note that the latter 124*c953409fSJohannes Doerfert // relation is not required to be strict. 125*c953409fSJohannes Doerfert return set_is_strict_subset(VMI0.RequiredTraits, VMI1.RequiredTraits) && 126*c953409fSJohannes Doerfert isSubset<TraitProperty>(VMI0.ConstructTraits, VMI1.ConstructTraits); 127*c953409fSJohannes Doerfert } 128*c953409fSJohannes Doerfert 129*c953409fSJohannes Doerfert static int isVariantApplicableInContextHelper( 130*c953409fSJohannes Doerfert const VariantMatchInfo &VMI, const OMPContext &Ctx, 131*c953409fSJohannes Doerfert SmallVectorImpl<unsigned> *ConstructMatches) { 132*c953409fSJohannes Doerfert 133*c953409fSJohannes Doerfert for (TraitProperty Property : VMI.RequiredTraits) { 134*c953409fSJohannes Doerfert 135*c953409fSJohannes Doerfert bool IsActiveTrait = Ctx.ActiveTraits.count(Property); 136*c953409fSJohannes Doerfert if (!IsActiveTrait) { 137*c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Property " 138*c953409fSJohannes Doerfert << getOpenMPContextTraitPropertyName(Property) 139*c953409fSJohannes Doerfert << " was not in the OpenMP context.\n"); 140*c953409fSJohannes Doerfert return false; 141*c953409fSJohannes Doerfert } 142*c953409fSJohannes Doerfert } 143*c953409fSJohannes Doerfert 144*c953409fSJohannes Doerfert // We could use isSubset here but we also want to record the match locations. 145*c953409fSJohannes Doerfert unsigned ConstructIdx = 0, NoConstructTraits = Ctx.ConstructTraits.size(); 146*c953409fSJohannes Doerfert for (TraitProperty Property : VMI.ConstructTraits) { 147*c953409fSJohannes Doerfert assert(getOpenMPContextTraitSetForProperty(Property) == 148*c953409fSJohannes Doerfert TraitSet::construct && 149*c953409fSJohannes Doerfert "Variant context is ill-formed!"); 150*c953409fSJohannes Doerfert 151*c953409fSJohannes Doerfert // Verify the nesting. 152*c953409fSJohannes Doerfert bool FoundInOrder = false; 153*c953409fSJohannes Doerfert while (!FoundInOrder && ConstructIdx != NoConstructTraits) 154*c953409fSJohannes Doerfert FoundInOrder = (Ctx.ConstructTraits[ConstructIdx++] == Property); 155*c953409fSJohannes Doerfert if (ConstructMatches) 156*c953409fSJohannes Doerfert ConstructMatches->push_back(ConstructIdx - 1); 157*c953409fSJohannes Doerfert 158*c953409fSJohannes Doerfert if (!FoundInOrder) { 159*c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Construct property " 160*c953409fSJohannes Doerfert << getOpenMPContextTraitPropertyName(Property) 161*c953409fSJohannes Doerfert << " was not nested properly.\n"); 162*c953409fSJohannes Doerfert return false; 163*c953409fSJohannes Doerfert } 164*c953409fSJohannes Doerfert 165*c953409fSJohannes Doerfert // TODO: Verify SIMD 166*c953409fSJohannes Doerfert } 167*c953409fSJohannes Doerfert 168*c953409fSJohannes Doerfert assert(isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) && 169*c953409fSJohannes Doerfert "Broken invariant!"); 170*c953409fSJohannes Doerfert return true; 171*c953409fSJohannes Doerfert } 172*c953409fSJohannes Doerfert 173*c953409fSJohannes Doerfert bool llvm::omp::isVariantApplicableInContext(const VariantMatchInfo &VMI, 174*c953409fSJohannes Doerfert const OMPContext &Ctx) { 175*c953409fSJohannes Doerfert return isVariantApplicableInContextHelper(VMI, Ctx, nullptr); 176*c953409fSJohannes Doerfert } 177*c953409fSJohannes Doerfert 178*c953409fSJohannes Doerfert static APInt getVariantMatchScore(const VariantMatchInfo &VMI, 179*c953409fSJohannes Doerfert const OMPContext &Ctx, 180*c953409fSJohannes Doerfert SmallVectorImpl<unsigned> &ConstructMatches) { 181*c953409fSJohannes Doerfert APInt Score(64, 1); 182*c953409fSJohannes Doerfert 183*c953409fSJohannes Doerfert unsigned NoConstructTraits = VMI.ConstructTraits.size(); 184*c953409fSJohannes Doerfert for (TraitProperty Property : VMI.RequiredTraits) { 185*c953409fSJohannes Doerfert // If there is a user score attached, use it. 186*c953409fSJohannes Doerfert if (VMI.ScoreMap.count(Property)) { 187*c953409fSJohannes Doerfert const APInt &UserScore = VMI.ScoreMap.lookup(Property); 188*c953409fSJohannes Doerfert assert(UserScore.uge(0) && "Expect non-negative user scores!"); 189*c953409fSJohannes Doerfert Score += UserScore.getZExtValue(); 190*c953409fSJohannes Doerfert continue; 191*c953409fSJohannes Doerfert } 192*c953409fSJohannes Doerfert 193*c953409fSJohannes Doerfert switch (getOpenMPContextTraitSetForProperty(Property)) { 194*c953409fSJohannes Doerfert case TraitSet::construct: 195*c953409fSJohannes Doerfert // We handle the construct traits later via the VMI.ConstructTraits 196*c953409fSJohannes Doerfert // container. 197*c953409fSJohannes Doerfert continue; 198*c953409fSJohannes Doerfert case TraitSet::implementation: 199*c953409fSJohannes Doerfert // No effect on the score (implementation defined). 200*c953409fSJohannes Doerfert continue; 201*c953409fSJohannes Doerfert case TraitSet::user: 202*c953409fSJohannes Doerfert // No effect on the score. 203*c953409fSJohannes Doerfert continue; 204*c953409fSJohannes Doerfert case TraitSet::device: 205*c953409fSJohannes Doerfert // Handled separately below. 206*c953409fSJohannes Doerfert break; 207*c953409fSJohannes Doerfert case TraitSet::invalid: 208*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait set is not to be used!"); 209*c953409fSJohannes Doerfert } 210*c953409fSJohannes Doerfert 211*c953409fSJohannes Doerfert // device={kind(any)} is "as if" no kind selector was specified. 212*c953409fSJohannes Doerfert if (Property == TraitProperty::device_kind_any) 213*c953409fSJohannes Doerfert continue; 214*c953409fSJohannes Doerfert 215*c953409fSJohannes Doerfert switch (getOpenMPContextTraitSelectorForProperty(Property)) { 216*c953409fSJohannes Doerfert case TraitSelector::device_kind: 217*c953409fSJohannes Doerfert Score += (1 << (NoConstructTraits + 0)); 218*c953409fSJohannes Doerfert continue; 219*c953409fSJohannes Doerfert case TraitSelector::device_arch: 220*c953409fSJohannes Doerfert Score += (1 << (NoConstructTraits + 1)); 221*c953409fSJohannes Doerfert continue; 222*c953409fSJohannes Doerfert case TraitSelector::device_isa: 223*c953409fSJohannes Doerfert Score += (1 << (NoConstructTraits + 2)); 224*c953409fSJohannes Doerfert continue; 225*c953409fSJohannes Doerfert default: 226*c953409fSJohannes Doerfert continue; 227*c953409fSJohannes Doerfert } 228*c953409fSJohannes Doerfert } 229*c953409fSJohannes Doerfert 230*c953409fSJohannes Doerfert unsigned ConstructIdx = 0; 231*c953409fSJohannes Doerfert assert(NoConstructTraits == ConstructMatches.size() && 232*c953409fSJohannes Doerfert "Mismatch in the construct traits!"); 233*c953409fSJohannes Doerfert for (TraitProperty Property : VMI.ConstructTraits) { 234*c953409fSJohannes Doerfert assert(getOpenMPContextTraitSetForProperty(Property) == 235*c953409fSJohannes Doerfert TraitSet::construct && 236*c953409fSJohannes Doerfert "Ill-formed variant match info!"); 237*c953409fSJohannes Doerfert // ConstructMatches is the position p - 1 and we need 2^(p-1). 238*c953409fSJohannes Doerfert Score += (1 << ConstructMatches[ConstructIdx++]); 239*c953409fSJohannes Doerfert } 240*c953409fSJohannes Doerfert 241*c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Variant has a score of " << Score 242*c953409fSJohannes Doerfert << "\n"); 243*c953409fSJohannes Doerfert return Score; 244*c953409fSJohannes Doerfert }; 245*c953409fSJohannes Doerfert 246*c953409fSJohannes Doerfert int llvm::omp::getBestVariantMatchForContext( 247*c953409fSJohannes Doerfert const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx) { 248*c953409fSJohannes Doerfert 249*c953409fSJohannes Doerfert APInt BestScore(64, 0); 250*c953409fSJohannes Doerfert int BestVMIIdx = -1; 251*c953409fSJohannes Doerfert const VariantMatchInfo *BestVMI = nullptr; 252*c953409fSJohannes Doerfert 253*c953409fSJohannes Doerfert for (unsigned u = 0, e = VMIs.size(); u < e; ++u) { 254*c953409fSJohannes Doerfert const VariantMatchInfo &VMI = VMIs[u]; 255*c953409fSJohannes Doerfert 256*c953409fSJohannes Doerfert SmallVector<unsigned, 8> ConstructMatches; 257*c953409fSJohannes Doerfert // If the variant is not applicable its not the best. 258*c953409fSJohannes Doerfert if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches)) 259*c953409fSJohannes Doerfert continue; 260*c953409fSJohannes Doerfert // Check if its clearly not the best. 261*c953409fSJohannes Doerfert APInt Score = getVariantMatchScore(VMI, Ctx, ConstructMatches); 262*c953409fSJohannes Doerfert if (Score.ult(BestScore)) 263*c953409fSJohannes Doerfert continue; 264*c953409fSJohannes Doerfert // Equal score need subset checks. 265*c953409fSJohannes Doerfert if (Score.eq(BestScore)) { 266*c953409fSJohannes Doerfert // Strict subset are never best. 267*c953409fSJohannes Doerfert if (isStrictSubset(VMI, *BestVMI)) 268*c953409fSJohannes Doerfert continue; 269*c953409fSJohannes Doerfert // Same score and the current best is no strict subset so we keep it. 270*c953409fSJohannes Doerfert if (!isStrictSubset(*BestVMI, VMI)) 271*c953409fSJohannes Doerfert continue; 272*c953409fSJohannes Doerfert } 273*c953409fSJohannes Doerfert // New best found. 274*c953409fSJohannes Doerfert BestVMI = &VMI; 275*c953409fSJohannes Doerfert BestVMIIdx = u; 276*c953409fSJohannes Doerfert BestScore = Score; 277*c953409fSJohannes Doerfert } 278*c953409fSJohannes Doerfert 279*c953409fSJohannes Doerfert return BestVMIIdx; 280*c953409fSJohannes Doerfert } 281*c953409fSJohannes Doerfert 282*c953409fSJohannes Doerfert TraitSet llvm::omp::getOpenMPContextTraitSetKind(StringRef S) { 283*c953409fSJohannes Doerfert return StringSwitch<TraitSet>(S) 284*c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) .Case(Str, TraitSet::Enum) 285*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 286*c953409fSJohannes Doerfert .Default(TraitSet::invalid); 287*c953409fSJohannes Doerfert } 288*c953409fSJohannes Doerfert TraitSet 289*c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSetForProperty(TraitProperty Property) { 290*c953409fSJohannes Doerfert switch (Property) { 291*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 292*c953409fSJohannes Doerfert case TraitProperty::Enum: \ 293*c953409fSJohannes Doerfert return TraitSet::TraitSetEnum; 294*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 295*c953409fSJohannes Doerfert } 296*c953409fSJohannes Doerfert } 297*c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSetName(TraitSet Kind) { 298*c953409fSJohannes Doerfert switch (Kind) { 299*c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) \ 300*c953409fSJohannes Doerfert case TraitSet::Enum: \ 301*c953409fSJohannes Doerfert return Str; 302*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 303*c953409fSJohannes Doerfert } 304*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait set!"); 305*c953409fSJohannes Doerfert } 306*c953409fSJohannes Doerfert 307*c953409fSJohannes Doerfert TraitSelector llvm::omp::getOpenMPContextTraitSelectorKind(StringRef S) { 308*c953409fSJohannes Doerfert return StringSwitch<TraitSelector>(S) 309*c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 310*c953409fSJohannes Doerfert .Case(Str, TraitSelector::Enum) 311*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 312*c953409fSJohannes Doerfert .Default(TraitSelector::invalid); 313*c953409fSJohannes Doerfert } 314*c953409fSJohannes Doerfert TraitSelector 315*c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSelectorForProperty(TraitProperty Property) { 316*c953409fSJohannes Doerfert switch (Property) { 317*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 318*c953409fSJohannes Doerfert case TraitProperty::Enum: \ 319*c953409fSJohannes Doerfert return TraitSelector::TraitSelectorEnum; 320*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 321*c953409fSJohannes Doerfert } 322*c953409fSJohannes Doerfert } 323*c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSelectorName(TraitSelector Kind) { 324*c953409fSJohannes Doerfert switch (Kind) { 325*c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 326*c953409fSJohannes Doerfert case TraitSelector::Enum: \ 327*c953409fSJohannes Doerfert return Str; 328*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 329*c953409fSJohannes Doerfert } 330*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 331*c953409fSJohannes Doerfert } 332*c953409fSJohannes Doerfert 333*c953409fSJohannes Doerfert TraitProperty llvm::omp::getOpenMPContextTraitPropertyKind( 334*c953409fSJohannes Doerfert TraitSet Set, TraitSelector Selector, StringRef S) { 335*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 336*c953409fSJohannes Doerfert if (Set == TraitSet::TraitSetEnum && \ 337*c953409fSJohannes Doerfert Selector == TraitSelector::TraitSelectorEnum && Str == S) \ 338*c953409fSJohannes Doerfert return TraitProperty::Enum; 339*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 340*c953409fSJohannes Doerfert return TraitProperty::invalid; 341*c953409fSJohannes Doerfert } 342*c953409fSJohannes Doerfert TraitProperty 343*c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitPropertyForSelector(TraitSelector Selector) { 344*c953409fSJohannes Doerfert return StringSwitch<TraitProperty>( 345*c953409fSJohannes Doerfert getOpenMPContextTraitSelectorName(Selector)) 346*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 347*c953409fSJohannes Doerfert .Case(Str, Selector == TraitSelector::TraitSelectorEnum \ 348*c953409fSJohannes Doerfert ? TraitProperty::Enum \ 349*c953409fSJohannes Doerfert : TraitProperty::invalid) 350*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 351*c953409fSJohannes Doerfert .Default(TraitProperty::invalid); 352*c953409fSJohannes Doerfert } 353*c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyName(TraitProperty Kind) { 354*c953409fSJohannes Doerfert switch (Kind) { 355*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 356*c953409fSJohannes Doerfert case TraitProperty::Enum: \ 357*c953409fSJohannes Doerfert return Str; 358*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 359*c953409fSJohannes Doerfert } 360*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 361*c953409fSJohannes Doerfert } 362*c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyFullName(TraitProperty Kind) { 363*c953409fSJohannes Doerfert switch (Kind) { 364*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 365*c953409fSJohannes Doerfert case TraitProperty::Enum: \ 366*c953409fSJohannes Doerfert return "(" #TraitSetEnum "," #TraitSelectorEnum "," Str ")"; 367*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 368*c953409fSJohannes Doerfert } 369*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 370*c953409fSJohannes Doerfert } 371*c953409fSJohannes Doerfert 372*c953409fSJohannes Doerfert bool llvm::omp::isValidTraitSelectorForTraitSet(TraitSelector Selector, 373*c953409fSJohannes Doerfert TraitSet Set, 374*c953409fSJohannes Doerfert bool &AllowsTraitScore, 375*c953409fSJohannes Doerfert bool &RequiresProperty) { 376*c953409fSJohannes Doerfert AllowsTraitScore = Set != TraitSet::construct && Set != TraitSet::device; 377*c953409fSJohannes Doerfert switch (Selector) { 378*c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 379*c953409fSJohannes Doerfert case TraitSelector::Enum: \ 380*c953409fSJohannes Doerfert RequiresProperty = ReqProp; \ 381*c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum; 382*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 383*c953409fSJohannes Doerfert } 384*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 385*c953409fSJohannes Doerfert } 386*c953409fSJohannes Doerfert 387*c953409fSJohannes Doerfert bool llvm::omp::isValidTraitPropertyForTraitSetAndSelector( 388*c953409fSJohannes Doerfert TraitProperty Property, TraitSelector Selector, TraitSet Set) { 389*c953409fSJohannes Doerfert switch (Property) { 390*c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 391*c953409fSJohannes Doerfert case TraitProperty::Enum: \ 392*c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum && \ 393*c953409fSJohannes Doerfert Selector == TraitSelector::TraitSelectorEnum; 394*c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 395*c953409fSJohannes Doerfert } 396*c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 397*c953409fSJohannes Doerfert } 398