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