diff options
Diffstat (limited to 'lib/Target/ARM/ARMSubtarget.h')
-rw-r--r-- | lib/Target/ARM/ARMSubtarget.h | 273 |
1 files changed, 206 insertions, 67 deletions
diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 4d54e5751473..910de0e1e72d 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -43,8 +43,9 @@ class ARMSubtarget : public ARMGenSubtargetInfo { protected: enum ARMProcFamilyEnum { Others, CortexA5, CortexA7, CortexA8, CortexA9, CortexA12, CortexA15, - CortexA17, CortexR4, CortexR4F, CortexR5, CortexR7, CortexA35, CortexA53, - CortexA57, CortexA72, Krait, Swift, ExynosM1 + CortexA17, CortexR4, CortexR4F, CortexR5, CortexR7, CortexM3, + CortexA32, CortexA35, CortexA53, CortexA57, CortexA72, CortexA73, + Krait, Swift, ExynosM1 }; enum ARMProcClassEnum { None, AClass, RClass, MClass @@ -52,188 +53,275 @@ protected: enum ARMArchEnum { ARMv2, ARMv2a, ARMv3, ARMv3m, ARMv4, ARMv4t, ARMv5, ARMv5t, ARMv5te, ARMv5tej, ARMv6, ARMv6k, ARMv6kz, ARMv6t2, ARMv6m, ARMv6sm, ARMv7a, ARMv7r, - ARMv7m, ARMv7em, ARMv8a, ARMv81a, ARMv82a + ARMv7m, ARMv7em, ARMv8a, ARMv81a, ARMv82a, ARMv8mMainline, ARMv8mBaseline }; +public: + /// What kind of timing do load multiple/store multiple instructions have. + enum ARMLdStMultipleTiming { + /// Can load/store 2 registers/cycle. + DoubleIssue, + /// Can load/store 2 registers/cycle, but needs an extra cycle if the access + /// is not 64-bit aligned. + DoubleIssueCheckUnalignedAccess, + /// Can load/store 1 register/cycle. + SingleIssue, + /// Can load/store 1 register/cycle, but needs an extra cycle for address + /// computation and potentially also for register writeback. + SingleIssuePlusExtras, + }; + +protected: /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others. - ARMProcFamilyEnum ARMProcFamily; + ARMProcFamilyEnum ARMProcFamily = Others; /// ARMProcClass - ARM processor class: None, AClass, RClass or MClass. - ARMProcClassEnum ARMProcClass; + ARMProcClassEnum ARMProcClass = None; /// ARMArch - ARM architecture - ARMArchEnum ARMArch; + ARMArchEnum ARMArch = ARMv4t; /// HasV4TOps, HasV5TOps, HasV5TEOps, /// HasV6Ops, HasV6MOps, HasV6KOps, HasV6T2Ops, HasV7Ops, HasV8Ops - /// Specify whether target support specific ARM ISA variants. - bool HasV4TOps; - bool HasV5TOps; - bool HasV5TEOps; - bool HasV6Ops; - bool HasV6MOps; - bool HasV6KOps; - bool HasV6T2Ops; - bool HasV7Ops; - bool HasV8Ops; - bool HasV8_1aOps; - bool HasV8_2aOps; + bool HasV4TOps = false; + bool HasV5TOps = false; + bool HasV5TEOps = false; + bool HasV6Ops = false; + bool HasV6MOps = false; + bool HasV6KOps = false; + bool HasV6T2Ops = false; + bool HasV7Ops = false; + bool HasV8Ops = false; + bool HasV8_1aOps = false; + bool HasV8_2aOps = false; + bool HasV8MBaselineOps = false; + bool HasV8MMainlineOps = false; /// HasVFPv2, HasVFPv3, HasVFPv4, HasFPARMv8, HasNEON - Specify what /// floating point ISAs are supported. - bool HasVFPv2; - bool HasVFPv3; - bool HasVFPv4; - bool HasFPARMv8; - bool HasNEON; + bool HasVFPv2 = false; + bool HasVFPv3 = false; + bool HasVFPv4 = false; + bool HasFPARMv8 = false; + bool HasNEON = false; /// UseNEONForSinglePrecisionFP - if the NEONFP attribute has been /// specified. Use the method useNEONForSinglePrecisionFP() to /// determine if NEON should actually be used. - bool UseNEONForSinglePrecisionFP; + bool UseNEONForSinglePrecisionFP = false; /// UseMulOps - True if non-microcoded fused integer multiply-add and /// multiply-subtract instructions should be used. - bool UseMulOps; + bool UseMulOps = false; /// SlowFPVMLx - If the VFP2 / NEON instructions are available, indicates /// whether the FP VML[AS] instructions are slow (if so, don't use them). - bool SlowFPVMLx; + bool SlowFPVMLx = false; /// HasVMLxForwarding - If true, NEON has special multiplier accumulator /// forwarding to allow mul + mla being issued back to back. - bool HasVMLxForwarding; + bool HasVMLxForwarding = false; /// SlowFPBrcc - True if floating point compare + branch is slow. - bool SlowFPBrcc; + bool SlowFPBrcc = false; /// InThumbMode - True if compiling for Thumb, false for ARM. - bool InThumbMode; + bool InThumbMode = false; /// UseSoftFloat - True if we're using software floating point features. - bool UseSoftFloat; + bool UseSoftFloat = false; /// HasThumb2 - True if Thumb2 instructions are supported. - bool HasThumb2; + bool HasThumb2 = false; /// NoARM - True if subtarget does not support ARM mode execution. - bool NoARM; + bool NoARM = false; /// ReserveR9 - True if R9 is not available as a general purpose register. - bool ReserveR9; + bool ReserveR9 = false; /// NoMovt - True if MOVT / MOVW pairs are not used for materialization of /// 32-bit imms (including global addresses). - bool NoMovt; + bool NoMovt = false; /// SupportsTailCall - True if the OS supports tail call. The dynamic linker /// must be able to synthesize call stubs for interworking between ARM and /// Thumb. - bool SupportsTailCall; + bool SupportsTailCall = false; /// HasFP16 - True if subtarget supports half-precision FP conversions - bool HasFP16; + bool HasFP16 = false; /// HasFullFP16 - True if subtarget supports half-precision FP operations - bool HasFullFP16; + bool HasFullFP16 = false; /// HasD16 - True if subtarget is limited to 16 double precision /// FP registers for VFPv3. - bool HasD16; + bool HasD16 = false; /// HasHardwareDivide - True if subtarget supports [su]div - bool HasHardwareDivide; + bool HasHardwareDivide = false; /// HasHardwareDivideInARM - True if subtarget supports [su]div in ARM mode - bool HasHardwareDivideInARM; + bool HasHardwareDivideInARM = false; /// HasT2ExtractPack - True if subtarget supports thumb2 extract/pack /// instructions. - bool HasT2ExtractPack; + bool HasT2ExtractPack = false; /// HasDataBarrier - True if the subtarget supports DMB / DSB data barrier /// instructions. - bool HasDataBarrier; + bool HasDataBarrier = false; + + /// HasV7Clrex - True if the subtarget supports CLREX instructions + bool HasV7Clrex = false; + + /// HasAcquireRelease - True if the subtarget supports v8 atomics (LDA/LDAEX etc) + /// instructions + bool HasAcquireRelease = false; /// Pref32BitThumb - If true, codegen would prefer 32-bit Thumb instructions /// over 16-bit ones. - bool Pref32BitThumb; + bool Pref32BitThumb = false; /// AvoidCPSRPartialUpdate - If true, codegen would avoid using instructions /// that partially update CPSR and add false dependency on the previous /// CPSR setting instruction. - bool AvoidCPSRPartialUpdate; + bool AvoidCPSRPartialUpdate = false; /// AvoidMOVsShifterOperand - If true, codegen should avoid using flag setting /// movs with shifter operand (i.e. asr, lsl, lsr). - bool AvoidMOVsShifterOperand; + bool AvoidMOVsShifterOperand = false; - /// HasRAS - Some processors perform return stack prediction. CodeGen should + /// HasRetAddrStack - Some processors perform return stack prediction. CodeGen should /// avoid issue "normal" call instructions to callees which do not return. - bool HasRAS; + bool HasRetAddrStack = false; /// HasMPExtension - True if the subtarget supports Multiprocessing /// extension (ARMv7 only). - bool HasMPExtension; + bool HasMPExtension = false; /// HasVirtualization - True if the subtarget supports the Virtualization /// extension. - bool HasVirtualization; + bool HasVirtualization = false; /// FPOnlySP - If true, the floating point unit only supports single /// precision. - bool FPOnlySP; + bool FPOnlySP = false; /// If true, the processor supports the Performance Monitor Extensions. These /// include a generic cycle-counter as well as more fine-grained (often /// implementation-specific) events. - bool HasPerfMon; + bool HasPerfMon = false; /// HasTrustZone - if true, processor supports TrustZone security extensions - bool HasTrustZone; + bool HasTrustZone = false; + + /// Has8MSecExt - if true, processor supports ARMv8-M Security Extensions + bool Has8MSecExt = false; /// HasCrypto - if true, processor supports Cryptography extensions - bool HasCrypto; + bool HasCrypto = false; /// HasCRC - if true, processor supports CRC instructions - bool HasCRC; + bool HasCRC = false; + + /// HasRAS - if true, the processor supports RAS extensions + bool HasRAS = false; /// If true, the instructions "vmov.i32 d0, #0" and "vmov.i32 q0, #0" are /// particularly effective at zeroing a VFP register. - bool HasZeroCycleZeroing; + bool HasZeroCycleZeroing = false; + + /// If true, if conversion may decide to leave some instructions unpredicated. + bool IsProfitableToUnpredicate = false; + + /// If true, VMOV will be favored over VGETLNi32. + bool HasSlowVGETLNi32 = false; + + /// If true, VMOV will be favored over VDUP. + bool HasSlowVDUP32 = false; + + /// If true, VMOVSR will be favored over VMOVDRR. + bool PreferVMOVSR = false; + + /// If true, ISHST barriers will be used for Release semantics. + bool PreferISHST = false; + + /// If true, a VLDM/VSTM starting with an odd register number is considered to + /// take more microops than single VLDRS/VSTRS. + bool SlowOddRegister = false; + + /// If true, loading into a D subregister will be penalized. + bool SlowLoadDSubregister = false; + + /// If true, the AGU and NEON/FPU units are multiplexed. + bool HasMuxedUnits = false; + + /// If true, VMOVS will never be widened to VMOVD + bool DontWidenVMOVS = false; + + /// If true, run the MLx expansion pass. + bool ExpandMLx = false; + + /// If true, VFP/NEON VMLA/VMLS have special RAW hazards. + bool HasVMLxHazards = false; + + /// If true, VMOVRS, VMOVSR and VMOVS will be converted from VFP to NEON. + bool UseNEONForFPMovs = false; + + /// If true, VLDn instructions take an extra cycle for unaligned accesses. + bool CheckVLDnAlign = false; + + /// If true, VFP instructions are not pipelined. + bool NonpipelinedVFP = false; /// StrictAlign - If true, the subtarget disallows unaligned memory /// accesses for some types. For details, see /// ARMTargetLowering::allowsMisalignedMemoryAccesses(). - bool StrictAlign; + bool StrictAlign = false; /// RestrictIT - If true, the subtarget disallows generation of deprecated IT /// blocks to conform to ARMv8 rule. - bool RestrictIT; + bool RestrictIT = false; /// HasDSP - If true, the subtarget supports the DSP (saturating arith /// and such) instructions. - bool HasDSP; + bool HasDSP = false; /// NaCl TRAP instruction is generated instead of the regular TRAP. - bool UseNaClTrap; + bool UseNaClTrap = false; /// Generate calls via indirect call instructions. - bool GenLongCalls; + bool GenLongCalls = false; /// Target machine allowed unsafe FP math (such as use of NEON fp) - bool UnsafeFPMath; + bool UnsafeFPMath = false; /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS). - bool UseSjLjEH; + bool UseSjLjEH = false; /// stackAlignment - The minimum alignment known to hold of the stack frame on /// entry to the function and which must be maintained by every function. - unsigned stackAlignment; + unsigned stackAlignment = 4; /// CPUString - String name of used CPU. std::string CPUString; + unsigned MaxInterleaveFactor = 1; + + /// Clearance before partial register updates (in number of instructions) + unsigned PartialUpdateClearance = 0; + + /// What kind of timing do load multiple/store multiple have (double issue, + /// single issue etc). + ARMLdStMultipleTiming LdStMultipleTiming = SingleIssue; + + /// The adjustment that we need to apply to get the operand latency from the + /// operand cycle returned by the itinerary data for pre-ISel operands. + int PreISelOperandLatencyAdjustment = 2; + /// IsLittle - The target is Little Endian bool IsLittle; @@ -313,17 +401,23 @@ public: bool hasV8Ops() const { return HasV8Ops; } bool hasV8_1aOps() const { return HasV8_1aOps; } bool hasV8_2aOps() const { return HasV8_2aOps; } + bool hasV8MBaselineOps() const { return HasV8MBaselineOps; } + bool hasV8MMainlineOps() const { return HasV8MMainlineOps; } + /// @{ + /// These functions are obsolete, please consider adding subtarget features + /// or properties instead of calling them. bool isCortexA5() const { return ARMProcFamily == CortexA5; } bool isCortexA7() const { return ARMProcFamily == CortexA7; } bool isCortexA8() const { return ARMProcFamily == CortexA8; } bool isCortexA9() const { return ARMProcFamily == CortexA9; } bool isCortexA15() const { return ARMProcFamily == CortexA15; } bool isSwift() const { return ARMProcFamily == Swift; } - bool isCortexM3() const { return CPUString == "cortex-m3"; } + bool isCortexM3() const { return ARMProcFamily == CortexM3; } bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); } bool isCortexR5() const { return ARMProcFamily == CortexR5; } bool isKrait() const { return ARMProcFamily == Krait; } + /// @} bool hasARMOps() const { return !NoARM; } @@ -334,6 +428,7 @@ public: bool hasNEON() const { return HasNEON; } bool hasCrypto() const { return HasCrypto; } bool hasCRC() const { return HasCRC; } + bool hasRAS() const { return HasRAS; } bool hasVirtualization() const { return HasVirtualization; } bool useNEONForSinglePrecisionFP() const { return hasNEON() && UseNEONForSinglePrecisionFP; @@ -343,6 +438,8 @@ public: bool hasDivideInARMMode() const { return HasHardwareDivideInARM; } bool hasT2ExtractPack() const { return HasT2ExtractPack; } bool hasDataBarrier() const { return HasDataBarrier; } + bool hasV7Clrex() const { return HasV7Clrex; } + bool hasAcquireRelease() const { return HasAcquireRelease; } bool hasAnyDataBarrier() const { return HasDataBarrier || (hasV6Ops() && !isThumb()); } @@ -353,11 +450,26 @@ public: bool isFPOnlySP() const { return FPOnlySP; } bool hasPerfMon() const { return HasPerfMon; } bool hasTrustZone() const { return HasTrustZone; } + bool has8MSecExt() const { return Has8MSecExt; } bool hasZeroCycleZeroing() const { return HasZeroCycleZeroing; } + bool isProfitableToUnpredicate() const { return IsProfitableToUnpredicate; } + bool hasSlowVGETLNi32() const { return HasSlowVGETLNi32; } + bool hasSlowVDUP32() const { return HasSlowVDUP32; } + bool preferVMOVSR() const { return PreferVMOVSR; } + bool preferISHSTBarriers() const { return PreferISHST; } + bool expandMLx() const { return ExpandMLx; } + bool hasVMLxHazards() const { return HasVMLxHazards; } + bool hasSlowOddRegister() const { return SlowOddRegister; } + bool hasSlowLoadDSubregister() const { return SlowLoadDSubregister; } + bool hasMuxedUnits() const { return HasMuxedUnits; } + bool dontWidenVMOVS() const { return DontWidenVMOVS; } + bool useNEONForFPMovs() const { return UseNEONForFPMovs; } + bool checkVLDnAccessAlignment() const { return CheckVLDnAlign; } + bool nonpipelinedVFP() const { return NonpipelinedVFP; } bool prefers32BitThumb() const { return Pref32BitThumb; } bool avoidCPSRPartialUpdate() const { return AvoidCPSRPartialUpdate; } bool avoidMOVsShifterOperand() const { return AvoidMOVsShifterOperand; } - bool hasRAS() const { return HasRAS; } + bool hasRetAddrStack() const { return HasRetAddrStack; } bool hasMPExtension() const { return HasMPExtension; } bool hasDSP() const { return HasDSP; } bool useNaClTrap() const { return UseNaClTrap; } @@ -373,6 +485,7 @@ public: bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } bool isTargetIOS() const { return TargetTriple.isiOS(); } bool isTargetWatchOS() const { return TargetTriple.isWatchOS(); } + bool isTargetWatchABI() const { return TargetTriple.isWatchABI(); } bool isTargetLinux() const { return TargetTriple.isOSLinux(); } bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); } @@ -399,14 +512,21 @@ public: TargetTriple.getEnvironment() == Triple::GNUEABIHF) && !isTargetDarwin() && !isTargetWindows(); } + bool isTargetMuslAEABI() const { + return (TargetTriple.getEnvironment() == Triple::MuslEABI || + TargetTriple.getEnvironment() == Triple::MuslEABIHF) && + !isTargetDarwin() && !isTargetWindows(); + } // ARM Targets that support EHABI exception handling standard // Darwin uses SjLj. Other targets might need more checks. bool isTargetEHABICompatible() const { return (TargetTriple.getEnvironment() == Triple::EABI || TargetTriple.getEnvironment() == Triple::GNUEABI || + TargetTriple.getEnvironment() == Triple::MuslEABI || TargetTriple.getEnvironment() == Triple::EABIHF || TargetTriple.getEnvironment() == Triple::GNUEABIHF || + TargetTriple.getEnvironment() == Triple::MuslEABIHF || isTargetAndroid()) && !isTargetDarwin() && !isTargetWindows(); } @@ -414,6 +534,7 @@ public: bool isTargetHardFloat() const { // FIXME: this is invalid for WindowsCE return TargetTriple.getEnvironment() == Triple::GNUEABIHF || + TargetTriple.getEnvironment() == Triple::MuslEABIHF || TargetTriple.getEnvironment() == Triple::EABIHF || isTargetWindows() || isAAPCS16_ABI(); } @@ -436,6 +557,13 @@ public: return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9; } + /// Returns true if the frame setup is split into two separate pushes (first + /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent + /// to lr. + bool splitFramePushPop() const { + return isTargetMachO(); + } + bool useStride4VFPs(const MachineFunction &MF) const; bool useMovt(const MachineFunction &MF) const; @@ -476,9 +604,20 @@ public: /// function for this subtarget. unsigned getStackAlignment() const { return stackAlignment; } - /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect - /// symbol. - bool GVIsIndirectSymbol(const GlobalValue *GV, Reloc::Model RelocM) const; + unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } + + unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; } + + ARMLdStMultipleTiming getLdStMultipleTiming() const { + return LdStMultipleTiming; + } + + int getPreISelOperandLatencyAdjustment() const { + return PreISelOperandLatencyAdjustment; + } + + /// True if the GV will be accessed via an indirect symbol. + bool isGVIndirectSymbol(const GlobalValue *GV) const; /// True if fast-isel is used. bool useFastISel() const; |