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