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