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/ADT/Triple.h"
12 #include "llvm/Support/TargetParser.h"
13 #include "llvm/Support/raw_ostream.h"
18 static llvm::SmallVector
<llvm::StringRef
, 4>
19 getAllPossibleAMDGPUTargetIDFeatures(const llvm::Triple
&T
,
20 llvm::StringRef Proc
) {
21 // Entries in returned vector should be in alphabetical order.
22 llvm::SmallVector
<llvm::StringRef
, 4> Ret
;
23 auto ProcKind
= T
.isAMDGCN() ? llvm::AMDGPU::parseArchAMDGCN(Proc
)
24 : llvm::AMDGPU::parseArchR600(Proc
);
25 if (ProcKind
== llvm::AMDGPU::GK_NONE
)
27 auto Features
= T
.isAMDGCN() ? llvm::AMDGPU::getArchAttrAMDGCN(ProcKind
)
28 : llvm::AMDGPU::getArchAttrR600(ProcKind
);
29 if (Features
& llvm::AMDGPU::FEATURE_SRAMECC
)
30 Ret
.push_back("sramecc");
31 if (Features
& llvm::AMDGPU::FEATURE_XNACK
)
32 Ret
.push_back("xnack");
36 llvm::SmallVector
<llvm::StringRef
, 4>
37 getAllPossibleTargetIDFeatures(const llvm::Triple
&T
,
38 llvm::StringRef Processor
) {
39 llvm::SmallVector
<llvm::StringRef
, 4> Ret
;
41 return getAllPossibleAMDGPUTargetIDFeatures(T
, Processor
);
45 /// Returns canonical processor name or empty string if \p Processor is invalid.
46 static llvm::StringRef
getCanonicalProcessorName(const llvm::Triple
&T
,
47 llvm::StringRef Processor
) {
49 return llvm::AMDGPU::getCanonicalArchName(T
, Processor
);
53 llvm::StringRef
getProcessorFromTargetID(const llvm::Triple
&T
,
54 llvm::StringRef TargetID
) {
55 auto Split
= TargetID
.split(':');
56 return getCanonicalProcessorName(T
, Split
.first
);
59 // Parse a target ID with format checking only. Do not check whether processor
60 // name or features are valid for the processor.
62 // A target ID is a processor name followed by a list of target features
63 // delimited by colon. Each target feature is a string post-fixed by a plus
64 // or minus sign, e.g. gfx908:sramecc+:xnack-.
65 static llvm::Optional
<llvm::StringRef
>
66 parseTargetIDWithFormatCheckingOnly(llvm::StringRef TargetID
,
67 llvm::StringMap
<bool> *FeatureMap
) {
68 llvm::StringRef Processor
;
71 return llvm::StringRef();
73 auto Split
= TargetID
.split(':');
74 Processor
= Split
.first
;
75 if (Processor
.empty())
78 auto Features
= Split
.second
;
82 llvm::StringMap
<bool> LocalFeatureMap
;
84 FeatureMap
= &LocalFeatureMap
;
86 while (!Features
.empty()) {
87 auto Splits
= Features
.split(':');
88 auto Sign
= Splits
.first
.back();
89 auto Feature
= Splits
.first
.drop_back();
90 if (Sign
!= '+' && Sign
!= '-')
92 bool IsOn
= Sign
== '+';
93 auto Loc
= FeatureMap
->find(Feature
);
94 // Each feature can only show up at most once in target ID.
95 if (Loc
!= FeatureMap
->end())
97 (*FeatureMap
)[Feature
] = IsOn
;
98 Features
= Splits
.second
;
103 llvm::Optional
<llvm::StringRef
>
104 parseTargetID(const llvm::Triple
&T
, llvm::StringRef TargetID
,
105 llvm::StringMap
<bool> *FeatureMap
) {
106 auto OptionalProcessor
=
107 parseTargetIDWithFormatCheckingOnly(TargetID
, FeatureMap
);
109 if (!OptionalProcessor
)
112 llvm::StringRef Processor
= getCanonicalProcessorName(T
, *OptionalProcessor
);
113 if (Processor
.empty())
116 llvm::SmallSet
<llvm::StringRef
, 4> AllFeatures
;
117 for (auto &&F
: getAllPossibleTargetIDFeatures(T
, Processor
))
118 AllFeatures
.insert(F
);
120 for (auto &&F
: *FeatureMap
)
121 if (!AllFeatures
.count(F
.first()))
127 // A canonical target ID is a target ID containing a canonical processor name
128 // and features in alphabetical order.
129 std::string
getCanonicalTargetID(llvm::StringRef Processor
,
130 const llvm::StringMap
<bool> &Features
) {
131 std::string TargetID
= Processor
.str();
132 std::map
<const llvm::StringRef
, bool> OrderedMap
;
133 for (const auto &F
: Features
)
134 OrderedMap
[F
.first()] = F
.second
;
135 for (auto F
: OrderedMap
)
136 TargetID
= TargetID
+ ':' + F
.first
.str() + (F
.second
? "+" : "-");
140 // For a specific processor, a feature either shows up in all target IDs, or
141 // does not show up in any target IDs. Otherwise the target ID combination
143 llvm::Optional
<std::pair
<llvm::StringRef
, llvm::StringRef
>>
144 getConflictTargetIDCombination(const std::set
<llvm::StringRef
> &TargetIDs
) {
146 llvm::StringRef TargetID
;
147 llvm::StringMap
<bool> Features
;
149 llvm::StringMap
<Info
> FeatureMap
;
150 for (auto &&ID
: TargetIDs
) {
151 llvm::StringMap
<bool> Features
;
152 llvm::StringRef Proc
= *parseTargetIDWithFormatCheckingOnly(ID
, &Features
);
153 auto Loc
= FeatureMap
.find(Proc
);
154 if (Loc
== FeatureMap
.end())
155 FeatureMap
[Proc
] = Info
{ID
, Features
};
157 auto &ExistingFeatures
= Loc
->second
.Features
;
158 if (llvm::any_of(Features
, [&](auto &F
) {
159 return ExistingFeatures
.count(F
.first()) == 0;
161 return std::make_pair(Loc
->second
.TargetID
, ID
);