LLVM 19.0.0git
AArch64TargetParser.cpp
Go to the documentation of this file.
1//===-- AArch64TargetParser - Parser for AArch64 features -------*- C++ -*-===//
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//
9// This file implements a target parser to recognise AArch64 hardware features
10// such as FPU/CPU/ARCH and extension names.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/Support/Debug.h"
16#include "llvm/Support/Format.h"
20#include <cctype>
21
22#define DEBUG_TYPE "target-parser"
23
24using namespace llvm;
25
26static unsigned checkArchVersion(llvm::StringRef Arch) {
27 if (Arch.size() >= 2 && Arch[0] == 'v' && std::isdigit(Arch[1]))
28 return (Arch[1] - 48);
29 return 0;
30}
31
33 if (CPU == "generic")
34 return &ARMV8A;
35
36 // Note: this now takes cpu aliases into account
37 std::optional<CpuInfo> Cpu = parseCpu(CPU);
38 if (!Cpu)
39 return nullptr;
40 return &Cpu->Arch;
41}
42
43std::optional<AArch64::ArchInfo> AArch64::ArchInfo::findBySubArch(StringRef SubArch) {
44 for (const auto *A : AArch64::ArchInfos)
45 if (A->getSubArch() == SubArch)
46 return *A;
47 return {};
48}
49
51 uint64_t FeaturesMask = 0;
52 for (const StringRef &FeatureStr : FeatureStrs) {
53 if (auto Ext = parseArchExtension(FeatureStr))
54 FeaturesMask |= (1ULL << Ext->CPUFeature);
55 }
56 return FeaturesMask;
57}
58
60 const AArch64::ExtensionBitset &InputExts,
61 std::vector<StringRef> &Features) {
62 for (const auto &E : Extensions)
63 /* INVALID and NONE have no feature name. */
64 if (InputExts.test(E.ID) && !E.Feature.empty())
65 Features.push_back(E.Feature);
66
67 return true;
68}
69
71 for (const auto &A : CpuAliases)
72 if (A.AltName == Name)
73 return A.Name;
74 return Name;
75}
76
78 bool IsNegated = ArchExt.starts_with("no");
79 StringRef ArchExtBase = IsNegated ? ArchExt.drop_front(2) : ArchExt;
80
81 if (auto AE = parseArchExtension(ArchExtBase)) {
82 // Note: the returned string can be empty.
83 return IsNegated ? AE->NegFeature : AE->Feature;
84 }
85
86 return StringRef();
87}
88
90 for (const auto &C : CpuInfos)
91 Values.push_back(C.Name);
92
93 for (const auto &Alias : CpuAliases)
94 Values.push_back(Alias.AltName);
95}
96
98 return TT.isAndroid() || TT.isOSDarwin() || TT.isOSFuchsia() ||
99 TT.isOSWindows() || TT.isOHOSFamily();
100}
101
102// Allows partial match, ex. "v8a" matches "armv8a".
105 if (checkArchVersion(Arch) < 8)
106 return {};
107
109 for (const auto *A : ArchInfos) {
110 if (A->Name.ends_with(Syn))
111 return A;
112 }
113 return {};
114}
115
116std::optional<AArch64::ExtensionInfo>
118 for (const auto &A : Extensions) {
119 if (ArchExt == A.Name || ArchExt == A.Alias)
120 return A;
121 }
122 return {};
123}
124
125std::optional<AArch64::CpuInfo> AArch64::parseCpu(StringRef Name) {
126 // Resolve aliases first.
128
129 // Then find the CPU name.
130 for (const auto &C : CpuInfos)
131 if (Name == C.Name)
132 return C;
133
134 return {};
135}
136
138 outs() << "All available -march extensions for AArch64\n\n"
139 << " " << left_justify("Name", 20)
140 << (DescMap.empty() ? "\n" : "Description\n");
141 for (const auto &Ext : Extensions) {
142 // Extensions without a feature cannot be used with -march.
143 if (!Ext.Feature.empty()) {
144 std::string Description = DescMap[Ext.Name].str();
145 outs() << " "
146 << format(Description.empty() ? "%s\n" : "%-20s%s\n",
147 Ext.Name.str().c_str(), Description.c_str());
148 }
149 }
150}
151
153lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID) {
154 for (const auto &E : llvm::AArch64::Extensions)
155 if (E.ID == ExtID)
156 return E;
157 llvm_unreachable("Invalid extension ID");
158}
159
160void AArch64::ExtensionSet::enable(ArchExtKind E) {
161 if (Enabled.test(E))
162 return;
163
164 LLVM_DEBUG(llvm::dbgs() << "Enable " << lookupExtensionByID(E).Name << "\n");
165
166 Touched.set(E);
167 Enabled.set(E);
168
169 // Recursively enable all features that this one depends on. This handles all
170 // of the simple cases, where the behaviour doesn't depend on the base
171 // architecture version.
172 for (auto Dep : ExtensionDependencies)
173 if (E == Dep.Later)
174 enable(Dep.Earlier);
175
176 // Special cases for dependencies which vary depending on the base
177 // architecture version.
178 if (BaseArch) {
179 // +fp16 implies +fp16fml for v8.4A+, but not v9.0-A+
180 if (E == AEK_FP16 && BaseArch->is_superset(ARMV8_4A) &&
181 !BaseArch->is_superset(ARMV9A))
182 enable(AEK_FP16FML);
183
184 // For all architectures, +crypto enables +aes and +sha2.
185 if (E == AEK_CRYPTO) {
186 enable(AEK_AES);
187 enable(AEK_SHA2);
188 }
189
190 // For v8.4A+ and v9.0A+, +crypto also enables +sha3 and +sm4.
191 if (E == AEK_CRYPTO && BaseArch->is_superset(ARMV8_4A)) {
192 enable(AEK_SHA3);
193 enable(AEK_SM4);
194 }
195 }
196}
197
199 // -crypto always disables aes, sha2, sha3 and sm4, even for architectures
200 // where the latter two would not be enabled by +crypto.
201 if (E == AEK_CRYPTO) {
202 disable(AEK_AES);
203 disable(AEK_SHA2);
204 disable(AEK_SHA3);
205 disable(AEK_SM4);
206 }
207
208 if (!Enabled.test(E))
209 return;
210
211 LLVM_DEBUG(llvm::dbgs() << "Disable " << lookupExtensionByID(E).Name << "\n");
212
213 Touched.set(E);
214 Enabled.reset(E);
215
216 // Recursively disable all features that depends on this one.
217 for (auto Dep : ExtensionDependencies)
218 if (E == Dep.Earlier)
219 disable(Dep.Later);
220}
221
223 std::vector<StringRef> &Features) const {
224 if (BaseArch && !BaseArch->ArchFeature.empty())
225 Features.push_back(BaseArch->ArchFeature);
226
227 for (const auto &E : Extensions) {
228 if (E.Feature.empty() || !Touched.test(E.ID))
229 continue;
230 if (Enabled.test(E.ID))
231 Features.push_back(E.Feature);
232 else
233 Features.push_back(E.NegFeature);
234 }
235}
236
238 LLVM_DEBUG(llvm::dbgs() << "addCPUDefaults(" << CPU.Name << ")\n");
239 BaseArch = &CPU.Arch;
240
242 for (const auto &E : Extensions)
243 if (CPUExtensions.test(E.ID))
244 enable(E.ID);
245}
246
248 LLVM_DEBUG(llvm::dbgs() << "addArchDefaults(" << Arch.Name << ")\n");
249 BaseArch = &Arch;
250
251 for (const auto &E : Extensions)
252 if (Arch.DefaultExts.test(E.ID))
253 enable(E.ID);
254}
255
257 LLVM_DEBUG(llvm::dbgs() << "parseModifier(" << Modifier << ")\n");
258
259 bool IsNegated = Modifier.starts_with("no");
260 StringRef ArchExt = IsNegated ? Modifier.drop_front(2) : Modifier;
261
262 if (auto AE = parseArchExtension(ArchExt)) {
263 if (AE->Feature.empty() || AE->NegFeature.empty())
264 return false;
265 if (IsNegated)
266 disable(AE->ID);
267 else
268 enable(AE->ID);
269 return true;
270 }
271 return false;
272}
273
275AArch64::getExtensionByID(AArch64::ArchExtKind ExtID) {
276 return lookupExtensionByID(ExtID);
277}
static unsigned checkArchVersion(llvm::StringRef Arch)
const llvm::AArch64::ExtensionInfo & lookupExtensionByID(llvm::AArch64::ArchExtKind ExtID)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_DEBUG(X)
Definition: Debug.h:101
std::string Name
static cl::opt< std::set< SPIRV::Extension::Extension >, false, SPIRVExtensionsParser > Extensions("spirv-ext", cl::desc("Specify list of enabled SPIR-V extensions"))
static bool Enabled
Definition: Statistic.cpp:46
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
constexpr bool test(unsigned I) const
Definition: Bitset.h:77
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
bool empty() const
Definition: StringMap.h:103
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:128
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:257
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:601
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void PrintSupportedExtensions(StringMap< StringRef > DescMap)
bool isX18ReservedByDefault(const Triple &TT)
StringRef getArchExtFeature(StringRef ArchExt)
std::optional< ExtensionInfo > parseArchExtension(StringRef Extension)
constexpr CpuInfo CpuInfos[]
std::optional< CpuInfo > parseCpu(StringRef Name)
constexpr ArchInfo ARMV8_4A
uint64_t getCpuSupportsMask(ArrayRef< StringRef > FeatureStrs)
const ArchInfo * parseArch(StringRef Arch)
const ArchInfo * getArchForCpu(StringRef CPU)
constexpr ArchInfo ARMV8A
constexpr ArchInfo ARMV9A
void fillValidCPUArchList(SmallVectorImpl< StringRef > &Values)
constexpr ExtensionDependency ExtensionDependencies[]
const ExtensionInfo & getExtensionByID(ArchExtKind(ExtID))
constexpr Alias CpuAliases[]
static constexpr std::array< const ArchInfo *, 17 > ArchInfos
StringRef resolveCPUAlias(StringRef CPU)
bool getExtensionFeatures(const AArch64::ExtensionBitset &Extensions, std::vector< StringRef > &Features)
StringRef getCanonicalArchName(StringRef Arch)
MArch is expected to be of the form (arm|thumb)?(eb)?(v.
StringRef getArchSynonym(StringRef Arch)
Converts e.g. "armv8" -> "armv8-a".
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
raw_fd_ostream & outs()
This returns a reference to a raw_fd_ostream for standard output.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:125
FormattedString left_justify(StringRef Str, unsigned Width)
left_justify - append spaces after string so total output is Width characters.
Definition: Format.h:146
AArch64::ExtensionBitset DefaultExts
static std::optional< ArchInfo > findBySubArch(StringRef SubArch)
AArch64::ExtensionBitset getImpliedExtensions() const
void addCPUDefaults(const CpuInfo &CPU)
void toLLVMFeatureList(std::vector< StringRef > &Features) const
bool parseModifier(StringRef Modifier)
void addArchDefaults(const ArchInfo &Arch)