clang 24.0.0git
TargetID.cpp
Go to the documentation of this file.
1//===--- TargetID.cpp - Utilities for parsing target ID -------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/SmallSet.h"
13#include "llvm/ADT/SmallVector.h"
14#include "llvm/Support/Path.h"
15#include "llvm/TargetParser/AMDGPUTargetParser.h"
16#include "llvm/TargetParser/Triple.h"
17#include <map>
18#include <optional>
19#include <string>
20
21namespace clang {
22
25 llvm::StringRef Proc) {
26 // Entries in returned vector should be in alphabetical order.
28 if (!T.isAMDGCN())
29 return Ret;
30 llvm::AMDGPU::GPUKind ProcKind = llvm::AMDGPU::parseArchAMDGCN(Proc);
31 if (ProcKind == llvm::AMDGPU::GK_NONE)
32 return Ret;
33 const llvm::AMDGPU::AMDGPUFeatureBitset &Features =
34 llvm::AMDGPU::getFeatureBitset(ProcKind);
35 // Only allow features in target IDs if the processor supports on/off modes.
36 if (Features.test(llvm::AMDGPU::FEAT_SRAMECC_ON_OFF_MODES))
37 Ret.push_back("sramecc");
38 if (Features.test(llvm::AMDGPU::FEAT_XNACK_ON_OFF_MODES))
39 Ret.push_back("xnack");
40 return Ret;
41}
42
45 llvm::StringRef Processor) {
47 if (T.isAMDGPU())
48 return getAllPossibleAMDGPUTargetIDFeatures(T, Processor);
49 return Ret;
50}
51
52/// Returns canonical processor name or empty string if \p Processor is invalid.
53static llvm::StringRef getCanonicalProcessorName(const llvm::Triple &T,
54 llvm::StringRef Processor) {
55 if (!T.isAMDGPU())
56 return Processor;
57
58 if (llvm::StringRef Name = llvm::AMDGPU::getCanonicalArchName(T, Processor);
59 !Name.empty())
60 return Name;
61
62 // Accept the AMDGPU subarch triple spelling (e.g. "amdgpu9.00") as an alias
63 // for the corresponding gfx processor.
65 getSubArchOffloadArch(llvm::Triple::parseSubArch(Processor));
66 if (Arch.isUnknown())
67 return {};
69}
70
71llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T,
72 llvm::StringRef TargetID) {
73 auto Split = TargetID.split(':');
74 return getCanonicalProcessorName(T, Split.first);
75}
76
77// Parse a target ID with format checking only. Do not check whether processor
78// name or features are valid for the processor.
79//
80// A target ID is a processor name followed by a list of target features
81// delimited by colon. Each target feature is a string post-fixed by a plus
82// or minus sign, e.g. gfx908:sramecc+:xnack-.
83static std::optional<llvm::StringRef>
84parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID,
85 llvm::StringMap<bool> *FeatureMap) {
86 llvm::StringRef Processor;
87
88 if (TargetID.empty())
89 return llvm::StringRef();
90
91 auto Split = TargetID.split(':');
92 Processor = Split.first;
93 if (Processor.empty())
94 return std::nullopt;
95
96 auto Features = Split.second;
97 if (Features.empty())
98 return Processor;
99
100 llvm::StringMap<bool> LocalFeatureMap;
101 if (!FeatureMap)
102 FeatureMap = &LocalFeatureMap;
103
104 while (!Features.empty()) {
105 auto Splits = Features.split(':');
106 if (Splits.first.empty())
107 return std::nullopt;
108 auto Sign = Splits.first.back();
109 auto Feature = Splits.first.drop_back();
110 if (Sign != '+' && Sign != '-')
111 return std::nullopt;
112 bool IsOn = Sign == '+';
113 // Each feature can only show up at most once in target ID.
114 if (!FeatureMap->try_emplace(Feature, IsOn).second)
115 return std::nullopt;
116 Features = Splits.second;
117 }
118 return Processor;
119}
120
121std::optional<llvm::StringRef>
122parseTargetID(const llvm::Triple &T, llvm::StringRef TargetID,
123 llvm::StringMap<bool> *FeatureMap) {
124 auto OptionalProcessor =
125 parseTargetIDWithFormatCheckingOnly(TargetID, FeatureMap);
126
127 if (!OptionalProcessor)
128 return std::nullopt;
129
130 llvm::StringRef Processor = getCanonicalProcessorName(T, *OptionalProcessor);
131 if (Processor.empty())
132 return std::nullopt;
133
134 llvm::SmallSet<llvm::StringRef, 4> AllFeatures(
135 llvm::from_range, getAllPossibleTargetIDFeatures(T, Processor));
136
137 for (auto &&F : *FeatureMap)
138 if (!AllFeatures.count(F.first()))
139 return std::nullopt;
140
141 return Processor;
142}
143
144// A canonical target ID is a target ID containing a canonical processor name
145// and features in alphabetical order.
146std::string getCanonicalTargetID(llvm::StringRef Processor,
147 const llvm::StringMap<bool> &Features) {
148 std::string TargetID = Processor.str();
149 std::map<const llvm::StringRef, bool> OrderedMap;
150 for (const auto &F : Features)
151 OrderedMap[F.first()] = F.second;
152 for (const auto &F : OrderedMap)
153 TargetID = TargetID + ':' + F.first.str() + (F.second ? "+" : "-");
154 return TargetID;
155}
156
157// For a specific processor, a feature either shows up in all target IDs, or
158// does not show up in any target IDs. Otherwise the target ID combination
159// is invalid.
160std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
161getConflictTargetIDCombination(const std::set<llvm::StringRef> &TargetIDs) {
162 struct Info {
163 llvm::StringRef TargetID;
164 llvm::StringMap<bool> Features;
165 Info(llvm::StringRef TargetID, const llvm::StringMap<bool> &Features)
166 : TargetID(TargetID), Features(Features) {}
167 };
168 llvm::StringMap<Info> FeatureMap;
169 for (auto &&ID : TargetIDs) {
170 llvm::StringMap<bool> Features;
171 llvm::StringRef Proc = *parseTargetIDWithFormatCheckingOnly(ID, &Features);
172 auto [Loc, Inserted] = FeatureMap.try_emplace(Proc, ID, Features);
173 if (!Inserted) {
174 auto &ExistingFeatures = Loc->second.Features;
175 if (llvm::any_of(Features, [&](auto &F) {
176 return ExistingFeatures.count(F.first()) == 0;
177 }))
178 return std::make_pair(Loc->second.TargetID, ID);
179 }
180 }
181 return std::nullopt;
182}
183
184bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested) {
185 llvm::StringMap<bool> ProvidedFeatures, RequestedFeatures;
186 llvm::StringRef ProvidedProc =
187 *parseTargetIDWithFormatCheckingOnly(Provided, &ProvidedFeatures);
188 llvm::StringRef RequestedProc =
189 *parseTargetIDWithFormatCheckingOnly(Requested, &RequestedFeatures);
190 if (ProvidedProc != RequestedProc)
191 return false;
192 for (const auto &F : ProvidedFeatures) {
193 auto Loc = RequestedFeatures.find(F.first());
194 // The default (unspecified) value of a feature is 'All', which can match
195 // either 'On' or 'Off'.
196 if (Loc == RequestedFeatures.end())
197 return false;
198 // If a feature is specified, it must have exact match.
199 if (Loc->second != F.second)
200 return false;
201 }
202 return true;
203}
204
205std::string sanitizeTargetIDInFileName(llvm::StringRef TargetID) {
206 std::string FileName = TargetID.str();
207 if (llvm::sys::path::is_style_windows(llvm::sys::path::Style::native))
208 llvm::replace(FileName, ':', '@');
209 return FileName;
210}
211
212std::string normalizeForBundler(const llvm::Triple &OrigT,
213 llvm::StringRef BoundArch) {
214 llvm::Triple T(OrigT);
215 bool HasTargetID = !BoundArch.empty();
216
217 // FIXME: Short-term hack. The HIP runtime hardcodes the legacy
218 // "amdgcn-amd-amdhsa--" prefix when parsing the target IDs embedded in the
219 // fatbin bundle, so force it.
220 if (HasTargetID && T.isAMDGCN()) {
221 return ("amdgcn-" + T.getVendorName() + "-" + T.getOSName() + "-" +
222 T.getEnvironmentName())
223 .str();
224 }
225
226 return HasTargetID ? (T.getArchName() + "-" + T.getVendorName() + "-" +
227 T.getOSName() + "-" + T.getEnvironmentName())
228 .str()
229 : T.normalize(llvm::Triple::CanonicalForm::FOUR_IDENT);
230}
231
232} // namespace clang
A processor an offloading action can target.
Definition OffloadArch.h:32
Top level wrappers for InstallAPI frontend operations.
static llvm::SmallVector< llvm::StringRef, 4 > getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple &T, llvm::StringRef Proc)
Definition TargetID.cpp:24
std::optional< llvm::StringRef > parseTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch, llvm::StringMap< bool > *FeatureMap)
Parse a target ID to get processor and feature map.
Definition TargetID.cpp:122
OffloadArch getSubArchOffloadArch(llvm::Triple::SubArchType SubArch)
static std::optional< llvm::StringRef > parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID, llvm::StringMap< bool > *FeatureMap)
Definition TargetID.cpp:84
std::string sanitizeTargetIDInFileName(llvm::StringRef TargetID)
Sanitize a target ID string for use in a file name.
Definition TargetID.cpp:205
llvm::StringRef getProcessorFromTargetID(const llvm::Triple &T, llvm::StringRef OffloadArch)
Get processor name from target ID.
Definition TargetID.cpp:71
std::optional< std::pair< llvm::StringRef, llvm::StringRef > > getConflictTargetIDCombination(const std::set< llvm::StringRef > &TargetIDs)
Get the conflicted pair of target IDs for a compilation or a bundled code object, assuming TargetIDs ...
Definition TargetID.cpp:161
static llvm::StringRef getCanonicalProcessorName(const llvm::Triple &T, llvm::StringRef Processor)
Returns canonical processor name or empty string if Processor is invalid.
Definition TargetID.cpp:53
std::string normalizeForBundler(const llvm::Triple &T, llvm::StringRef BoundArch)
Constructs the normalized triple string used inside an offload bundle entry ID for device triple T.
Definition TargetID.cpp:212
bool isCompatibleTargetID(llvm::StringRef Provided, llvm::StringRef Requested)
Check whether the provided target ID is compatible with the requested target ID.
Definition TargetID.cpp:184
const FunctionProtoType * T
llvm::SmallVector< llvm::StringRef, 4 > getAllPossibleTargetIDFeatures(const llvm::Triple &T, llvm::StringRef Processor)
Get all feature strings that can be used in target ID for Processor.
Definition TargetID.cpp:44
const char * OffloadArchToString(OffloadArch A)
std::string getCanonicalTargetID(llvm::StringRef Processor, const llvm::StringMap< bool > &Features)
Returns canonical target ID, assuming Processor is canonical and all entries in Features are valid.
Definition TargetID.cpp:146
Represents a bound architecture for offload / multiple architecture compilation.
bool empty() const