1 //===-- ARMSubtarget.h - Define Subtarget for the ARM ----------*- 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 ARM specific subclass of TargetSubtargetInfo. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 14 #define LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 15 16 #include "ARMBaseInstrInfo.h" 17 #include "ARMBaseRegisterInfo.h" 18 #include "ARMConstantPoolValue.h" 19 #include "ARMFrameLowering.h" 20 #include "ARMISelLowering.h" 21 #include "ARMMachineFunctionInfo.h" 22 #include "ARMSelectionDAGInfo.h" 23 #include "llvm/Analysis/TargetTransformInfo.h" 24 #include "llvm/CodeGen/GlobalISel/CallLowering.h" 25 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 26 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 27 #include "llvm/CodeGen/MachineFunction.h" 28 #include "llvm/CodeGen/RegisterBankInfo.h" 29 #include "llvm/CodeGen/TargetSubtargetInfo.h" 30 #include "llvm/MC/MCInstrItineraries.h" 31 #include "llvm/MC/MCSchedule.h" 32 #include "llvm/Target/TargetMachine.h" 33 #include "llvm/Target/TargetOptions.h" 34 #include "llvm/TargetParser/Triple.h" 35 #include <bitset> 36 #include <memory> 37 #include <string> 38 39 #define GET_SUBTARGETINFO_HEADER 40 #include "ARMGenSubtargetInfo.inc" 41 42 namespace llvm { 43 44 class ARMBaseTargetMachine; 45 class GlobalValue; 46 class StringRef; 47 48 class ARMSubtarget : public ARMGenSubtargetInfo { 49 protected: 50 enum ARMProcFamilyEnum { 51 Others, 52 #define ARM_PROCESSOR_FAMILY(ENUM) ENUM, 53 #include "llvm/TargetParser/ARMTargetParserDef.inc" 54 #undef ARM_PROCESSOR_FAMILY 55 }; 56 enum ARMProcClassEnum { 57 None, 58 59 AClass, 60 MClass, 61 RClass 62 }; 63 enum ARMArchEnum { 64 #define ARM_ARCHITECTURE(ENUM) ENUM, 65 #include "llvm/TargetParser/ARMTargetParserDef.inc" 66 #undef ARM_ARCHITECTURE 67 }; 68 69 public: 70 /// What kind of timing do load multiple/store multiple instructions have. 71 enum ARMLdStMultipleTiming { 72 /// Can load/store 2 registers/cycle. 73 DoubleIssue, 74 /// Can load/store 2 registers/cycle, but needs an extra cycle if the access 75 /// is not 64-bit aligned. 76 DoubleIssueCheckUnalignedAccess, 77 /// Can load/store 1 register/cycle. 78 SingleIssue, 79 /// Can load/store 1 register/cycle, but needs an extra cycle for address 80 /// computation and potentially also for register writeback. 81 SingleIssuePlusExtras, 82 }; 83 84 protected: 85 // Bool members corresponding to the SubtargetFeatures defined in tablegen 86 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 87 bool ATTRIBUTE = DEFAULT; 88 #include "ARMGenSubtargetInfo.inc" 89 90 /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others. 91 ARMProcFamilyEnum ARMProcFamily = Others; 92 93 /// ARMProcClass - ARM processor class: None, AClass, RClass or MClass. 94 ARMProcClassEnum ARMProcClass = None; 95 96 /// ARMArch - ARM architecture 97 ARMArchEnum ARMArch = ARMv4t; 98 99 /// UseMulOps - True if non-microcoded fused integer multiply-add and 100 /// multiply-subtract instructions should be used. 101 bool UseMulOps = false; 102 103 /// SupportsTailCall - True if the OS supports tail call. The dynamic linker 104 /// must be able to synthesize call stubs for interworking between ARM and 105 /// Thumb. 106 bool SupportsTailCall = false; 107 108 /// RestrictIT - If true, the subtarget disallows generation of complex IT 109 /// blocks. 110 bool RestrictIT = false; 111 112 /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS). 113 bool UseSjLjEH = false; 114 115 /// stackAlignment - The minimum alignment known to hold of the stack frame on 116 /// entry to the function and which must be maintained by every function. 117 Align stackAlignment = Align(4); 118 119 /// CPUString - String name of used CPU. 120 std::string CPUString; 121 122 unsigned MaxInterleaveFactor = 1; 123 124 /// Clearance before partial register updates (in number of instructions) 125 unsigned PartialUpdateClearance = 0; 126 127 /// What kind of timing do load multiple/store multiple have (double issue, 128 /// single issue etc). 129 ARMLdStMultipleTiming LdStMultipleTiming = SingleIssue; 130 131 /// The adjustment that we need to apply to get the operand latency from the 132 /// operand cycle returned by the itinerary data for pre-ISel operands. 133 int PreISelOperandLatencyAdjustment = 2; 134 135 /// What alignment is preferred for loop bodies and functions, in log2(bytes). 136 unsigned PrefLoopLogAlignment = 0; 137 138 /// The cost factor for MVE instructions, representing the multiple beats an 139 // instruction can take. The default is 2, (set in initSubtargetFeatures so 140 // that we can use subtarget features less than 2). 141 unsigned MVEVectorCostFactor = 0; 142 143 /// OptMinSize - True if we're optimising for minimum code size, equal to 144 /// the function attribute. 145 bool OptMinSize = false; 146 147 /// IsLittle - The target is Little Endian 148 bool IsLittle; 149 150 /// TargetTriple - What processor and OS we're targeting. 151 Triple TargetTriple; 152 153 /// SchedModel - Processor specific instruction costs. 154 MCSchedModel SchedModel; 155 156 /// Selected instruction itineraries (one entry per itinerary class.) 157 InstrItineraryData InstrItins; 158 159 /// Options passed via command line that could influence the target 160 const TargetOptions &Options; 161 162 const ARMBaseTargetMachine &TM; 163 164 public: 165 /// This constructor initializes the data members to match that 166 /// of the specified triple. 167 /// 168 ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, 169 const ARMBaseTargetMachine &TM, bool IsLittle, 170 bool MinSize = false); 171 172 /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size 173 /// that still makes it profitable to inline the call. getMaxInlineSizeThreshold()174 unsigned getMaxInlineSizeThreshold() const { 175 return 64; 176 } 177 178 /// getMaxMemcpyTPInlineSizeThreshold - Returns the maximum size 179 /// that still makes it profitable to inline a llvm.memcpy as a Tail 180 /// Predicated loop. 181 /// This threshold should only be used for constant size inputs. getMaxMemcpyTPInlineSizeThreshold()182 unsigned getMaxMemcpyTPInlineSizeThreshold() const { return 128; } 183 184 /// ParseSubtargetFeatures - Parses features string setting specified 185 /// subtarget options. Definition of function is auto generated by tblgen. 186 void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 187 188 /// initializeSubtargetDependencies - Initializes using a CPU and feature string 189 /// so that we can use initializer lists for subtarget initialization. 190 ARMSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); 191 getSelectionDAGInfo()192 const ARMSelectionDAGInfo *getSelectionDAGInfo() const override { 193 return &TSInfo; 194 } 195 getInstrInfo()196 const ARMBaseInstrInfo *getInstrInfo() const override { 197 return InstrInfo.get(); 198 } 199 getTargetLowering()200 const ARMTargetLowering *getTargetLowering() const override { 201 return &TLInfo; 202 } 203 getFrameLowering()204 const ARMFrameLowering *getFrameLowering() const override { 205 return FrameLowering.get(); 206 } 207 getRegisterInfo()208 const ARMBaseRegisterInfo *getRegisterInfo() const override { 209 return &InstrInfo->getRegisterInfo(); 210 } 211 212 /// The correct instructions have been implemented to initialize undef 213 /// registers, therefore the ARM Architecture is supported by the Init Undef 214 /// Pass. This will return true as the pass needs to be supported for all 215 /// types of instructions. The pass will then perform more checks to ensure it 216 /// should be applying the Pseudo Instructions. supportsInitUndef()217 bool supportsInitUndef() const override { return true; } 218 219 const CallLowering *getCallLowering() const override; 220 InstructionSelector *getInstructionSelector() const override; 221 const LegalizerInfo *getLegalizerInfo() const override; 222 const RegisterBankInfo *getRegBankInfo() const override; 223 224 private: 225 ARMSelectionDAGInfo TSInfo; 226 // Either Thumb1FrameLowering or ARMFrameLowering. 227 std::unique_ptr<ARMFrameLowering> FrameLowering; 228 // Either Thumb1InstrInfo or Thumb2InstrInfo. 229 std::unique_ptr<ARMBaseInstrInfo> InstrInfo; 230 ARMTargetLowering TLInfo; 231 232 /// GlobalISel related APIs. 233 std::unique_ptr<CallLowering> CallLoweringInfo; 234 std::unique_ptr<InstructionSelector> InstSelector; 235 std::unique_ptr<LegalizerInfo> Legalizer; 236 std::unique_ptr<RegisterBankInfo> RegBankInfo; 237 238 void initializeEnvironment(); 239 void initSubtargetFeatures(StringRef CPU, StringRef FS); 240 ARMFrameLowering *initializeFrameLowering(StringRef CPU, StringRef FS); 241 242 std::bitset<8> CoprocCDE = {}; 243 public: 244 // Getters for SubtargetFeatures defined in tablegen 245 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 246 bool GETTER() const { return ATTRIBUTE; } 247 #include "ARMGenSubtargetInfo.inc" 248 249 /// @{ 250 /// These functions are obsolete, please consider adding subtarget features 251 /// or properties instead of calling them. isCortexA5()252 bool isCortexA5() const { return ARMProcFamily == CortexA5; } isCortexA7()253 bool isCortexA7() const { return ARMProcFamily == CortexA7; } isCortexA8()254 bool isCortexA8() const { return ARMProcFamily == CortexA8; } isCortexA9()255 bool isCortexA9() const { return ARMProcFamily == CortexA9; } isCortexA15()256 bool isCortexA15() const { return ARMProcFamily == CortexA15; } isSwift()257 bool isSwift() const { return ARMProcFamily == Swift; } isCortexM3()258 bool isCortexM3() const { return ARMProcFamily == CortexM3; } isCortexM7()259 bool isCortexM7() const { return ARMProcFamily == CortexM7; } isLikeA9()260 bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); } isCortexR5()261 bool isCortexR5() const { return ARMProcFamily == CortexR5; } isKrait()262 bool isKrait() const { return ARMProcFamily == Krait; } 263 /// @} 264 hasARMOps()265 bool hasARMOps() const { return !NoARM; } 266 useNEONForSinglePrecisionFP()267 bool useNEONForSinglePrecisionFP() const { 268 return hasNEON() && hasNEONForFP(); 269 } 270 hasVFP2Base()271 bool hasVFP2Base() const { return hasVFPv2SP(); } hasVFP3Base()272 bool hasVFP3Base() const { return hasVFPv3D16SP(); } hasVFP4Base()273 bool hasVFP4Base() const { return hasVFPv4D16SP(); } hasFPARMv8Base()274 bool hasFPARMv8Base() const { return hasFPARMv8D16SP(); } 275 hasAnyDataBarrier()276 bool hasAnyDataBarrier() const { 277 return HasDataBarrier || (hasV6Ops() && !isThumb()); 278 } 279 useMulOps()280 bool useMulOps() const { return UseMulOps; } useFPVMLx()281 bool useFPVMLx() const { return !SlowFPVMLx; } useFPVFMx()282 bool useFPVFMx() const { 283 return !isTargetDarwin() && hasVFP4Base() && !SlowFPVFMx; 284 } useFPVFMx16()285 bool useFPVFMx16() const { return useFPVFMx() && hasFullFP16(); } useFPVFMx64()286 bool useFPVFMx64() const { return useFPVFMx() && hasFP64(); } useSjLjEH()287 bool useSjLjEH() const { return UseSjLjEH; } hasBaseDSP()288 bool hasBaseDSP() const { 289 if (isThumb()) 290 return hasThumb2() && hasDSP(); 291 else 292 return hasV5TEOps(); 293 } 294 295 /// Return true if the CPU supports any kind of instruction fusion. hasFusion()296 bool hasFusion() const { return hasFuseAES() || hasFuseLiterals(); } 297 getTargetTriple()298 const Triple &getTargetTriple() const { return TargetTriple; } 299 isTargetDarwin()300 bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } isTargetIOS()301 bool isTargetIOS() const { return TargetTriple.isiOS(); } isTargetWatchOS()302 bool isTargetWatchOS() const { return TargetTriple.isWatchOS(); } isTargetWatchABI()303 bool isTargetWatchABI() const { return TargetTriple.isWatchABI(); } isTargetDriverKit()304 bool isTargetDriverKit() const { return TargetTriple.isDriverKit(); } isTargetLinux()305 bool isTargetLinux() const { return TargetTriple.isOSLinux(); } isTargetNaCl()306 bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } isTargetNetBSD()307 bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); } isTargetWindows()308 bool isTargetWindows() const { return TargetTriple.isOSWindows(); } 309 isTargetCOFF()310 bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } isTargetELF()311 bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } isTargetMachO()312 bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } 313 314 // ARM EABI is the bare-metal EABI described in ARM ABI documents and 315 // can be accessed via -target arm-none-eabi. This is NOT GNUEABI. 316 // FIXME: Add a flag for bare-metal for that target and set Triple::EABI 317 // even for GNUEABI, so we can make a distinction here and still conform to 318 // the EABI on GNU (and Android) mode. This requires change in Clang, too. 319 // FIXME: The Darwin exception is temporary, while we move users to 320 // "*-*-*-macho" triples as quickly as possible. isTargetAEABI()321 bool isTargetAEABI() const { 322 return (TargetTriple.getEnvironment() == Triple::EABI || 323 TargetTriple.getEnvironment() == Triple::EABIHF) && 324 !isTargetDarwin() && !isTargetWindows(); 325 } isTargetGNUAEABI()326 bool isTargetGNUAEABI() const { 327 return (TargetTriple.getEnvironment() == Triple::GNUEABI || 328 TargetTriple.getEnvironment() == Triple::GNUEABIT64 || 329 TargetTriple.getEnvironment() == Triple::GNUEABIHF || 330 TargetTriple.getEnvironment() == Triple::GNUEABIHFT64) && 331 !isTargetDarwin() && !isTargetWindows(); 332 } isTargetMuslAEABI()333 bool isTargetMuslAEABI() const { 334 return (TargetTriple.getEnvironment() == Triple::MuslEABI || 335 TargetTriple.getEnvironment() == Triple::MuslEABIHF || 336 TargetTriple.getEnvironment() == Triple::OpenHOS) && 337 !isTargetDarwin() && !isTargetWindows(); 338 } 339 340 // ARM Targets that support EHABI exception handling standard 341 // Darwin uses SjLj. Other targets might need more checks. isTargetEHABICompatible()342 bool isTargetEHABICompatible() const { 343 return TargetTriple.isTargetEHABICompatible(); 344 } 345 346 bool isTargetHardFloat() const; 347 isReadTPSoft()348 bool isReadTPSoft() const { 349 return !(isReadTPTPIDRURW() || isReadTPTPIDRURO() || isReadTPTPIDRPRW()); 350 } 351 isTargetAndroid()352 bool isTargetAndroid() const { return TargetTriple.isAndroid(); } 353 354 bool isXRaySupported() const override; 355 356 bool isAPCS_ABI() const; 357 bool isAAPCS_ABI() const; 358 bool isAAPCS16_ABI() const; 359 360 bool isROPI() const; 361 bool isRWPI() const; 362 useMachineScheduler()363 bool useMachineScheduler() const { return UseMISched; } useMachinePipeliner()364 bool useMachinePipeliner() const { return UseMIPipeliner; } hasMinSize()365 bool hasMinSize() const { return OptMinSize; } isThumb1Only()366 bool isThumb1Only() const { return isThumb() && !hasThumb2(); } isThumb2()367 bool isThumb2() const { return isThumb() && hasThumb2(); } isMClass()368 bool isMClass() const { return ARMProcClass == MClass; } isRClass()369 bool isRClass() const { return ARMProcClass == RClass; } isAClass()370 bool isAClass() const { return ARMProcClass == AClass; } 371 isR9Reserved()372 bool isR9Reserved() const { 373 return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9; 374 } 375 getFramePointerReg()376 MCPhysReg getFramePointerReg() const { 377 if (isTargetDarwin() || 378 (!isTargetWindows() && isThumb() && !createAAPCSFrameChain())) 379 return ARM::R7; 380 return ARM::R11; 381 } 382 383 /// Returns true if the frame setup is split into two separate pushes (first 384 /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent 385 /// to lr. This is always required on Thumb1-only targets, as the push and 386 /// pop instructions can't access the high registers. splitFramePushPop(const MachineFunction & MF)387 bool splitFramePushPop(const MachineFunction &MF) const { 388 if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress()) 389 return true; 390 return (getFramePointerReg() == ARM::R7 && 391 MF.getTarget().Options.DisableFramePointerElim(MF)) || 392 isThumb1Only(); 393 } 394 395 bool splitFramePointerPush(const MachineFunction &MF) const; 396 397 bool useStride4VFPs() const; 398 399 bool useMovt() const; 400 supportsTailCall()401 bool supportsTailCall() const { return SupportsTailCall; } 402 allowsUnalignedMem()403 bool allowsUnalignedMem() const { return !StrictAlign; } 404 restrictIT()405 bool restrictIT() const { return RestrictIT; } 406 getCPUString()407 const std::string & getCPUString() const { return CPUString; } 408 isLittle()409 bool isLittle() const { return IsLittle; } 410 411 unsigned getMispredictionPenalty() const; 412 413 /// Returns true if machine scheduler should be enabled. 414 bool enableMachineScheduler() const override; 415 416 /// Returns true if machine pipeliner should be enabled. 417 bool enableMachinePipeliner() const override; 418 bool useDFAforSMS() const override; 419 420 /// True for some subtargets at > -O0. 421 bool enablePostRAScheduler() const override; 422 423 /// True for some subtargets at > -O0. 424 bool enablePostRAMachineScheduler() const override; 425 426 /// Check whether this subtarget wants to use subregister liveness. 427 bool enableSubRegLiveness() const override; 428 429 /// Enable use of alias analysis during code generation (during MI 430 /// scheduling, DAGCombine, etc.). useAA()431 bool useAA() const override { return true; } 432 433 /// getInstrItins - Return the instruction itineraries based on subtarget 434 /// selection. getInstrItineraryData()435 const InstrItineraryData *getInstrItineraryData() const override { 436 return &InstrItins; 437 } 438 439 /// getStackAlignment - Returns the minimum alignment known to hold of the 440 /// stack frame on entry to the function and which must be maintained by every 441 /// function for this subtarget. getStackAlignment()442 Align getStackAlignment() const { return stackAlignment; } 443 444 // Returns the required alignment for LDRD/STRD instructions getDualLoadStoreAlignment()445 Align getDualLoadStoreAlignment() const { 446 return Align(hasV7Ops() || allowsUnalignedMem() ? 4 : 8); 447 } 448 getMaxInterleaveFactor()449 unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } 450 getPartialUpdateClearance()451 unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; } 452 getLdStMultipleTiming()453 ARMLdStMultipleTiming getLdStMultipleTiming() const { 454 return LdStMultipleTiming; 455 } 456 getPreISelOperandLatencyAdjustment()457 int getPreISelOperandLatencyAdjustment() const { 458 return PreISelOperandLatencyAdjustment; 459 } 460 461 /// True if the GV will be accessed via an indirect symbol. 462 bool isGVIndirectSymbol(const GlobalValue *GV) const; 463 464 /// Returns the constant pool modifier needed to access the GV. 465 bool isGVInGOT(const GlobalValue *GV) const; 466 467 /// True if fast-isel is used. 468 bool useFastISel() const; 469 470 /// Returns the correct return opcode for the current feature set. 471 /// Use BX if available to allow mixing thumb/arm code, but fall back 472 /// to plain mov pc,lr on ARMv4. getReturnOpcode()473 unsigned getReturnOpcode() const { 474 if (isThumb()) 475 return ARM::tBX_RET; 476 if (hasV4TOps()) 477 return ARM::BX_RET; 478 return ARM::MOVPCLR; 479 } 480 481 /// Allow movt+movw for PIC global address calculation. 482 /// ELF does not have GOT relocations for movt+movw. 483 /// ROPI does not use GOT. allowPositionIndependentMovt()484 bool allowPositionIndependentMovt() const { 485 return isROPI() || !isTargetELF(); 486 } 487 getPrefLoopLogAlignment()488 unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; } 489 490 unsigned getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind)491 getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind) const { 492 if (CostKind == TargetTransformInfo::TCK_CodeSize) 493 return 1; 494 return MVEVectorCostFactor; 495 } 496 497 bool ignoreCSRForAllocationOrder(const MachineFunction &MF, 498 unsigned PhysReg) const override; 499 unsigned getGPRAllocationOrder(const MachineFunction &MF) const; 500 }; 501 502 } // end namespace llvm 503 504 #endif // LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 505