1 //===--- TargetID.cpp - Utilities for parsing target ID -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Basic/TargetID.h"
10 #include "llvm/ADT/SmallSet.h"
11 #include "llvm/Support/raw_ostream.h"
12 #include "llvm/TargetParser/TargetParser.h"
13 #include "llvm/TargetParser/Triple.h"
19 static llvm::SmallVector
<llvm::StringRef
, 4>
20 getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple
&T
,
21 llvm::StringRef Proc
) {
22 // Entries in returned vector should be in alphabetical order.
23 llvm::SmallVector
<llvm::StringRef
, 4> Ret
;
24 auto ProcKind
= T
.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Proc
)
25 : llvm::AMDGPU::parseArchR600(Proc
);
26 if (ProcKind
== llvm::AMDGPU::GK_NONE
)
28 auto Features
= T
.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind
)
29 : llvm::AMDGPU::getArchAttrR600(ProcKind
);
30 if (Features
& llvm::AMDGPU::FEATURE_SRAMECC
)
31 Ret
.push_back("sramecc");
32 if (Features
& llvm::AMDGPU::FEATURE_XNACK
)
33 Ret
.push_back("xnack");
37 llvm::SmallVector
<llvm::StringRef
, 4>
38 getAllPossibleTargetIDFeatures(const llvm::Triple
&T
,
39 llvm::StringRef Processor
) {
40 llvm::SmallVector
<llvm::StringRef
, 4> Ret
;
42 return getAllPossibleAMDGPUTargetIDFeatures(T
, Processor
);
46 /// Returns canonical processor name or empty string if \p Processor is invalid.
47 static llvm::StringRef
getCanonicalProcessorName(const llvm::Triple
&T
,
48 llvm::StringRef Processor
) {
50 return llvm::AMDGPU::getCanonicalArchName(T
, Processor
);
54 llvm::StringRef
getProcessorFromTargetID(const llvm::Triple
&T
,
55 llvm::StringRef TargetID
) {
56 auto Split
= TargetID
.split(':');
57 return getCanonicalProcessorName(T
, Split
.first
);
60 // Parse a target ID with format checking only. Do not check whether processor
61 // name or features are valid for the processor.
63 // A target ID is a processor name followed by a list of target features
64 // delimited by colon. Each target feature is a string post-fixed by a plus
65 // or minus sign, e.g. gfx908:sramecc+:xnack-.
66 static std::optional
<llvm::StringRef
>
67 parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID
,
68 llvm::StringMap
<bool> *FeatureMap
) {
69 llvm::StringRef Processor
;
72 return llvm::StringRef();
74 auto Split
= TargetID
.split(':');
75 Processor
= Split
.first
;
76 if (Processor
.empty())
79 auto Features
= Split
.second
;
83 llvm::StringMap
<bool> LocalFeatureMap
;
85 FeatureMap
= &LocalFeatureMap
;
87 while (!Features
.empty()) {
88 auto Splits
= Features
.split(':');
89 auto Sign
= Splits
.first
.back();
90 auto Feature
= Splits
.first
.drop_back();
91 if (Sign
!= '+' && Sign
!= '-')
93 bool IsOn
= Sign
== '+';
94 auto Loc
= FeatureMap
->find(Feature
);
95 // Each feature can only show up at most once in target ID.
96 if (Loc
!= FeatureMap
->end())
98 (*FeatureMap
)[Feature
] = IsOn
;
99 Features
= Splits
.second
;
104 std::optional
<llvm::StringRef
>
105 parseTargetID(const llvm::Triple
&T
, llvm::StringRef TargetID
,
106 llvm::StringMap
<bool> *FeatureMap
) {
107 auto OptionalProcessor
=
108 parseTargetIDWithFormatCheckingOnly(TargetID
, FeatureMap
);
110 if (!OptionalProcessor
)
113 llvm::StringRef Processor
= getCanonicalProcessorName(T
, *OptionalProcessor
);
114 if (Processor
.empty())
117 llvm::SmallSet
<llvm::StringRef
, 4> AllFeatures
;
118 for (auto &&F
: getAllPossibleTargetIDFeatures(T
, Processor
))
119 AllFeatures
.insert(F
);
121 for (auto &&F
: *FeatureMap
)
122 if (!AllFeatures
.count(F
.first()))
128 // A canonical target ID is a target ID containing a canonical processor name
129 // and features in alphabetical order.
130 std::string
getCanonicalTargetID(llvm::StringRef Processor
,
131 const llvm::StringMap
<bool> &Features
) {
132 std::string TargetID
= Processor
.str();
133 std::map
<const llvm::StringRef
, bool> OrderedMap
;
134 for (const auto &F
: Features
)
135 OrderedMap
[F
.first()] = F
.second
;
136 for (const auto &F
: OrderedMap
)
137 TargetID
= TargetID
+ ':' + F
.first
.str() + (F
.second
? "+" : "-");
141 // For a specific processor, a feature either shows up in all target IDs, or
142 // does not show up in any target IDs. Otherwise the target ID combination
144 std::optional
<std::pair
<llvm::StringRef
, llvm::StringRef
>>
145 getConflictTargetIDCombination(const std::set
<llvm::StringRef
> &TargetIDs
) {
147 llvm::StringRef TargetID
;
148 llvm::StringMap
<bool> Features
;
150 llvm::StringMap
<Info
> FeatureMap
;
151 for (auto &&ID
: TargetIDs
) {
152 llvm::StringMap
<bool> Features
;
153 llvm::StringRef Proc
= *parseTargetIDWithFormatCheckingOnly(ID
, &Features
);
154 auto Loc
= FeatureMap
.find(Proc
);
155 if (Loc
== FeatureMap
.end())
156 FeatureMap
[Proc
] = Info
{ID
, Features
};
158 auto &ExistingFeatures
= Loc
->second
.Features
;
159 if (llvm::any_of(Features
, [&](auto &F
) {
160 return ExistingFeatures
.count(F
.first()) == 0;
162 return std::make_pair(Loc
->second
.TargetID
, ID
);
168 bool isCompatibleTargetID(llvm::StringRef Provided
, llvm::StringRef Requested
) {
169 llvm::StringMap
<bool> ProvidedFeatures
, RequestedFeatures
;
170 llvm::StringRef ProvidedProc
=
171 *parseTargetIDWithFormatCheckingOnly(Provided
, &ProvidedFeatures
);
172 llvm::StringRef RequestedProc
=
173 *parseTargetIDWithFormatCheckingOnly(Requested
, &RequestedFeatures
);
174 if (ProvidedProc
!= RequestedProc
)
176 for (const auto &F
: ProvidedFeatures
) {
177 auto Loc
= RequestedFeatures
.find(F
.first());
178 // The default (unspecified) value of a feature is 'All', which can match
179 // either 'On' or 'Off'.
180 if (Loc
== RequestedFeatures
.end())
182 // If a feature is specified, it must have exact match.
183 if (Loc
->second
!= F
.second
)