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