xref: /llvm-project/llvm/include/llvm/TargetParser/AArch64TargetParser.h (revision 831527a5ef63d24d056afc92509caf5ceb1d3682)
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 
14 #ifndef LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
15 #define LLVM_TARGETPARSER_AARCH64TARGETPARSER_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/Bitset.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringMap.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/VersionTuple.h"
23 #include "llvm/Support/raw_ostream.h"
24 #include "llvm/TargetParser/SubtargetFeature.h"
25 #include <array>
26 #include <set>
27 #include <vector>
28 
29 namespace llvm {
30 
31 class Triple;
32 
33 namespace AArch64 {
34 
35 struct ArchInfo;
36 struct CpuInfo;
37 
38 #include "llvm/TargetParser/AArch64CPUFeatures.inc"
39 #include "llvm/TargetParser/AArch64FeatPriorities.inc"
40 
41 static_assert(FEAT_MAX < 62,
42               "Number of features in CPUFeatures are limited to 62 entries");
43 
44 // Each ArchExtKind correponds directly to a possible -target-feature.
45 #define EMIT_ARCHEXTKIND_ENUM
46 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
47 
48 using ExtensionBitset = Bitset<AEK_NUM_EXTENSIONS>;
49 
50 // Represents an extension that can be enabled with -march=<arch>+<extension>.
51 // Typically these correspond to Arm Architecture extensions, unlike
52 // SubtargetFeature which may represent either an actual extension or some
53 // internal LLVM property.
54 struct ExtensionInfo {
55   StringRef UserVisibleName;      // Human readable name used in -march, -cpu
56                                   // and target func attribute, e.g. "profile".
57   std::optional<StringRef> Alias; // An alias for this extension, if one exists.
58   ArchExtKind ID;                 // Corresponding to the ArchExtKind, this
59                                   // extensions representation in the bitfield.
60   StringRef ArchFeatureName;      // The feature name defined by the
61                                   // Architecture, e.g. FEAT_AdvSIMD.
62   StringRef Description;          // The textual description of the extension.
63   StringRef PosTargetFeature;     // -target-feature/-mattr enable string,
64                                   // e.g. "+spe".
65   StringRef NegTargetFeature;     // -target-feature/-mattr disable string,
66                                   // e.g. "-spe".
67 };
68 
69 #define EMIT_EXTENSIONS
70 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
71 
72 struct FMVInfo {
73   StringRef Name;                // The target_version/target_clones spelling.
74   CPUFeatures FeatureBit;        // Index of the bit in the FMV feature bitset.
75   FeatPriorities PriorityBit;    // Index of the bit in the FMV priority bitset.
76   std::optional<ArchExtKind> ID; // The architecture extension to enable.
77   FMVInfo(StringRef Name, CPUFeatures FeatureBit, FeatPriorities PriorityBit,
78           std::optional<ArchExtKind> ID)
79       : Name(Name), FeatureBit(FeatureBit), PriorityBit(PriorityBit), ID(ID) {};
80 };
81 
82 const std::vector<FMVInfo> &getFMVInfo();
83 
84 // Represents a dependency between two architecture extensions. Later is the
85 // feature which was added to the architecture after Earlier, and expands the
86 // functionality provided by it. If Later is enabled, then Earlier will also be
87 // enabled. If Earlier is disabled, then Later will also be disabled.
88 struct ExtensionDependency {
89   ArchExtKind Earlier;
90   ArchExtKind Later;
91 };
92 
93 #define EMIT_EXTENSION_DEPENDENCIES
94 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
95 
96 enum ArchProfile { AProfile = 'A', RProfile = 'R', InvalidProfile = '?' };
97 
98 // Information about a specific architecture, e.g. V8.1-A
99 struct ArchInfo {
100   VersionTuple Version;  // Architecture version, major + minor.
101   ArchProfile Profile;   // Architecuture profile
102   StringRef Name;        // Name as supplied to -march e.g. "armv8.1-a"
103   StringRef ArchFeature; // Name as supplied to -target-feature, e.g. "+v8a"
104   AArch64::ExtensionBitset
105       DefaultExts; // bitfield of default extensions ArchExtKind
106 
107   bool operator==(const ArchInfo &Other) const {
108     return this->Name == Other.Name;
109   }
110   bool operator!=(const ArchInfo &Other) const {
111     return this->Name != Other.Name;
112   }
113 
114   // Defines the following partial order, indicating when an architecture is
115   // a superset of another:
116   //
117   // v9.6a > v9.5a > v9.4a > v9.3a > v9.2a > v9.1a > v9a;
118   //                   v       v       v       v       v
119   //                 v8.9a > v8.8a > v8.7a > v8.6a > v8.5a > v8.4a > ... > v8a;
120   //
121   // v8r has no relation to anything. This is used to determine which
122   // features to enable for a given architecture. See
123   // AArch64TargetInfo::setFeatureEnabled.
124   bool implies(const ArchInfo &Other) const {
125     if (this->Profile != Other.Profile)
126       return false; // ARMV8R
127     if (this->Version.getMajor() == Other.Version.getMajor()) {
128       return this->Version > Other.Version;
129     }
130     if (this->Version.getMajor() == 9 && Other.Version.getMajor() == 8) {
131       assert(this->Version.getMinor() && Other.Version.getMinor() &&
132              "AArch64::ArchInfo should have a minor version.");
133       return this->Version.getMinor().value_or(0) + 5 >=
134              Other.Version.getMinor().value_or(0);
135     }
136     return false;
137   }
138 
139   // True if this architecture is a superset of Other (including being equal to
140   // it).
141   bool is_superset(const ArchInfo &Other) const {
142     return (*this == Other) || implies(Other);
143   }
144 
145   // Return ArchFeature without the leading "+".
146   StringRef getSubArch() const { return ArchFeature.substr(1); }
147 
148   // Search for ArchInfo by SubArch name
149   static std::optional<ArchInfo> findBySubArch(StringRef SubArch);
150 };
151 
152 #define EMIT_ARCHITECTURES
153 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
154 
155 // Details of a specific CPU.
156 struct CpuInfo {
157   StringRef Name; // Name, as written for -mcpu.
158   const ArchInfo &Arch;
159   AArch64::ExtensionBitset
160       DefaultExtensions; // Default extensions for this CPU.
161 
162   AArch64::ExtensionBitset getImpliedExtensions() const {
163     return DefaultExtensions;
164   }
165 };
166 
167 #define EMIT_CPU_INFO
168 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
169 
170 struct ExtensionSet {
171   // Set of extensions which are currently enabled.
172   ExtensionBitset Enabled;
173   // Set of extensions which have been enabled or disabled at any point. Used
174   // to avoid cluttering the cc1 command-line with lots of unneeded features.
175   ExtensionBitset Touched;
176   // Base architecture version, which we need to know because some feature
177   // dependencies change depending on this.
178   const ArchInfo *BaseArch;
179 
180   ExtensionSet() : Enabled(), Touched(), BaseArch(nullptr) {}
181 
182   // Enable the given architecture extension, and any other extensions it
183   // depends on. Does not change the base architecture, or follow dependencies
184   // between features which are only related by required arcitecture versions.
185   void enable(ArchExtKind E);
186 
187   // Disable the given architecture extension, and any other extensions which
188   // depend on it. Does not change the base architecture, or follow
189   // dependencies between features which are only related by required
190   // arcitecture versions.
191   void disable(ArchExtKind E);
192 
193   // Add default extensions for the given CPU. Records the base architecture,
194   // to later resolve dependencies which depend on it.
195   void addCPUDefaults(const CpuInfo &CPU);
196 
197   // Add default extensions for the given architecture version. Records the
198   // base architecture, to later resolve dependencies which depend on it.
199   void addArchDefaults(const ArchInfo &Arch);
200 
201   // Add or remove a feature based on a modifier string. The string must be of
202   // the form "<name>" to enable a feature or "no<name>" to disable it. This
203   // will also enable or disable any features as required by the dependencies
204   // between them.
205   bool parseModifier(StringRef Modifier, const bool AllowNoDashForm = false);
206 
207   // Constructs a new ExtensionSet by toggling the corresponding bits for every
208   // feature in the \p Features list without expanding their dependencies. Used
209   // for reconstructing an ExtensionSet from the output of toLLVMFeatures().
210   // Features that are not recognized are pushed back to \p NonExtensions.
211   void reconstructFromParsedFeatures(const std::vector<std::string> &Features,
212                                      std::vector<std::string> &NonExtensions);
213 
214   // Convert the set of enabled extension to an LLVM feature list, appending
215   // them to Features.
216   template <typename T> void toLLVMFeatureList(std::vector<T> &Features) const {
217     if (BaseArch && !BaseArch->ArchFeature.empty())
218       Features.emplace_back(T(BaseArch->ArchFeature));
219 
220     for (const auto &E : Extensions) {
221       if (E.PosTargetFeature.empty() || !Touched.test(E.ID))
222         continue;
223       if (Enabled.test(E.ID))
224         Features.emplace_back(T(E.PosTargetFeature));
225       else
226         Features.emplace_back(T(E.NegTargetFeature));
227     }
228   }
229 
230   void dump() const;
231 };
232 
233 // Name alias.
234 struct Alias {
235   StringRef AltName;
236   StringRef Name;
237 };
238 
239 #define EMIT_CPU_ALIAS
240 #include "llvm/TargetParser/AArch64TargetParserDef.inc"
241 
242 const ExtensionInfo &getExtensionByID(ArchExtKind(ExtID));
243 
244 bool getExtensionFeatures(
245     const AArch64::ExtensionBitset &Extensions,
246     std::vector<StringRef> &Features);
247 
248 StringRef getArchExtFeature(StringRef ArchExt);
249 StringRef resolveCPUAlias(StringRef CPU);
250 
251 // Information by Name
252 const ArchInfo *getArchForCpu(StringRef CPU);
253 
254 // Parser
255 const ArchInfo *parseArch(StringRef Arch);
256 
257 // Return the extension which has the given -target-feature name.
258 std::optional<ExtensionInfo> targetFeatureToExtension(StringRef TargetFeature);
259 
260 // Parse a name as defined by the Extension class in tablegen.
261 std::optional<ExtensionInfo> parseArchExtension(StringRef Extension);
262 
263 // Parse a name as defined by the FMVInfo class in tablegen.
264 std::optional<FMVInfo> parseFMVExtension(StringRef Extension);
265 
266 // Given the name of a CPU or alias, return the correponding CpuInfo.
267 std::optional<CpuInfo> parseCpu(StringRef Name);
268 // Used by target parser tests
269 void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values);
270 
271 bool isX18ReservedByDefault(const Triple &TT);
272 
273 // For a given set of feature names, which can be either target-features, or
274 // fmv-features metadata, expand their dependencies and then return a bitmask
275 // corresponding to the entries of AArch64::FeatPriorities.
276 uint64_t getFMVPriority(ArrayRef<StringRef> Features);
277 
278 // For a given set of FMV feature names, expand their dependencies and then
279 // return a bitmask corresponding to the entries of AArch64::CPUFeatures.
280 // The values in CPUFeatures are not bitmasks themselves, they are sequential
281 // (0, 1, 2, 3, ...). The resulting bitmask is used at runtime to test whether
282 // a certain FMV feature is available on the host.
283 uint64_t getCpuSupportsMask(ArrayRef<StringRef> Features);
284 
285 void PrintSupportedExtensions();
286 
287 void printEnabledExtensions(const std::set<StringRef> &EnabledFeatureNames);
288 
289 } // namespace AArch64
290 } // namespace llvm
291 
292 #endif
293