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: 217ae5d3e8cSSimon Pilgrim Score += (1ULL << (NoConstructTraits + 0)); 218c953409fSJohannes Doerfert continue; 219c953409fSJohannes Doerfert case TraitSelector::device_arch: 220ae5d3e8cSSimon Pilgrim Score += (1ULL << (NoConstructTraits + 1)); 221c953409fSJohannes Doerfert continue; 222c953409fSJohannes Doerfert case TraitSelector::device_isa: 223ae5d3e8cSSimon Pilgrim Score += (1ULL << (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!"); 2377b6e49a2SDmitri Gribenko (void)Property; 238c953409fSJohannes Doerfert // ConstructMatches is the position p - 1 and we need 2^(p-1). 239ae5d3e8cSSimon Pilgrim Score += (1ULL << ConstructMatches[ConstructIdx++]); 240c953409fSJohannes Doerfert } 241c953409fSJohannes Doerfert 242c953409fSJohannes Doerfert LLVM_DEBUG(dbgs() << "[" << DEBUG_TYPE << "] Variant has a score of " << Score 243c953409fSJohannes Doerfert << "\n"); 244c953409fSJohannes Doerfert return Score; 2452dc45bf3SMartin Storsjö } 246c953409fSJohannes Doerfert 247c953409fSJohannes Doerfert int llvm::omp::getBestVariantMatchForContext( 248c953409fSJohannes Doerfert const SmallVectorImpl<VariantMatchInfo> &VMIs, const OMPContext &Ctx) { 249c953409fSJohannes Doerfert 250c953409fSJohannes Doerfert APInt BestScore(64, 0); 251c953409fSJohannes Doerfert int BestVMIIdx = -1; 252c953409fSJohannes Doerfert const VariantMatchInfo *BestVMI = nullptr; 253c953409fSJohannes Doerfert 254c953409fSJohannes Doerfert for (unsigned u = 0, e = VMIs.size(); u < e; ++u) { 255c953409fSJohannes Doerfert const VariantMatchInfo &VMI = VMIs[u]; 256c953409fSJohannes Doerfert 257c953409fSJohannes Doerfert SmallVector<unsigned, 8> ConstructMatches; 258c953409fSJohannes Doerfert // If the variant is not applicable its not the best. 259c953409fSJohannes Doerfert if (!isVariantApplicableInContextHelper(VMI, Ctx, &ConstructMatches)) 260c953409fSJohannes Doerfert continue; 261c953409fSJohannes Doerfert // Check if its clearly not the best. 262c953409fSJohannes Doerfert APInt Score = getVariantMatchScore(VMI, Ctx, ConstructMatches); 263c953409fSJohannes Doerfert if (Score.ult(BestScore)) 264c953409fSJohannes Doerfert continue; 265c953409fSJohannes Doerfert // Equal score need subset checks. 266c953409fSJohannes Doerfert if (Score.eq(BestScore)) { 267c953409fSJohannes Doerfert // Strict subset are never best. 268c953409fSJohannes Doerfert if (isStrictSubset(VMI, *BestVMI)) 269c953409fSJohannes Doerfert continue; 270c953409fSJohannes Doerfert // Same score and the current best is no strict subset so we keep it. 271c953409fSJohannes Doerfert if (!isStrictSubset(*BestVMI, VMI)) 272c953409fSJohannes Doerfert continue; 273c953409fSJohannes Doerfert } 274c953409fSJohannes Doerfert // New best found. 275c953409fSJohannes Doerfert BestVMI = &VMI; 276c953409fSJohannes Doerfert BestVMIIdx = u; 277c953409fSJohannes Doerfert BestScore = Score; 278c953409fSJohannes Doerfert } 279c953409fSJohannes Doerfert 280c953409fSJohannes Doerfert return BestVMIIdx; 281c953409fSJohannes Doerfert } 282c953409fSJohannes Doerfert 283c953409fSJohannes Doerfert TraitSet llvm::omp::getOpenMPContextTraitSetKind(StringRef S) { 284c953409fSJohannes Doerfert return StringSwitch<TraitSet>(S) 285c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) .Case(Str, TraitSet::Enum) 286c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 287c953409fSJohannes Doerfert .Default(TraitSet::invalid); 288c953409fSJohannes Doerfert } 289*1228d42dSJohannes Doerfert 290*1228d42dSJohannes Doerfert TraitSet 291*1228d42dSJohannes Doerfert llvm::omp::getOpenMPContextTraitSetForSelector(TraitSelector Selector) { 292*1228d42dSJohannes Doerfert switch (Selector) { 293*1228d42dSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 294*1228d42dSJohannes Doerfert case TraitSelector::Enum: \ 295*1228d42dSJohannes Doerfert return TraitSet::TraitSetEnum; 296*1228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 297*1228d42dSJohannes Doerfert } 298*1228d42dSJohannes Doerfert } 299c953409fSJohannes Doerfert TraitSet 300c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSetForProperty(TraitProperty Property) { 301c953409fSJohannes Doerfert switch (Property) { 302c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 303c953409fSJohannes Doerfert case TraitProperty::Enum: \ 304c953409fSJohannes Doerfert return TraitSet::TraitSetEnum; 305c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 306c953409fSJohannes Doerfert } 3072dc45bf3SMartin Storsjö llvm_unreachable("Unknown trait set!"); 308c953409fSJohannes Doerfert } 309c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSetName(TraitSet Kind) { 310c953409fSJohannes Doerfert switch (Kind) { 311c953409fSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) \ 312c953409fSJohannes Doerfert case TraitSet::Enum: \ 313c953409fSJohannes Doerfert return Str; 314c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 315c953409fSJohannes Doerfert } 316c953409fSJohannes Doerfert llvm_unreachable("Unknown trait set!"); 317c953409fSJohannes Doerfert } 318c953409fSJohannes Doerfert 319c953409fSJohannes Doerfert TraitSelector llvm::omp::getOpenMPContextTraitSelectorKind(StringRef S) { 320c953409fSJohannes Doerfert return StringSwitch<TraitSelector>(S) 321c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 322c953409fSJohannes Doerfert .Case(Str, TraitSelector::Enum) 323c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 324c953409fSJohannes Doerfert .Default(TraitSelector::invalid); 325c953409fSJohannes Doerfert } 326c953409fSJohannes Doerfert TraitSelector 327c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitSelectorForProperty(TraitProperty Property) { 328c953409fSJohannes Doerfert switch (Property) { 329c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 330c953409fSJohannes Doerfert case TraitProperty::Enum: \ 331c953409fSJohannes Doerfert return TraitSelector::TraitSelectorEnum; 332c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 333c953409fSJohannes Doerfert } 3342dc45bf3SMartin Storsjö llvm_unreachable("Unknown trait set!"); 335c953409fSJohannes Doerfert } 336c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitSelectorName(TraitSelector Kind) { 337c953409fSJohannes Doerfert switch (Kind) { 338c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 339c953409fSJohannes Doerfert case TraitSelector::Enum: \ 340c953409fSJohannes Doerfert return Str; 341c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 342c953409fSJohannes Doerfert } 343c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 344c953409fSJohannes Doerfert } 345c953409fSJohannes Doerfert 346*1228d42dSJohannes Doerfert TraitProperty llvm::omp::getOpenMPContextTraitPropertyKind(TraitSet Set, 347*1228d42dSJohannes Doerfert StringRef S) { 348c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 349*1228d42dSJohannes Doerfert if (Set == TraitSet::TraitSetEnum && Str == S) \ 350c953409fSJohannes Doerfert return TraitProperty::Enum; 351c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 352c953409fSJohannes Doerfert return TraitProperty::invalid; 353c953409fSJohannes Doerfert } 354c953409fSJohannes Doerfert TraitProperty 355c953409fSJohannes Doerfert llvm::omp::getOpenMPContextTraitPropertyForSelector(TraitSelector Selector) { 356c953409fSJohannes Doerfert return StringSwitch<TraitProperty>( 357c953409fSJohannes Doerfert getOpenMPContextTraitSelectorName(Selector)) 358c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 359c953409fSJohannes Doerfert .Case(Str, Selector == TraitSelector::TraitSelectorEnum \ 360c953409fSJohannes Doerfert ? TraitProperty::Enum \ 361c953409fSJohannes Doerfert : TraitProperty::invalid) 362c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 363c953409fSJohannes Doerfert .Default(TraitProperty::invalid); 364c953409fSJohannes Doerfert } 365c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyName(TraitProperty Kind) { 366c953409fSJohannes Doerfert switch (Kind) { 367c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 368c953409fSJohannes Doerfert case TraitProperty::Enum: \ 369c953409fSJohannes Doerfert return Str; 370c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 371c953409fSJohannes Doerfert } 372c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 373c953409fSJohannes Doerfert } 374c953409fSJohannes Doerfert StringRef llvm::omp::getOpenMPContextTraitPropertyFullName(TraitProperty Kind) { 375c953409fSJohannes Doerfert switch (Kind) { 376c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 377c953409fSJohannes Doerfert case TraitProperty::Enum: \ 378c953409fSJohannes Doerfert return "(" #TraitSetEnum "," #TraitSelectorEnum "," Str ")"; 379c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 380c953409fSJohannes Doerfert } 381c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 382c953409fSJohannes Doerfert } 383c953409fSJohannes Doerfert 384c953409fSJohannes Doerfert bool llvm::omp::isValidTraitSelectorForTraitSet(TraitSelector Selector, 385c953409fSJohannes Doerfert TraitSet Set, 386c953409fSJohannes Doerfert bool &AllowsTraitScore, 387c953409fSJohannes Doerfert bool &RequiresProperty) { 388c953409fSJohannes Doerfert AllowsTraitScore = Set != TraitSet::construct && Set != TraitSet::device; 389c953409fSJohannes Doerfert switch (Selector) { 390c953409fSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 391c953409fSJohannes Doerfert case TraitSelector::Enum: \ 392c953409fSJohannes Doerfert RequiresProperty = ReqProp; \ 393c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum; 394c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 395c953409fSJohannes Doerfert } 396c953409fSJohannes Doerfert llvm_unreachable("Unknown trait selector!"); 397c953409fSJohannes Doerfert } 398c953409fSJohannes Doerfert 399c953409fSJohannes Doerfert bool llvm::omp::isValidTraitPropertyForTraitSetAndSelector( 400c953409fSJohannes Doerfert TraitProperty Property, TraitSelector Selector, TraitSet Set) { 401c953409fSJohannes Doerfert switch (Property) { 402c953409fSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 403c953409fSJohannes Doerfert case TraitProperty::Enum: \ 404c953409fSJohannes Doerfert return Set == TraitSet::TraitSetEnum && \ 405c953409fSJohannes Doerfert Selector == TraitSelector::TraitSelectorEnum; 406c953409fSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 407c953409fSJohannes Doerfert } 408c953409fSJohannes Doerfert llvm_unreachable("Unknown trait property!"); 409c953409fSJohannes Doerfert } 410*1228d42dSJohannes Doerfert 411*1228d42dSJohannes Doerfert std::string llvm::omp::listOpenMPContextTraitSets() { 412*1228d42dSJohannes Doerfert std::string S; 413*1228d42dSJohannes Doerfert #define OMP_TRAIT_SET(Enum, Str) \ 414*1228d42dSJohannes Doerfert if (Str != "invalid") \ 415*1228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 416*1228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 417*1228d42dSJohannes Doerfert S.pop_back(); 418*1228d42dSJohannes Doerfert return S; 419*1228d42dSJohannes Doerfert } 420*1228d42dSJohannes Doerfert 421*1228d42dSJohannes Doerfert std::string llvm::omp::listOpenMPContextTraitSelectors(TraitSet Set) { 422*1228d42dSJohannes Doerfert std::string S; 423*1228d42dSJohannes Doerfert #define OMP_TRAIT_SELECTOR(Enum, TraitSetEnum, Str, ReqProp) \ 424*1228d42dSJohannes Doerfert if (TraitSet::TraitSetEnum == Set && Str != "Invalid") \ 425*1228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 426*1228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 427*1228d42dSJohannes Doerfert S.pop_back(); 428*1228d42dSJohannes Doerfert return S; 429*1228d42dSJohannes Doerfert } 430*1228d42dSJohannes Doerfert 431*1228d42dSJohannes Doerfert std::string 432*1228d42dSJohannes Doerfert llvm::omp::listOpenMPContextTraitProperties(TraitSet Set, 433*1228d42dSJohannes Doerfert TraitSelector Selector) { 434*1228d42dSJohannes Doerfert std::string S; 435*1228d42dSJohannes Doerfert #define OMP_TRAIT_PROPERTY(Enum, TraitSetEnum, TraitSelectorEnum, Str) \ 436*1228d42dSJohannes Doerfert if (TraitSet::TraitSetEnum == Set && \ 437*1228d42dSJohannes Doerfert TraitSelector::TraitSelectorEnum == Selector && Str != "invalid") \ 438*1228d42dSJohannes Doerfert S.append("'").append(Str).append("'").append(" "); 439*1228d42dSJohannes Doerfert #include "llvm/Frontend/OpenMP/OMPKinds.def" 440*1228d42dSJohannes Doerfert S.pop_back(); 441*1228d42dSJohannes Doerfert return S; 442*1228d42dSJohannes Doerfert } 443