1 //===--- AArch64Subtarget.h - Define Subtarget for the AArch64 -*- 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 declares the AArch64 specific subclass of TargetSubtarget. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H 14 #define LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H 15 16 #include "AArch64FrameLowering.h" 17 #include "AArch64ISelLowering.h" 18 #include "AArch64InstrInfo.h" 19 #include "AArch64RegisterInfo.h" 20 #include "AArch64SelectionDAGInfo.h" 21 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 22 #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" 23 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 24 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 25 #include "llvm/CodeGen/RegisterBankInfo.h" 26 #include "llvm/CodeGen/TargetSubtargetInfo.h" 27 #include "llvm/IR/DataLayout.h" 28 #include <string> 29 30 #define GET_SUBTARGETINFO_HEADER 31 #include "AArch64GenSubtargetInfo.inc" 32 33 namespace llvm { 34 class GlobalValue; 35 class StringRef; 36 class Triple; 37 38 class AArch64Subtarget final : public AArch64GenSubtargetInfo { 39 public: 40 enum ARMProcFamilyEnum : uint8_t { 41 Others, 42 A64FX, 43 Ampere1, 44 AppleA7, 45 AppleA10, 46 AppleA11, 47 AppleA12, 48 AppleA13, 49 AppleA14, 50 Carmel, 51 CortexA35, 52 CortexA53, 53 CortexA55, 54 CortexA510, 55 CortexA57, 56 CortexA65, 57 CortexA72, 58 CortexA73, 59 CortexA75, 60 CortexA76, 61 CortexA77, 62 CortexA78, 63 CortexA78C, 64 CortexA710, 65 CortexR82, 66 CortexX1, 67 CortexX1C, 68 CortexX2, 69 ExynosM3, 70 Falkor, 71 Kryo, 72 NeoverseE1, 73 NeoverseN1, 74 NeoverseN2, 75 Neoverse512TVB, 76 NeoverseV1, 77 Saphira, 78 ThunderX2T99, 79 ThunderX, 80 ThunderXT81, 81 ThunderXT83, 82 ThunderXT88, 83 ThunderX3T110, 84 TSV110 85 }; 86 87 protected: 88 /// ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others. 89 ARMProcFamilyEnum ARMProcFamily = Others; 90 91 // Enable 64-bit vectorization in SLP. 92 unsigned MinVectorRegisterBitWidth = 64; 93 94 // Bool members corresponding to the SubtargetFeatures defined in tablegen 95 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 96 bool ATTRIBUTE = DEFAULT; 97 #include "AArch64GenSubtargetInfo.inc" 98 99 uint8_t MaxInterleaveFactor = 2; 100 uint8_t VectorInsertExtractBaseCost = 3; 101 uint16_t CacheLineSize = 0; 102 uint16_t PrefetchDistance = 0; 103 uint16_t MinPrefetchStride = 1; 104 unsigned MaxPrefetchIterationsAhead = UINT_MAX; 105 unsigned PrefFunctionLogAlignment = 0; 106 unsigned PrefLoopLogAlignment = 0; 107 unsigned MaxBytesForLoopAlignment = 0; 108 unsigned MaxJumpTableSize = 0; 109 110 // ReserveXRegister[i] - X#i is not available as a general purpose register. 111 BitVector ReserveXRegister; 112 113 // CustomCallUsedXRegister[i] - X#i call saved. 114 BitVector CustomCallSavedXRegs; 115 116 bool IsLittle; 117 118 unsigned MinSVEVectorSizeInBits; 119 unsigned MaxSVEVectorSizeInBits; 120 unsigned VScaleForTuning = 2; 121 122 /// TargetTriple - What processor and OS we're targeting. 123 Triple TargetTriple; 124 125 AArch64FrameLowering FrameLowering; 126 AArch64InstrInfo InstrInfo; 127 AArch64SelectionDAGInfo TSInfo; 128 AArch64TargetLowering TLInfo; 129 130 /// GlobalISel related APIs. 131 std::unique_ptr<CallLowering> CallLoweringInfo; 132 std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo; 133 std::unique_ptr<InstructionSelector> InstSelector; 134 std::unique_ptr<LegalizerInfo> Legalizer; 135 std::unique_ptr<RegisterBankInfo> RegBankInfo; 136 137 private: 138 /// initializeSubtargetDependencies - Initializes using CPUString and the 139 /// passed in feature string so that we can use initializer lists for 140 /// subtarget initialization. 141 AArch64Subtarget &initializeSubtargetDependencies(StringRef FS, 142 StringRef CPUString, 143 StringRef TuneCPUString); 144 145 /// Initialize properties based on the selected processor family. 146 void initializeProperties(); 147 148 public: 149 /// This constructor initializes the data members to match that 150 /// of the specified triple. 151 AArch64Subtarget(const Triple &TT, const std::string &CPU, 152 const std::string &TuneCPU, const std::string &FS, 153 const TargetMachine &TM, bool LittleEndian, 154 unsigned MinSVEVectorSizeInBitsOverride = 0, 155 unsigned MaxSVEVectorSizeInBitsOverride = 0); 156 157 // Getters for SubtargetFeatures defined in tablegen 158 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 159 bool GETTER() const { return ATTRIBUTE; } 160 #include "AArch64GenSubtargetInfo.inc" 161 162 const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override { 163 return &TSInfo; 164 } 165 const AArch64FrameLowering *getFrameLowering() const override { 166 return &FrameLowering; 167 } 168 const AArch64TargetLowering *getTargetLowering() const override { 169 return &TLInfo; 170 } 171 const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; } 172 const AArch64RegisterInfo *getRegisterInfo() const override { 173 return &getInstrInfo()->getRegisterInfo(); 174 } 175 const CallLowering *getCallLowering() const override; 176 const InlineAsmLowering *getInlineAsmLowering() const override; 177 InstructionSelector *getInstructionSelector() const override; 178 const LegalizerInfo *getLegalizerInfo() const override; 179 const RegisterBankInfo *getRegBankInfo() const override; 180 const Triple &getTargetTriple() const { return TargetTriple; } 181 bool enableMachineScheduler() const override { return true; } 182 bool enablePostRAScheduler() const override { return usePostRAScheduler(); } 183 184 /// Returns ARM processor family. 185 /// Avoid this function! CPU specifics should be kept local to this class 186 /// and preferably modeled with SubtargetFeatures or properties in 187 /// initializeProperties(). 188 ARMProcFamilyEnum getProcFamily() const { 189 return ARMProcFamily; 190 } 191 192 bool isXRaySupported() const override { return true; } 193 194 unsigned getMinVectorRegisterBitWidth() const { 195 return MinVectorRegisterBitWidth; 196 } 197 198 bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; } 199 unsigned getNumXRegisterReserved() const { return ReserveXRegister.count(); } 200 bool isXRegCustomCalleeSaved(size_t i) const { 201 return CustomCallSavedXRegs[i]; 202 } 203 bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); } 204 205 /// Return true if the CPU supports any kind of instruction fusion. 206 bool hasFusion() const { 207 return hasArithmeticBccFusion() || hasArithmeticCbzFusion() || 208 hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCCSelect() || 209 hasFuseAdrpAdd() || hasFuseLiterals(); 210 } 211 212 unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } 213 unsigned getVectorInsertExtractBaseCost() const; 214 unsigned getCacheLineSize() const override { return CacheLineSize; } 215 unsigned getPrefetchDistance() const override { return PrefetchDistance; } 216 unsigned getMinPrefetchStride(unsigned NumMemAccesses, 217 unsigned NumStridedMemAccesses, 218 unsigned NumPrefetches, 219 bool HasCall) const override { 220 return MinPrefetchStride; 221 } 222 unsigned getMaxPrefetchIterationsAhead() const override { 223 return MaxPrefetchIterationsAhead; 224 } 225 unsigned getPrefFunctionLogAlignment() const { 226 return PrefFunctionLogAlignment; 227 } 228 unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; } 229 230 unsigned getMaxBytesForLoopAlignment() const { 231 return MaxBytesForLoopAlignment; 232 } 233 234 unsigned getMaximumJumpTableSize() const { return MaxJumpTableSize; } 235 236 /// CPU has TBI (top byte of addresses is ignored during HW address 237 /// translation) and OS enables it. 238 bool supportsAddressTopByteIgnored() const; 239 240 bool isLittleEndian() const { return IsLittle; } 241 242 bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } 243 bool isTargetIOS() const { return TargetTriple.isiOS(); } 244 bool isTargetLinux() const { return TargetTriple.isOSLinux(); } 245 bool isTargetWindows() const { return TargetTriple.isOSWindows(); } 246 bool isTargetAndroid() const { return TargetTriple.isAndroid(); } 247 bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } 248 249 bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } 250 bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } 251 bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } 252 253 bool isTargetILP32() const { 254 return TargetTriple.isArch32Bit() || 255 TargetTriple.getEnvironment() == Triple::GNUILP32; 256 } 257 258 bool useAA() const override; 259 260 bool addrSinkUsingGEPs() const override { 261 // Keeping GEPs inbounds is important for exploiting AArch64 262 // addressing-modes in ILP32 mode. 263 return useAA() || isTargetILP32(); 264 } 265 266 bool useSmallAddressing() const { 267 switch (TLInfo.getTargetMachine().getCodeModel()) { 268 case CodeModel::Kernel: 269 // Kernel is currently allowed only for Fuchsia targets, 270 // where it is the same as Small for almost all purposes. 271 case CodeModel::Small: 272 return true; 273 default: 274 return false; 275 } 276 } 277 278 /// ParseSubtargetFeatures - Parses features string setting specified 279 /// subtarget options. Definition of function is auto generated by tblgen. 280 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 281 282 /// ClassifyGlobalReference - Find the target operand flags that describe 283 /// how a global value should be referenced for the current subtarget. 284 unsigned ClassifyGlobalReference(const GlobalValue *GV, 285 const TargetMachine &TM) const; 286 287 unsigned classifyGlobalFunctionReference(const GlobalValue *GV, 288 const TargetMachine &TM) const; 289 290 void overrideSchedPolicy(MachineSchedPolicy &Policy, 291 unsigned NumRegionInstrs) const override; 292 293 bool enableEarlyIfConversion() const override; 294 295 std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override; 296 297 bool isCallingConvWin64(CallingConv::ID CC) const { 298 switch (CC) { 299 case CallingConv::C: 300 case CallingConv::Fast: 301 case CallingConv::Swift: 302 return isTargetWindows(); 303 case CallingConv::Win64: 304 return true; 305 default: 306 return false; 307 } 308 } 309 310 /// Return whether FrameLowering should always set the "extended frame 311 /// present" bit in FP, or set it based on a symbol in the runtime. 312 bool swiftAsyncContextIsDynamicallySet() const { 313 // Older OS versions (particularly system unwinders) are confused by the 314 // Swift extended frame, so when building code that might be run on them we 315 // must dynamically query the concurrency library to determine whether 316 // extended frames should be flagged as present. 317 const Triple &TT = getTargetTriple(); 318 319 unsigned Major = TT.getOSVersion().getMajor(); 320 switch(TT.getOS()) { 321 default: 322 return false; 323 case Triple::IOS: 324 case Triple::TvOS: 325 return Major < 15; 326 case Triple::WatchOS: 327 return Major < 8; 328 case Triple::MacOSX: 329 case Triple::Darwin: 330 return Major < 12; 331 } 332 } 333 334 void mirFileLoaded(MachineFunction &MF) const override; 335 336 // Return the known range for the bit length of SVE data registers. A value 337 // of 0 means nothing is known about that particular limit beyong what's 338 // implied by the architecture. 339 unsigned getMaxSVEVectorSizeInBits() const { 340 assert(HasSVE && "Tried to get SVE vector length without SVE support!"); 341 return MaxSVEVectorSizeInBits; 342 } 343 344 unsigned getMinSVEVectorSizeInBits() const { 345 assert(HasSVE && "Tried to get SVE vector length without SVE support!"); 346 return MinSVEVectorSizeInBits; 347 } 348 349 bool useSVEForFixedLengthVectors() const { 350 // Prefer NEON unless larger SVE registers are available. 351 return hasSVE() && getMinSVEVectorSizeInBits() >= 256; 352 } 353 354 unsigned getVScaleForTuning() const { return VScaleForTuning; } 355 }; 356 } // End llvm namespace 357 358 #endif 359