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