Path: blob/main/contrib/llvm-project/clang/lib/Basic/TargetID.cpp
35233 views
//===--- TargetID.cpp - Utilities for parsing target ID -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Basic/TargetID.h"9#include "llvm/ADT/SmallSet.h"10#include "llvm/Support/raw_ostream.h"11#include "llvm/TargetParser/TargetParser.h"12#include "llvm/TargetParser/Triple.h"13#include <map>14#include <optional>1516namespace clang {1718static llvm::SmallVector<llvm::StringRef, 4>19getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple &T,20llvm::StringRef Proc) {21// Entries in returned vector should be in alphabetical order.22llvm::SmallVector<llvm::StringRef, 4> Ret;23auto ProcKind = T.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Proc)24: llvm::AMDGPU::parseArchR600(Proc);25if (ProcKind == llvm::AMDGPU::GK_NONE)26return Ret;27auto Features = T.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind)28: llvm::AMDGPU::getArchAttrR600(ProcKind);29if (Features & llvm::AMDGPU::FEATURE_SRAMECC)30Ret.push_back("sramecc");31if (Features & llvm::AMDGPU::FEATURE_XNACK)32Ret.push_back("xnack");33return Ret;34}3536llvm::SmallVector<llvm::StringRef, 4>37getAllPossibleTargetIDFeatures(const llvm::Triple &T,38llvm::StringRef Processor) {39llvm::SmallVector<llvm::StringRef, 4> Ret;40if (T.isAMDGPU())41return getAllPossibleAMDGPUTargetIDFeatures(T, Processor);42return Ret;43}4445/// Returns canonical processor name or empty string if \p Processor is invalid.46static llvm::StringRef getCanonicalProcessorName(const llvm::Triple &T,47llvm::StringRef Processor) {48if (T.isAMDGPU())49return llvm::AMDGPU::getCanonicalArchName(T, Processor);50return Processor;51}5253llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T,54llvm::StringRef TargetID) {55auto Split = TargetID.split(':');56return getCanonicalProcessorName(T, Split.first);57}5859// Parse a target ID with format checking only. Do not check whether processor60// name or features are valid for the processor.61//62// A target ID is a processor name followed by a list of target features63// delimited by colon. Each target feature is a string post-fixed by a plus64// or minus sign, e.g. gfx908:sramecc+:xnack-.65static std::optional<llvm::StringRef>66parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID,67llvm::StringMap<bool> *FeatureMap) {68llvm::StringRef Processor;6970if (TargetID.empty())71return llvm::StringRef();7273auto Split = TargetID.split(':');74Processor = Split.first;75if (Processor.empty())76return std::nullopt;7778auto Features = Split.second;79if (Features.empty())80return Processor;8182llvm::StringMap<bool> LocalFeatureMap;83if (!FeatureMap)84FeatureMap = &LocalFeatureMap;8586while (!Features.empty()) {87auto Splits = Features.split(':');88auto Sign = Splits.first.back();89auto Feature = Splits.first.drop_back();90if (Sign != '+' && Sign != '-')91return std::nullopt;92bool IsOn = Sign == '+';93auto Loc = FeatureMap->find(Feature);94// Each feature can only show up at most once in target ID.95if (Loc != FeatureMap->end())96return std::nullopt;97(*FeatureMap)[Feature] = IsOn;98Features = Splits.second;99}100return Processor;101}102103std::optional<llvm::StringRef>104parseTargetID(const llvm::Triple &T, llvm::StringRef TargetID,105llvm::StringMap<bool> *FeatureMap) {106auto OptionalProcessor =107parseTargetIDWithFormatCheckingOnly(TargetID, FeatureMap);108109if (!OptionalProcessor)110return std::nullopt;111112llvm::StringRef Processor = getCanonicalProcessorName(T, *OptionalProcessor);113if (Processor.empty())114return std::nullopt;115116llvm::SmallSet<llvm::StringRef, 4> AllFeatures;117for (auto &&F : getAllPossibleTargetIDFeatures(T, Processor))118AllFeatures.insert(F);119120for (auto &&F : *FeatureMap)121if (!AllFeatures.count(F.first()))122return std::nullopt;123124return Processor;125}126127// A canonical target ID is a target ID containing a canonical processor name128// and features in alphabetical order.129std::string getCanonicalTargetID(llvm::StringRef Processor,130const llvm::StringMap<bool> &Features) {131std::string TargetID = Processor.str();132std::map<const llvm::StringRef, bool> OrderedMap;133for (const auto &F : Features)134OrderedMap[F.first()] = F.second;135for (const auto &F : OrderedMap)136TargetID = TargetID + ':' + F.first.str() + (F.second ? "+" : "-");137return TargetID;138}139140// For a specific processor, a feature either shows up in all target IDs, or141// does not show up in any target IDs. Otherwise the target ID combination142// is invalid.143std::optional<std::pair<llvm::StringRef, llvm::StringRef>>144getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs) {145struct Info {146llvm::StringRef TargetID;147llvm::StringMap<bool> Features;148};149llvm::StringMap<Info> FeatureMap;150for (auto &&ID : TargetIDs) {151llvm::StringMap<bool> Features;152llvm::StringRef Proc = *parseTargetIDWithFormatCheckingOnly(ID, &Features);153auto Loc = FeatureMap.find(Proc);154if (Loc == FeatureMap.end())155FeatureMap[Proc] = Info{ID, Features};156else {157auto &ExistingFeatures = Loc->second.Features;158if (llvm::any_of(Features, [&](auto &F) {159return ExistingFeatures.count(F.first()) == 0;160}))161return std::make_pair(Loc->second.TargetID, ID);162}163}164return std::nullopt;165}166167bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested) {168llvm::StringMap<bool> ProvidedFeatures, RequestedFeatures;169llvm::StringRef ProvidedProc =170*parseTargetIDWithFormatCheckingOnly(Provided, &ProvidedFeatures);171llvm::StringRef RequestedProc =172*parseTargetIDWithFormatCheckingOnly(Requested, &RequestedFeatures);173if (ProvidedProc != RequestedProc)174return false;175for (const auto &F : ProvidedFeatures) {176auto Loc = RequestedFeatures.find(F.first());177// The default (unspecified) value of a feature is 'All', which can match178// either 'On' or 'Off'.179if (Loc == RequestedFeatures.end())180return false;181// If a feature is specified, it must have exact match.182if (Loc->second != F.second)183return false;184}185return true;186}187188} // namespace clang189190191