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 172 const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override { 173 return &TSInfo; 174 } 175 const AArch64FrameLowering *getFrameLowering() const override { 176 return &FrameLowering; 177 } 178 const AArch64TargetLowering *getTargetLowering() const override { 179 return &TLInfo; 180 } 181 const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; } 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; 190 const Triple &getTargetTriple() const { return TargetTriple; } 191 bool enableMachineScheduler() const override { return true; } 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(). 198 ARMProcFamilyEnum getProcFamily() const { 199 return ARMProcFamily; 200 } 201 202 bool isXRaySupported() const override { return true; } 203 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 211 bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; } 212 bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; } 213 unsigned getNumXRegisterReserved() const { 214 BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs()); 215 AllReservedX |= ReserveXRegister; 216 AllReservedX |= ReserveXRegisterForRA; 217 return AllReservedX.count(); 218 } 219 bool isXRegCustomCalleeSaved(size_t i) const { 220 return CustomCallSavedXRegs[i]; 221 } 222 bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); } 223 224 /// Return true if the CPU supports any kind of instruction fusion. 225 bool hasFusion() const { 226 return hasArithmeticBccFusion() || hasArithmeticCbzFusion() || 227 hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCCSelect() || 228 hasFuseAdrpAdd() || hasFuseLiterals(); 229 } 230 231 unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } 232 unsigned getVectorInsertExtractBaseCost() const; 233 unsigned getCacheLineSize() const override { return CacheLineSize; } 234 unsigned getPrefetchDistance() const override { return PrefetchDistance; } 235 unsigned getMinPrefetchStride(unsigned NumMemAccesses, 236 unsigned NumStridedMemAccesses, 237 unsigned NumPrefetches, 238 bool HasCall) const override { 239 return MinPrefetchStride; 240 } 241 unsigned getMaxPrefetchIterationsAhead() const override { 242 return MaxPrefetchIterationsAhead; 243 } 244 unsigned getPrefFunctionLogAlignment() const { 245 return PrefFunctionLogAlignment; 246 } 247 unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; } 248 249 unsigned getMaxBytesForLoopAlignment() const { 250 return MaxBytesForLoopAlignment; 251 } 252 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 259 bool isLittleEndian() const { return IsLittle; } 260 261 bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } 262 bool isTargetIOS() const { return TargetTriple.isiOS(); } 263 bool isTargetLinux() const { return TargetTriple.isOSLinux(); } 264 bool isTargetWindows() const { return TargetTriple.isOSWindows(); } 265 bool isTargetAndroid() const { return TargetTriple.isAndroid(); } 266 bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } 267 bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); } 268 269 bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } 270 bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } 271 bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } 272 273 bool isTargetILP32() const { 274 return TargetTriple.isArch32Bit() || 275 TargetTriple.getEnvironment() == Triple::GNUILP32; 276 } 277 278 bool useAA() const override; 279 280 bool addrSinkUsingGEPs() const override { 281 // Keeping GEPs inbounds is important for exploiting AArch64 282 // addressing-modes in ILP32 mode. 283 return useAA() || isTargetILP32(); 284 } 285 286 bool useSmallAddressing() const { 287 switch (TLInfo.getTargetMachine().getCodeModel()) { 288 case CodeModel::Kernel: 289 // Kernel is currently allowed only for Fuchsia targets, 290 // where it is the same as Small for almost all purposes. 291 case CodeModel::Small: 292 return true; 293 default: 294 return false; 295 } 296 } 297 298 /// ParseSubtargetFeatures - Parses features string setting specified 299 /// subtarget options. Definition of function is auto generated by tblgen. 300 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 301 302 /// ClassifyGlobalReference - Find the target operand flags that describe 303 /// how a global value should be referenced for the current subtarget. 304 unsigned ClassifyGlobalReference(const GlobalValue *GV, 305 const TargetMachine &TM) const; 306 307 unsigned classifyGlobalFunctionReference(const GlobalValue *GV, 308 const TargetMachine &TM) const; 309 310 /// This function is design to compatible with the function def in other 311 /// targets and escape build error about the virtual function def in base 312 /// class TargetSubtargetInfo. Updeate me if AArch64 target need to use it. 313 unsigned char 314 classifyGlobalFunctionReference(const GlobalValue *GV) const override { 315 return 0; 316 } 317 318 void overrideSchedPolicy(MachineSchedPolicy &Policy, 319 unsigned NumRegionInstrs) const override; 320 321 bool enableEarlyIfConversion() const override; 322 323 std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override; 324 325 bool isCallingConvWin64(CallingConv::ID CC) const { 326 switch (CC) { 327 case CallingConv::C: 328 case CallingConv::Fast: 329 case CallingConv::Swift: 330 return isTargetWindows(); 331 case CallingConv::Win64: 332 return true; 333 default: 334 return false; 335 } 336 } 337 338 /// Return whether FrameLowering should always set the "extended frame 339 /// present" bit in FP, or set it based on a symbol in the runtime. 340 bool swiftAsyncContextIsDynamicallySet() const { 341 // Older OS versions (particularly system unwinders) are confused by the 342 // Swift extended frame, so when building code that might be run on them we 343 // must dynamically query the concurrency library to determine whether 344 // extended frames should be flagged as present. 345 const Triple &TT = getTargetTriple(); 346 347 unsigned Major = TT.getOSVersion().getMajor(); 348 switch(TT.getOS()) { 349 default: 350 return false; 351 case Triple::IOS: 352 case Triple::TvOS: 353 return Major < 15; 354 case Triple::WatchOS: 355 return Major < 8; 356 case Triple::MacOSX: 357 case Triple::Darwin: 358 return Major < 12; 359 } 360 } 361 362 void mirFileLoaded(MachineFunction &MF) const override; 363 364 bool hasSVEorSME() const { return hasSVE() || hasSME(); } 365 366 // Return the known range for the bit length of SVE data registers. A value 367 // of 0 means nothing is known about that particular limit beyong what's 368 // implied by the architecture. 369 unsigned getMaxSVEVectorSizeInBits() const { 370 assert(hasSVEorSME() && 371 "Tried to get SVE vector length without SVE support!"); 372 return MaxSVEVectorSizeInBits; 373 } 374 375 unsigned getMinSVEVectorSizeInBits() const { 376 assert(hasSVEorSME() && 377 "Tried to get SVE vector length without SVE support!"); 378 return MinSVEVectorSizeInBits; 379 } 380 381 bool useSVEForFixedLengthVectors() const { 382 if (forceStreamingCompatibleSVE()) 383 return true; 384 385 // Prefer NEON unless larger SVE registers are available. 386 return hasSVE() && getMinSVEVectorSizeInBits() >= 256; 387 } 388 389 bool forceStreamingCompatibleSVE() const; 390 391 unsigned getVScaleForTuning() const { return VScaleForTuning; } 392 393 const char* getChkStkName() const { 394 if (isWindowsArm64EC()) 395 return "__chkstk_arm64ec"; 396 return "__chkstk"; 397 } 398 399 const char* getSecurityCheckCookieName() const { 400 if (isWindowsArm64EC()) 401 return "__security_check_cookie_arm64ec"; 402 return "__security_check_cookie"; 403 } 404 405 bool isStreamingSVEModeDisabled() const { return StreamingSVEModeDisabled; } 406 }; 407 } // End llvm namespace 408 409 #endif 410