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