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. 296b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(IsDeviceCompilation 306b57d7f5SJohannes Doerfert ? TraitProperty::device_kind_nohost 316b57d7f5SJohannes Doerfert : TraitProperty::device_kind_host)); 32c953409fSJohannes Doerfert switch (TargetTriple.getArch()) { 33c953409fSJohannes Doerfert case Triple::arm: 34c953409fSJohannes Doerfert case Triple::armeb: 35c953409fSJohannes Doerfert case Triple::aarch64: 36c953409fSJohannes Doerfert case Triple::aarch64_be: 37c953409fSJohannes Doerfert case Triple::aarch64_32: 38c953409fSJohannes Doerfert case Triple::mips: 39c953409fSJohannes Doerfert case Triple::mipsel: 40c953409fSJohannes Doerfert case Triple::mips64: 41c953409fSJohannes Doerfert case Triple::mips64el: 42c953409fSJohannes Doerfert case Triple::ppc: 43c953409fSJohannes Doerfert case Triple::ppc64: 44c953409fSJohannes Doerfert case Triple::ppc64le: 45c953409fSJohannes Doerfert case Triple::x86: 46c953409fSJohannes Doerfert case Triple::x86_64: 476b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::device_kind_cpu)); 48c953409fSJohannes Doerfert break; 49c953409fSJohannes Doerfert case Triple::amdgcn: 50c953409fSJohannes Doerfert case Triple::nvptx: 51c953409fSJohannes Doerfert case Triple::nvptx64: 526b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::device_kind_gpu)); 53c953409fSJohannes Doerfert break; 54c953409fSJohannes Doerfert default: 55c953409fSJohannes Doerfert break; 56c953409fSJohannes Doerfert } 57c953409fSJohannes Doerfert 58c953409fSJohannes Doerfert // Add the appropriate device architecture trait based on the triple. 59c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 60c953409fSJohannes Doerfert if (TraitSelector::TraitSelectorEnum == TraitSelector::device_arch) \ 61c953409fSJohannes Doerfert if (TargetTriple.getArch() == TargetTriple.getArchTypeForLLVMName(Str)) \ 626b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::Enum)); 63c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 64c953409fSJohannes Doerfert 65c953409fSJohannes Doerfert // TODO: What exactly do we want to see as device ISA trait? 66c953409fSJohannes Doerfert // The discussion on the list did not seem to have come to an agreed 67c953409fSJohannes Doerfert // upon solution. 68c953409fSJohannes Doerfert 69c953409fSJohannes Doerfert // LLVM is the "OpenMP vendor" but we could also interpret vendor as the 70c953409fSJohannes Doerfert // target vendor. 716b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::implementation_vendor_llvm)); 72c953409fSJohannes Doerfert 73c953409fSJohannes Doerfert // The user condition true is accepted but not false. 746b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::user_condition_true)); 75c953409fSJohannes Doerfert 76c953409fSJohannes Doerfert // This is for sure some device. 776b57d7f5SJohannes Doerfert ActiveTraits.set(unsigned(TraitProperty::device_kind_any)); 78c953409fSJohannes Doerfert 79c953409fSJohannes Doerfert LLVM_DEBUG({ 80c953409fSJohannes Doerfert dbgs() << "[" << DEBUG_TYPE 81c953409fSJohannes Doerfert << "] New OpenMP context with the following properties:\n"; 826b57d7f5SJohannes Doerfert for (const auto &SetBitsIt : ActiveTraits.set_bits()) { 836b57d7f5SJohannes Doerfert TraitProperty Property = TraitProperty(SetBitsIt); 84c953409fSJohannes Doerfert dbgs() << "\t " << getOpenMPContextTraitPropertyFullName(Property) 85c953409fSJohannes Doerfert << "\n"; 866b57d7f5SJohannes Doerfert } 87c953409fSJohannes Doerfert }); 88c953409fSJohannes Doerfert } 89c953409fSJohannes Doerfert 90c953409fSJohannes Doerfert /// Return true if \p C0 is a subset of \p C1. Note that both arrays are 91c953409fSJohannes Doerfert /// expected to be sorted. 92c953409fSJohannes Doerfert template <typename T> static bool isSubset(ArrayRef<T> C0, ArrayRef<T> C1) { 93c953409fSJohannes Doerfert #ifdef EXPENSIVE_CHECKS 94c953409fSJohannes Doerfert assert(std::is_sorted(C0.begin(), C0.end()) && 95c953409fSJohannes Doerfert std::is_sorted(C1.begin(), C1.end()) && "Expected sorted arrays!"); 96c953409fSJohannes Doerfert #endif 97c953409fSJohannes Doerfert if (C0.size() > C1.size()) 98c953409fSJohannes Doerfert return false; 99c953409fSJohannes Doerfert auto It0 = C0.begin(), End0 = C0.end(); 100c953409fSJohannes Doerfert auto It1 = C1.begin(), End1 = C1.end(); 101c953409fSJohannes Doerfert while (It0 != End0) { 102c953409fSJohannes Doerfert if (It1 == End1) 103c953409fSJohannes Doerfert return false; 104c953409fSJohannes Doerfert if (*It0 == *It1) { 105c953409fSJohannes Doerfert ++It0; 106c953409fSJohannes Doerfert ++It1; 107c953409fSJohannes Doerfert continue; 108c953409fSJohannes Doerfert } 109c953409fSJohannes Doerfert ++It0; 110c953409fSJohannes Doerfert } 111c953409fSJohannes Doerfert return true; 112c953409fSJohannes Doerfert } 113c953409fSJohannes Doerfert 114c953409fSJohannes Doerfert /// Return true if \p C0 is a strict subset of \p C1. Note that both arrays are 115c953409fSJohannes Doerfert /// expected to be sorted. 116c953409fSJohannes Doerfert template <typename T> 117c953409fSJohannes Doerfert static bool isStrictSubset(ArrayRef<T> C0, ArrayRef<T> C1) { 118c953409fSJohannes Doerfert if (C0.size() >= C1.size()) 119c953409fSJohannes Doerfert return false; 120c953409fSJohannes Doerfert return isSubset<T>(C0, C1); 121c953409fSJohannes Doerfert } 122c953409fSJohannes Doerfert 123c953409fSJohannes Doerfert static bool isStrictSubset(const VariantMatchInfo &VMI0, 124c953409fSJohannes Doerfert const VariantMatchInfo &VMI1) { 125c953409fSJohannes Doerfert // If all required traits are a strict subset and the ordered vectors storing 126c953409fSJohannes Doerfert // the construct traits, we say it is a strict subset. Note that the latter 127c953409fSJohannes Doerfert // relation is not required to be strict. 1286b57d7f5SJohannes Doerfert if (VMI0.RequiredTraits.count() >= VMI1.RequiredTraits.count()) 1296b57d7f5SJohannes Doerfert return false; 1306b57d7f5SJohannes Doerfert for (const auto &SetBitsIt : VMI0.RequiredTraits.set_bits()) 1316b57d7f5SJohannes Doerfert if (!VMI1.RequiredTraits.test(SetBitsIt)) 1326b57d7f5SJohannes Doerfert return false; 1336b57d7f5SJohannes Doerfert if (!isSubset<TraitProperty>(VMI0.ConstructTraits, VMI1.ConstructTraits)) 1346b57d7f5SJohannes Doerfert return false; 1356b57d7f5SJohannes Doerfert return true; 136c953409fSJohannes Doerfert } 137c953409fSJohannes Doerfert 138c953409fSJohannes Doerfert static int isVariantApplicableInContextHelper( 139c953409fSJohannes Doerfert const VariantMatchInfo &VMI, const OMPContext &Ctx, 140c953409fSJohannes Doerfert SmallVectorImpl<unsigned> *ConstructMatches) { 141c953409fSJohannes Doerfert 1426b57d7f5SJohannes Doerfert for (const auto &SetBitsIt : VMI.RequiredTraits.set_bits()) { 1436b57d7f5SJohannes Doerfert TraitProperty Property = TraitProperty(SetBitsIt); 144c953409fSJohannes Doerfert 1456b57d7f5SJohannes Doerfert bool IsActiveTrait = Ctx.ActiveTraits.test(unsigned(Property)); 146c953409fSJohannes Doerfert if (!IsActiveTrait) { 147c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Property " 148c953409fSJohannes Doerfert << getOpenMPContextTraitPropertyName(Property) 149c953409fSJohannes Doerfert << " was not in the OpenMP context.\n"); 150c953409fSJohannes Doerfert return false; 151c953409fSJohannes Doerfert } 152c953409fSJohannes Doerfert } 153c953409fSJohannes Doerfert 154c953409fSJohannes Doerfert // We could use isSubset here but we also want to record the match locations. 155c953409fSJohannes Doerfert unsigned ConstructIdx = 0, NoConstructTraits = Ctx.ConstructTraits.size(); 156c953409fSJohannes Doerfert for (TraitProperty Property : VMI.ConstructTraits) { 157c953409fSJohannes Doerfert assert(getOpenMPContextTraitSetForProperty(Property) == 158c953409fSJohannes Doerfert TraitSet::construct && 159c953409fSJohannes Doerfert "Variant context is ill-formed!"); 160c953409fSJohannes Doerfert 161c953409fSJohannes Doerfert // Verify the nesting. 162c953409fSJohannes Doerfert bool FoundInOrder = false; 163c953409fSJohannes Doerfert while (!FoundInOrder && ConstructIdx != NoConstructTraits) 164c953409fSJohannes Doerfert FoundInOrder = (Ctx.ConstructTraits[ConstructIdx++] == Property); 165c953409fSJohannes Doerfert if (ConstructMatches) 166c953409fSJohannes Doerfert ConstructMatches->push_back(ConstructIdx - 1); 167c953409fSJohannes Doerfert 168c953409fSJohannes Doerfert if (!FoundInOrder) { 169c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Construct property " 170c953409fSJohannes Doerfert << getOpenMPContextTraitPropertyName(Property) 171c953409fSJohannes Doerfert << " was not nested properly.\n"); 172c953409fSJohannes Doerfert return false; 173c953409fSJohannes Doerfert } 174c953409fSJohannes Doerfert 175c953409fSJohannes Doerfert // TODO: Verify SIMD 176c953409fSJohannes Doerfert } 177c953409fSJohannes Doerfert 178c953409fSJohannes Doerfert assert(isSubset<TraitProperty>(VMI.ConstructTraits, Ctx.ConstructTraits) && 179c953409fSJohannes Doerfert "Broken invariant!"); 180c953409fSJohannes Doerfert return true; 181c953409fSJohannes Doerfert } 182c953409fSJohannes Doerfert 183c953409fSJohannes Doerfert bool llvm::omp::isVariantApplicableInContext(const VariantMatchInfo &VMI, 184c953409fSJohannes Doerfert const OMPContext &Ctx) { 185c953409fSJohannes Doerfert return isVariantApplicableInContextHelper(VMI, Ctx, nullptr); 186c953409fSJohannes Doerfert } 187c953409fSJohannes Doerfert 188c953409fSJohannes Doerfert static APInt getVariantMatchScore(const VariantMatchInfo &VMI, 189c953409fSJohannes Doerfert const OMPContext &Ctx, 190c953409fSJohannes Doerfert SmallVectorImpl<unsigned> &ConstructMatches) { 191c953409fSJohannes Doerfert APInt Score(64, 1); 192c953409fSJohannes Doerfert 193c953409fSJohannes Doerfert unsigned NoConstructTraits = VMI.ConstructTraits.size(); 1946b57d7f5SJohannes Doerfert for (const auto &SetBitsIt : VMI.RequiredTraits.set_bits()) { 1956b57d7f5SJohannes Doerfert TraitProperty Property = TraitProperty(SetBitsIt); 196c953409fSJohannes Doerfert // If there is a user score attached, use it. 197c953409fSJohannes Doerfert if (VMI.ScoreMap.count(Property)) { 198c953409fSJohannes Doerfert const APInt &UserScore = VMI.ScoreMap.lookup(Property); 199c953409fSJohannes Doerfert assert(UserScore.uge(0) && "Expect non-negative user scores!"); 200c953409fSJohannes Doerfert Score += UserScore.getZExtValue(); 201c953409fSJohannes Doerfert continue; 202c953409fSJohannes Doerfert } 203c953409fSJohannes Doerfert 204c953409fSJohannes Doerfert switch (getOpenMPContextTraitSetForProperty(Property)) { 205c953409fSJohannes Doerfert case TraitSet::construct: 206c953409fSJohannes Doerfert // We handle the construct traits later via the VMI.ConstructTraits 207c953409fSJohannes Doerfert // container. 208c953409fSJohannes Doerfert continue; 209c953409fSJohannes Doerfert case TraitSet::implementation: 210c953409fSJohannes Doerfert // No effect on the score (implementation defined). 211c953409fSJohannes Doerfert continue; 212c953409fSJohannes Doerfert case TraitSet::user: 213c953409fSJohannes Doerfert // No effect on the score. 214c953409fSJohannes Doerfert continue; 215c953409fSJohannes Doerfert case TraitSet::device: 216c953409fSJohannes Doerfert // Handled separately below. 217c953409fSJohannes Doerfert break; 218c953409fSJohannes Doerfert case TraitSet::invalid: 219c953409fSJohannes Doerfert llvm_unreachable("Unknown trait set is not to be used!"); 220c953409fSJohannes Doerfert } 221c953409fSJohannes Doerfert 222c953409fSJohannes Doerfert // device={kind(any)} is "as if" no kind selector was specified. 223c953409fSJohannes Doerfert if (Property == TraitProperty::device_kind_any) 224c953409fSJohannes Doerfert continue; 225c953409fSJohannes Doerfert 226c953409fSJohannes Doerfert switch (getOpenMPContextTraitSelectorForProperty(Property)) { 227c953409fSJohannes Doerfert case TraitSelector::device_kind: 228ae5d3e8cSSimon Pilgrim Score += (1ULL << (NoConstructTraits + 0)); 229c953409fSJohannes Doerfert continue; 230c953409fSJohannes Doerfert case TraitSelector::device_arch: 231ae5d3e8cSSimon Pilgrim Score += (1ULL << (NoConstructTraits + 1)); 232c953409fSJohannes Doerfert continue; 233c953409fSJohannes Doerfert case TraitSelector::device_isa: 234ae5d3e8cSSimon Pilgrim Score += (1ULL << (NoConstructTraits + 2)); 235c953409fSJohannes Doerfert continue; 236c953409fSJohannes Doerfert default: 237c953409fSJohannes Doerfert continue; 238c953409fSJohannes Doerfert } 239c953409fSJohannes Doerfert } 240c953409fSJohannes Doerfert 241c953409fSJohannes Doerfert unsigned ConstructIdx = 0; 242c953409fSJohannes Doerfert assert(NoConstructTraits == ConstructMatches.size() && 243c953409fSJohannes Doerfert "Mismatch in the construct traits!"); 244c953409fSJohannes Doerfert for (TraitProperty Property : VMI.ConstructTraits) { 245c953409fSJohannes Doerfert assert(getOpenMPContextTraitSetForProperty(Property) == 246c953409fSJohannes Doerfert TraitSet::construct && 247c953409fSJohannes Doerfert "Ill-formed variant match info!"); 2487b6e49a2SDmitri Gribenko (void)Property; 249c953409fSJohannes Doerfert // ConstructMatches is the position p - 1 and we need 2^(p-1). 250ae5d3e8cSSimon Pilgrim Score += (1ULL << ConstructMatches[ConstructIdx++]); 251c953409fSJohannes Doerfert } 252c953409fSJohannes Doerfert 253c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Variant has a score of " << Score 254c953409fSJohannes Doerfert << "\n"); 255c953409fSJohannes Doerfert return Score; 2562dc45bf3SMartin Storsjö } 257c953409fSJohannes Doerfert 258c953409fSJohannes Doerfert int llvm::omp::getBestVariantMatchForContext( 259c953409fSJohannes Doerfert const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx) { 260c953409fSJohannes Doerfert 261c953409fSJohannes Doerfert APInt BestScore(64, 0); 262c953409fSJohannes Doerfert int BestVMIIdx = -1; 263c953409fSJohannes Doerfert const VariantMatchInfo *BestVMI = nullptr; 264c953409fSJohannes Doerfert 265c953409fSJohannes Doerfert for (unsigned u = 0, e = VMIs.size(); u < e; ++u) { 266c953409fSJohannes Doerfert const VariantMatchInfo &VMI = VMIs[u]; 267c953409fSJohannes Doerfert 268c953409fSJohannes Doerfert SmallVector<unsigned, 8> ConstructMatches; 269c953409fSJohannes Doerfert // If the variant is not applicable its not the best. 270c953409fSJohannes Doerfert if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches)) 271c953409fSJohannes Doerfert continue; 272c953409fSJohannes Doerfert // Check if its clearly not the best. 273c953409fSJohannes Doerfert APInt Score = getVariantMatchScore(VMI, Ctx, ConstructMatches); 274c953409fSJohannes Doerfert if (Score.ult(BestScore)) 275c953409fSJohannes Doerfert continue; 276c953409fSJohannes Doerfert // Equal score need subset checks. 277c953409fSJohannes Doerfert if (Score.eq(BestScore)) { 278c953409fSJohannes Doerfert // Strict subset are never best. 279c953409fSJohannes Doerfert if (isStrictSubset(VMI, *BestVMI)) 280c953409fSJohannes Doerfert continue; 281c953409fSJohannes Doerfert // Same score and the current best is no strict subset so we keep it. 282c953409fSJohannes Doerfert if (!isStrictSubset(*BestVMI, VMI)) 283c953409fSJohannes Doerfert continue; 284c953409fSJohannes Doerfert } 285c953409fSJohannes Doerfert // New best found. 286c953409fSJohannes Doerfert BestVMI = &VMI; 287c953409fSJohannes Doerfert BestVMIIdx = u; 288c953409fSJohannes Doerfert BestScore = Score; 289c953409fSJohannes Doerfert } 290c953409fSJohannes Doerfert 291c953409fSJohannes Doerfert return BestVMIIdx; 292c953409fSJohannes Doerfert } 293c953409fSJohannes Doerfert 294c953409fSJohannes Doerfert TraitSet llvm::omp::getOpenMPContextTraitSetKind(StringRef S) { 295c953409fSJohannes Doerfert return StringSwitch<TraitSet>(S) 296c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) .Case(Str, TraitSet::Enum) 297c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 298c953409fSJohannes Doerfert .Default(TraitSet::invalid); 299c953409fSJohannes Doerfert } 3001228d42dSJohannes Doerfert 3011228d42dSJohannes Doerfert TraitSet 3021228d42dSJohannes Doerfert llvm::omp::getOpenMPContextTraitSetForSelector(TraitSelector Selector) { 3031228d42dSJohannes Doerfert switch (Selector) { 3041228d42dSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 3051228d42dSJohannes Doerfert case TraitSelector::Enum: \ 3061228d42dSJohannes Doerfert return TraitSet::TraitSetEnum; 3071228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 3081228d42dSJohannes Doerfert } 309b91c2673SJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 3101228d42dSJohannes Doerfert } 311c953409fSJohannes Doerfert TraitSet 312c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSetForProperty(TraitProperty Property) { 313c953409fSJohannes Doerfert switch (Property) { 314c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 315c953409fSJohannes Doerfert case TraitProperty::Enum: \ 316c953409fSJohannes Doerfert return TraitSet::TraitSetEnum; 317c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 318c953409fSJohannes Doerfert } 3192dc45bf3SMartin Storsjö llvm_unreachable("Unknown trait set!"); 320c953409fSJohannes Doerfert } 321c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSetName(TraitSet Kind) { 322c953409fSJohannes Doerfert switch (Kind) { 323c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) \ 324c953409fSJohannes Doerfert case TraitSet::Enum: \ 325c953409fSJohannes Doerfert return Str; 326c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 327c953409fSJohannes Doerfert } 328c953409fSJohannes Doerfert llvm_unreachable("Unknown trait set!"); 329c953409fSJohannes Doerfert } 330c953409fSJohannes Doerfert 331c953409fSJohannes Doerfert TraitSelector llvm::omp::getOpenMPContextTraitSelectorKind(StringRef S) { 332c953409fSJohannes Doerfert return StringSwitch<TraitSelector>(S) 333c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 334c953409fSJohannes Doerfert .Case(Str, TraitSelector::Enum) 335c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 336c953409fSJohannes Doerfert .Default(TraitSelector::invalid); 337c953409fSJohannes Doerfert } 338c953409fSJohannes Doerfert TraitSelector 339c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSelectorForProperty(TraitProperty Property) { 340c953409fSJohannes Doerfert switch (Property) { 341c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 342c953409fSJohannes Doerfert case TraitProperty::Enum: \ 343c953409fSJohannes Doerfert return TraitSelector::TraitSelectorEnum; 344c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 345c953409fSJohannes Doerfert } 3462dc45bf3SMartin Storsjö llvm_unreachable("Unknown trait set!"); 347c953409fSJohannes Doerfert } 348c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSelectorName(TraitSelector Kind) { 349c953409fSJohannes Doerfert switch (Kind) { 350c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 351c953409fSJohannes Doerfert case TraitSelector::Enum: \ 352c953409fSJohannes Doerfert return Str; 353c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 354c953409fSJohannes Doerfert } 355c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 356c953409fSJohannes Doerfert } 357c953409fSJohannes Doerfert 3581228d42dSJohannes Doerfert TraitProperty llvm::omp::getOpenMPContextTraitPropertyKind(TraitSet Set, 3591228d42dSJohannes Doerfert StringRef S) { 360c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 3611228d42dSJohannes Doerfert if (Set == TraitSet::TraitSetEnum && Str == S) \ 362c953409fSJohannes Doerfert return TraitProperty::Enum; 363c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 364c953409fSJohannes Doerfert return TraitProperty::invalid; 365c953409fSJohannes Doerfert } 366c953409fSJohannes Doerfert TraitProperty 367c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitPropertyForSelector(TraitSelector Selector) { 368c953409fSJohannes Doerfert return StringSwitch<TraitProperty>( 369c953409fSJohannes Doerfert getOpenMPContextTraitSelectorName(Selector)) 370c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 371c953409fSJohannes Doerfert .Case(Str, Selector == TraitSelector::TraitSelectorEnum \ 372c953409fSJohannes Doerfert ? TraitProperty::Enum \ 373c953409fSJohannes Doerfert : TraitProperty::invalid) 374c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 375c953409fSJohannes Doerfert .Default(TraitProperty::invalid); 376c953409fSJohannes Doerfert } 377c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyName(TraitProperty Kind) { 378c953409fSJohannes Doerfert switch (Kind) { 379c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 380c953409fSJohannes Doerfert case TraitProperty::Enum: \ 381c953409fSJohannes Doerfert return Str; 382c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 383c953409fSJohannes Doerfert } 384c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 385c953409fSJohannes Doerfert } 386c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyFullName(TraitProperty Kind) { 387c953409fSJohannes Doerfert switch (Kind) { 388c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 389c953409fSJohannes Doerfert case TraitProperty::Enum: \ 390c953409fSJohannes Doerfert return "(" #TraitSetEnum "," #TraitSelectorEnum "," Str ")"; 391c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 392c953409fSJohannes Doerfert } 393c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 394c953409fSJohannes Doerfert } 395c953409fSJohannes Doerfert 396c953409fSJohannes Doerfert bool llvm::omp::isValidTraitSelectorForTraitSet(TraitSelector Selector, 397c953409fSJohannes Doerfert TraitSet Set, 398c953409fSJohannes Doerfert bool &AllowsTraitScore, 399c953409fSJohannes Doerfert bool &RequiresProperty) { 400c953409fSJohannes Doerfert AllowsTraitScore = Set != TraitSet::construct && Set != TraitSet::device; 401c953409fSJohannes Doerfert switch (Selector) { 402c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 403c953409fSJohannes Doerfert case TraitSelector::Enum: \ 404c953409fSJohannes Doerfert RequiresProperty = ReqProp; \ 405c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum; 406c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 407c953409fSJohannes Doerfert } 408c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 409c953409fSJohannes Doerfert } 410c953409fSJohannes Doerfert 411c953409fSJohannes Doerfert bool llvm::omp::isValidTraitPropertyForTraitSetAndSelector( 412c953409fSJohannes Doerfert TraitProperty Property, TraitSelector Selector, TraitSet Set) { 413c953409fSJohannes Doerfert switch (Property) { 414c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 415c953409fSJohannes Doerfert case TraitProperty::Enum: \ 416c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum && \ 417c953409fSJohannes Doerfert Selector == TraitSelector::TraitSelectorEnum; 418c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 419c953409fSJohannes Doerfert } 420c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 421c953409fSJohannes Doerfert } 4221228d42dSJohannes Doerfert 4231228d42dSJohannes Doerfert std::string llvm::omp::listOpenMPContextTraitSets() { 4241228d42dSJohannes Doerfert std::string S; 4251228d42dSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) \ 426a8f03963SJohannes Doerfert if (StringRef(Str) != "invalid") \ 4271228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 4281228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 4291228d42dSJohannes Doerfert S.pop_back(); 4301228d42dSJohannes Doerfert return S; 4311228d42dSJohannes Doerfert } 4321228d42dSJohannes Doerfert 4331228d42dSJohannes Doerfert std::string llvm::omp::listOpenMPContextTraitSelectors(TraitSet Set) { 4341228d42dSJohannes Doerfert std::string S; 4351228d42dSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 436a8f03963SJohannes Doerfert if (TraitSet::TraitSetEnum == Set && StringRef(Str) != "Invalid") \ 4371228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 4381228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 4391228d42dSJohannes Doerfert S.pop_back(); 4401228d42dSJohannes Doerfert return S; 4411228d42dSJohannes Doerfert } 4421228d42dSJohannes Doerfert 4431228d42dSJohannes Doerfert std::string 4441228d42dSJohannes Doerfert llvm::omp::listOpenMPContextTraitProperties(TraitSet Set, 4451228d42dSJohannes Doerfert TraitSelector Selector) { 4461228d42dSJohannes Doerfert std::string S; 4471228d42dSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 4481228d42dSJohannes Doerfert if (TraitSet::TraitSetEnum == Set && \ 4491a93285cSReid Kleckner TraitSelector::TraitSelectorEnum == Selector && \ 450a8f03963SJohannes Doerfert StringRef(Str) != "invalid") \ 4511228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 4521228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 453*095cecbeSJohannes Doerfert if (S.empty()) 454*095cecbeSJohannes Doerfert return "<none>"; 4551228d42dSJohannes Doerfert S.pop_back(); 4561228d42dSJohannes Doerfert return S; 4571228d42dSJohannes Doerfert } 458