10b57cec5SDimitry Andric //===-- ARMSubtarget.h - Define Subtarget for the ARM ----------*- C++ -*--===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares the ARM specific subclass of TargetSubtargetInfo. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "ARMBaseInstrInfo.h" 170b57cec5SDimitry Andric #include "ARMBaseRegisterInfo.h" 180b57cec5SDimitry Andric #include "ARMConstantPoolValue.h" 190b57cec5SDimitry Andric #include "ARMFrameLowering.h" 200b57cec5SDimitry Andric #include "ARMISelLowering.h" 210eae32dcSDimitry Andric #include "ARMMachineFunctionInfo.h" 220b57cec5SDimitry Andric #include "ARMSelectionDAGInfo.h" 23fe6060f1SDimitry Andric #include "llvm/Analysis/TargetTransformInfo.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 2881ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 290b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 300b57cec5SDimitry Andric #include "llvm/MC/MCInstrItineraries.h" 310b57cec5SDimitry Andric #include "llvm/MC/MCSchedule.h" 325ffd83dbSDimitry Andric #include "llvm/Target/TargetMachine.h" 330b57cec5SDimitry Andric #include "llvm/Target/TargetOptions.h" 3406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 355f757f3fSDimitry Andric #include <bitset> 360b57cec5SDimitry Andric #include <memory> 370b57cec5SDimitry Andric #include <string> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #define GET_SUBTARGETINFO_HEADER 400b57cec5SDimitry Andric #include "ARMGenSubtargetInfo.inc" 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric namespace llvm { 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric class ARMBaseTargetMachine; 450b57cec5SDimitry Andric class GlobalValue; 460b57cec5SDimitry Andric class StringRef; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric class ARMSubtarget : public ARMGenSubtargetInfo { 490b57cec5SDimitry Andric protected: 500b57cec5SDimitry Andric enum ARMProcFamilyEnum { 510b57cec5SDimitry Andric Others, 520fca6ea1SDimitry Andric #define ARM_PROCESSOR_FAMILY(ENUM) ENUM, 530fca6ea1SDimitry Andric #include "llvm/TargetParser/ARMTargetParserDef.inc" 540fca6ea1SDimitry Andric #undef ARM_PROCESSOR_FAMILY 550b57cec5SDimitry Andric }; 560b57cec5SDimitry Andric enum ARMProcClassEnum { 570b57cec5SDimitry Andric None, 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric AClass, 600b57cec5SDimitry Andric MClass, 610b57cec5SDimitry Andric RClass 620b57cec5SDimitry Andric }; 630b57cec5SDimitry Andric enum ARMArchEnum { 640fca6ea1SDimitry Andric #define ARM_ARCHITECTURE(ENUM) ENUM, 650fca6ea1SDimitry Andric #include "llvm/TargetParser/ARMTargetParserDef.inc" 660fca6ea1SDimitry Andric #undef ARM_ARCHITECTURE 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric public: 700b57cec5SDimitry Andric /// What kind of timing do load multiple/store multiple instructions have. 710b57cec5SDimitry Andric enum ARMLdStMultipleTiming { 720b57cec5SDimitry Andric /// Can load/store 2 registers/cycle. 730b57cec5SDimitry Andric DoubleIssue, 740b57cec5SDimitry Andric /// Can load/store 2 registers/cycle, but needs an extra cycle if the access 750b57cec5SDimitry Andric /// is not 64-bit aligned. 760b57cec5SDimitry Andric DoubleIssueCheckUnalignedAccess, 770b57cec5SDimitry Andric /// Can load/store 1 register/cycle. 780b57cec5SDimitry Andric SingleIssue, 790b57cec5SDimitry Andric /// Can load/store 1 register/cycle, but needs an extra cycle for address 800b57cec5SDimitry Andric /// computation and potentially also for register writeback. 810b57cec5SDimitry Andric SingleIssuePlusExtras, 820b57cec5SDimitry Andric }; 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric protected: 8581ad6265SDimitry Andric // Bool members corresponding to the SubtargetFeatures defined in tablegen 8681ad6265SDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 8781ad6265SDimitry Andric bool ATTRIBUTE = DEFAULT; 8881ad6265SDimitry Andric #include "ARMGenSubtargetInfo.inc" 8981ad6265SDimitry Andric 900b57cec5SDimitry Andric /// ARMProcFamily - ARM processor family: Cortex-A8, Cortex-A9, and others. 910b57cec5SDimitry Andric ARMProcFamilyEnum ARMProcFamily = Others; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric /// ARMProcClass - ARM processor class: None, AClass, RClass or MClass. 940b57cec5SDimitry Andric ARMProcClassEnum ARMProcClass = None; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric /// ARMArch - ARM architecture 970b57cec5SDimitry Andric ARMArchEnum ARMArch = ARMv4t; 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric /// UseMulOps - True if non-microcoded fused integer multiply-add and 1000b57cec5SDimitry Andric /// multiply-subtract instructions should be used. 1010b57cec5SDimitry Andric bool UseMulOps = false; 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric /// SupportsTailCall - True if the OS supports tail call. The dynamic linker 1040b57cec5SDimitry Andric /// must be able to synthesize call stubs for interworking between ARM and 1050b57cec5SDimitry Andric /// Thumb. 1060b57cec5SDimitry Andric bool SupportsTailCall = false; 1070b57cec5SDimitry Andric 10881ad6265SDimitry Andric /// RestrictIT - If true, the subtarget disallows generation of complex IT 10981ad6265SDimitry Andric /// blocks. 1100b57cec5SDimitry Andric bool RestrictIT = false; 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric /// UseSjLjEH - If true, the target uses SjLj exception handling (e.g. iOS). 1130b57cec5SDimitry Andric bool UseSjLjEH = false; 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// stackAlignment - The minimum alignment known to hold of the stack frame on 1160b57cec5SDimitry Andric /// entry to the function and which must be maintained by every function. 1178bcb0991SDimitry Andric Align stackAlignment = Align(4); 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// CPUString - String name of used CPU. 1200b57cec5SDimitry Andric std::string CPUString; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric unsigned MaxInterleaveFactor = 1; 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric /// Clearance before partial register updates (in number of instructions) 1250b57cec5SDimitry Andric unsigned PartialUpdateClearance = 0; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// What kind of timing do load multiple/store multiple have (double issue, 1280b57cec5SDimitry Andric /// single issue etc). 1290b57cec5SDimitry Andric ARMLdStMultipleTiming LdStMultipleTiming = SingleIssue; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric /// The adjustment that we need to apply to get the operand latency from the 1320b57cec5SDimitry Andric /// operand cycle returned by the itinerary data for pre-ISel operands. 1330b57cec5SDimitry Andric int PreISelOperandLatencyAdjustment = 2; 1340b57cec5SDimitry Andric 1355f757f3fSDimitry Andric /// What alignment is preferred for loop bodies and functions, in log2(bytes). 1368bcb0991SDimitry Andric unsigned PrefLoopLogAlignment = 0; 1378bcb0991SDimitry Andric 1388bcb0991SDimitry Andric /// The cost factor for MVE instructions, representing the multiple beats an 1398bcb0991SDimitry Andric // instruction can take. The default is 2, (set in initSubtargetFeatures so 1408bcb0991SDimitry Andric // that we can use subtarget features less than 2). 1418bcb0991SDimitry Andric unsigned MVEVectorCostFactor = 0; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// OptMinSize - True if we're optimising for minimum code size, equal to 1440b57cec5SDimitry Andric /// the function attribute. 1450b57cec5SDimitry Andric bool OptMinSize = false; 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric /// IsLittle - The target is Little Endian 1480b57cec5SDimitry Andric bool IsLittle; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric /// TargetTriple - What processor and OS we're targeting. 1510b57cec5SDimitry Andric Triple TargetTriple; 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// SchedModel - Processor specific instruction costs. 1540b57cec5SDimitry Andric MCSchedModel SchedModel; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /// Selected instruction itineraries (one entry per itinerary class.) 1570b57cec5SDimitry Andric InstrItineraryData InstrItins; 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric /// Options passed via command line that could influence the target 1600b57cec5SDimitry Andric const TargetOptions &Options; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric const ARMBaseTargetMachine &TM; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric public: 1650b57cec5SDimitry Andric /// This constructor initializes the data members to match that 1660b57cec5SDimitry Andric /// of the specified triple. 1670b57cec5SDimitry Andric /// 1680b57cec5SDimitry Andric ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, 1690b57cec5SDimitry Andric const ARMBaseTargetMachine &TM, bool IsLittle, 1700b57cec5SDimitry Andric bool MinSize = false); 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric /// getMaxInlineSizeThreshold - Returns the maximum memset / memcpy size 1730b57cec5SDimitry Andric /// that still makes it profitable to inline the call. getMaxInlineSizeThreshold()1740b57cec5SDimitry Andric unsigned getMaxInlineSizeThreshold() const { 1750b57cec5SDimitry Andric return 64; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 178fe6060f1SDimitry Andric /// getMaxMemcpyTPInlineSizeThreshold - Returns the maximum size 179fe6060f1SDimitry Andric /// that still makes it profitable to inline a llvm.memcpy as a Tail 180fe6060f1SDimitry Andric /// Predicated loop. 181fe6060f1SDimitry Andric /// This threshold should only be used for constant size inputs. getMaxMemcpyTPInlineSizeThreshold()182fe6060f1SDimitry Andric unsigned getMaxMemcpyTPInlineSizeThreshold() const { return 128; } 183fe6060f1SDimitry Andric 1840b57cec5SDimitry Andric /// ParseSubtargetFeatures - Parses features string setting specified 1850b57cec5SDimitry Andric /// subtarget options. Definition of function is auto generated by tblgen. 186e8d8bef9SDimitry Andric void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric /// initializeSubtargetDependencies - Initializes using a CPU and feature string 1890b57cec5SDimitry Andric /// so that we can use initializer lists for subtarget initialization. 1900b57cec5SDimitry Andric ARMSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); 1910b57cec5SDimitry Andric getSelectionDAGInfo()1920b57cec5SDimitry Andric const ARMSelectionDAGInfo *getSelectionDAGInfo() const override { 1930b57cec5SDimitry Andric return &TSInfo; 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric getInstrInfo()1960b57cec5SDimitry Andric const ARMBaseInstrInfo *getInstrInfo() const override { 1970b57cec5SDimitry Andric return InstrInfo.get(); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric getTargetLowering()2000b57cec5SDimitry Andric const ARMTargetLowering *getTargetLowering() const override { 2010b57cec5SDimitry Andric return &TLInfo; 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric getFrameLowering()2040b57cec5SDimitry Andric const ARMFrameLowering *getFrameLowering() const override { 2050b57cec5SDimitry Andric return FrameLowering.get(); 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric getRegisterInfo()2080b57cec5SDimitry Andric const ARMBaseRegisterInfo *getRegisterInfo() const override { 2090b57cec5SDimitry Andric return &InstrInfo->getRegisterInfo(); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120fca6ea1SDimitry Andric /// The correct instructions have been implemented to initialize undef 2130fca6ea1SDimitry Andric /// registers, therefore the ARM Architecture is supported by the Init Undef 2140fca6ea1SDimitry Andric /// Pass. This will return true as the pass needs to be supported for all 2150fca6ea1SDimitry Andric /// types of instructions. The pass will then perform more checks to ensure it 2160fca6ea1SDimitry Andric /// should be applying the Pseudo Instructions. supportsInitUndef()2170fca6ea1SDimitry Andric bool supportsInitUndef() const override { return true; } 2180fca6ea1SDimitry Andric 2190b57cec5SDimitry Andric const CallLowering *getCallLowering() const override; 2208bcb0991SDimitry Andric InstructionSelector *getInstructionSelector() const override; 2210b57cec5SDimitry Andric const LegalizerInfo *getLegalizerInfo() const override; 2220b57cec5SDimitry Andric const RegisterBankInfo *getRegBankInfo() const override; 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric private: 2250b57cec5SDimitry Andric ARMSelectionDAGInfo TSInfo; 2260b57cec5SDimitry Andric // Either Thumb1FrameLowering or ARMFrameLowering. 2270b57cec5SDimitry Andric std::unique_ptr<ARMFrameLowering> FrameLowering; 2280b57cec5SDimitry Andric // Either Thumb1InstrInfo or Thumb2InstrInfo. 2290b57cec5SDimitry Andric std::unique_ptr<ARMBaseInstrInfo> InstrInfo; 2300b57cec5SDimitry Andric ARMTargetLowering TLInfo; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric /// GlobalISel related APIs. 2330b57cec5SDimitry Andric std::unique_ptr<CallLowering> CallLoweringInfo; 2340b57cec5SDimitry Andric std::unique_ptr<InstructionSelector> InstSelector; 2350b57cec5SDimitry Andric std::unique_ptr<LegalizerInfo> Legalizer; 2360b57cec5SDimitry Andric std::unique_ptr<RegisterBankInfo> RegBankInfo; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void initializeEnvironment(); 2390b57cec5SDimitry Andric void initSubtargetFeatures(StringRef CPU, StringRef FS); 2400b57cec5SDimitry Andric ARMFrameLowering *initializeFrameLowering(StringRef CPU, StringRef FS); 2410b57cec5SDimitry Andric 2425ffd83dbSDimitry Andric std::bitset<8> CoprocCDE = {}; 2430b57cec5SDimitry Andric public: 24481ad6265SDimitry Andric // Getters for SubtargetFeatures defined in tablegen 24581ad6265SDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 24681ad6265SDimitry Andric bool GETTER() const { return ATTRIBUTE; } 24781ad6265SDimitry Andric #include "ARMGenSubtargetInfo.inc" 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric /// @{ 2500b57cec5SDimitry Andric /// These functions are obsolete, please consider adding subtarget features 2510b57cec5SDimitry Andric /// or properties instead of calling them. isCortexA5()2520b57cec5SDimitry Andric bool isCortexA5() const { return ARMProcFamily == CortexA5; } isCortexA7()2530b57cec5SDimitry Andric bool isCortexA7() const { return ARMProcFamily == CortexA7; } isCortexA8()2540b57cec5SDimitry Andric bool isCortexA8() const { return ARMProcFamily == CortexA8; } isCortexA9()2550b57cec5SDimitry Andric bool isCortexA9() const { return ARMProcFamily == CortexA9; } isCortexA15()2560b57cec5SDimitry Andric bool isCortexA15() const { return ARMProcFamily == CortexA15; } isSwift()2570b57cec5SDimitry Andric bool isSwift() const { return ARMProcFamily == Swift; } isCortexM3()2580b57cec5SDimitry Andric bool isCortexM3() const { return ARMProcFamily == CortexM3; } isCortexM7()259e8d8bef9SDimitry Andric bool isCortexM7() const { return ARMProcFamily == CortexM7; } isLikeA9()2600b57cec5SDimitry Andric bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); } isCortexR5()2610b57cec5SDimitry Andric bool isCortexR5() const { return ARMProcFamily == CortexR5; } isKrait()2620b57cec5SDimitry Andric bool isKrait() const { return ARMProcFamily == Krait; } 2630b57cec5SDimitry Andric /// @} 2640b57cec5SDimitry Andric hasARMOps()2650b57cec5SDimitry Andric bool hasARMOps() const { return !NoARM; } 2660b57cec5SDimitry Andric useNEONForSinglePrecisionFP()2670b57cec5SDimitry Andric bool useNEONForSinglePrecisionFP() const { 26881ad6265SDimitry Andric return hasNEON() && hasNEONForFP(); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric hasVFP2Base()27181ad6265SDimitry Andric bool hasVFP2Base() const { return hasVFPv2SP(); } hasVFP3Base()27281ad6265SDimitry Andric bool hasVFP3Base() const { return hasVFPv3D16SP(); } hasVFP4Base()27381ad6265SDimitry Andric bool hasVFP4Base() const { return hasVFPv4D16SP(); } hasFPARMv8Base()27481ad6265SDimitry Andric bool hasFPARMv8Base() const { return hasFPARMv8D16SP(); } 2750b57cec5SDimitry Andric hasAnyDataBarrier()2760b57cec5SDimitry Andric bool hasAnyDataBarrier() const { 2770b57cec5SDimitry Andric return HasDataBarrier || (hasV6Ops() && !isThumb()); 2780b57cec5SDimitry Andric } 2790b57cec5SDimitry Andric useMulOps()2800b57cec5SDimitry Andric bool useMulOps() const { return UseMulOps; } useFPVMLx()2810b57cec5SDimitry Andric bool useFPVMLx() const { return !SlowFPVMLx; } useFPVFMx()282480093f4SDimitry Andric bool useFPVFMx() const { 283480093f4SDimitry Andric return !isTargetDarwin() && hasVFP4Base() && !SlowFPVFMx; 284480093f4SDimitry Andric } useFPVFMx16()285480093f4SDimitry Andric bool useFPVFMx16() const { return useFPVFMx() && hasFullFP16(); } useFPVFMx64()286480093f4SDimitry Andric bool useFPVFMx64() const { return useFPVFMx() && hasFP64(); } useSjLjEH()2870b57cec5SDimitry Andric bool useSjLjEH() const { return UseSjLjEH; } hasBaseDSP()2888bcb0991SDimitry Andric bool hasBaseDSP() const { 2898bcb0991SDimitry Andric if (isThumb()) 29006c3fb27SDimitry Andric return hasThumb2() && hasDSP(); 2918bcb0991SDimitry Andric else 2928bcb0991SDimitry Andric return hasV5TEOps(); 2938bcb0991SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric /// Return true if the CPU supports any kind of instruction fusion. hasFusion()2960b57cec5SDimitry Andric bool hasFusion() const { return hasFuseAES() || hasFuseLiterals(); } 2970b57cec5SDimitry Andric getTargetTriple()2980b57cec5SDimitry Andric const Triple &getTargetTriple() const { return TargetTriple; } 2990b57cec5SDimitry Andric isTargetDarwin()3000b57cec5SDimitry Andric bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } isTargetIOS()3010b57cec5SDimitry Andric bool isTargetIOS() const { return TargetTriple.isiOS(); } isTargetWatchOS()3020b57cec5SDimitry Andric bool isTargetWatchOS() const { return TargetTriple.isWatchOS(); } isTargetWatchABI()3030b57cec5SDimitry Andric bool isTargetWatchABI() const { return TargetTriple.isWatchABI(); } isTargetDriverKit()30481ad6265SDimitry Andric bool isTargetDriverKit() const { return TargetTriple.isDriverKit(); } isTargetLinux()3050b57cec5SDimitry Andric bool isTargetLinux() const { return TargetTriple.isOSLinux(); } isTargetNaCl()3060b57cec5SDimitry Andric bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } isTargetNetBSD()3070b57cec5SDimitry Andric bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); } isTargetWindows()3080b57cec5SDimitry Andric bool isTargetWindows() const { return TargetTriple.isOSWindows(); } 3090b57cec5SDimitry Andric isTargetCOFF()3100b57cec5SDimitry Andric bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } isTargetELF()3110b57cec5SDimitry Andric bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } isTargetMachO()3120b57cec5SDimitry Andric bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric // ARM EABI is the bare-metal EABI described in ARM ABI documents and 3150b57cec5SDimitry Andric // can be accessed via -target arm-none-eabi. This is NOT GNUEABI. 3160b57cec5SDimitry Andric // FIXME: Add a flag for bare-metal for that target and set Triple::EABI 3170b57cec5SDimitry Andric // even for GNUEABI, so we can make a distinction here and still conform to 3180b57cec5SDimitry Andric // the EABI on GNU (and Android) mode. This requires change in Clang, too. 3190b57cec5SDimitry Andric // FIXME: The Darwin exception is temporary, while we move users to 3200b57cec5SDimitry Andric // "*-*-*-macho" triples as quickly as possible. isTargetAEABI()3210b57cec5SDimitry Andric bool isTargetAEABI() const { 3220b57cec5SDimitry Andric return (TargetTriple.getEnvironment() == Triple::EABI || 3230b57cec5SDimitry Andric TargetTriple.getEnvironment() == Triple::EABIHF) && 3240b57cec5SDimitry Andric !isTargetDarwin() && !isTargetWindows(); 3250b57cec5SDimitry Andric } isTargetGNUAEABI()3260b57cec5SDimitry Andric bool isTargetGNUAEABI() const { 3270b57cec5SDimitry Andric return (TargetTriple.getEnvironment() == Triple::GNUEABI || 328*d686ce93SDimitry Andric TargetTriple.getEnvironment() == Triple::GNUEABIT64 || 329*d686ce93SDimitry Andric TargetTriple.getEnvironment() == Triple::GNUEABIHF || 330*d686ce93SDimitry Andric TargetTriple.getEnvironment() == Triple::GNUEABIHFT64) && 3310b57cec5SDimitry Andric !isTargetDarwin() && !isTargetWindows(); 3320b57cec5SDimitry Andric } isTargetMuslAEABI()3330b57cec5SDimitry Andric bool isTargetMuslAEABI() const { 3340b57cec5SDimitry Andric return (TargetTriple.getEnvironment() == Triple::MuslEABI || 33506c3fb27SDimitry Andric TargetTriple.getEnvironment() == Triple::MuslEABIHF || 33606c3fb27SDimitry Andric TargetTriple.getEnvironment() == Triple::OpenHOS) && 3370b57cec5SDimitry Andric !isTargetDarwin() && !isTargetWindows(); 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // ARM Targets that support EHABI exception handling standard 3410b57cec5SDimitry Andric // Darwin uses SjLj. Other targets might need more checks. isTargetEHABICompatible()3420b57cec5SDimitry Andric bool isTargetEHABICompatible() const { 343349cc55cSDimitry Andric return TargetTriple.isTargetEHABICompatible(); 3440b57cec5SDimitry Andric } 3450b57cec5SDimitry Andric 3460b57cec5SDimitry Andric bool isTargetHardFloat() const; 3470b57cec5SDimitry Andric isReadTPSoft()34806c3fb27SDimitry Andric bool isReadTPSoft() const { 34906c3fb27SDimitry Andric return !(isReadTPTPIDRURW() || isReadTPTPIDRURO() || isReadTPTPIDRPRW()); 35006c3fb27SDimitry Andric } 35106c3fb27SDimitry Andric isTargetAndroid()3520b57cec5SDimitry Andric bool isTargetAndroid() const { return TargetTriple.isAndroid(); } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric bool isXRaySupported() const override; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric bool isAPCS_ABI() const; 3570b57cec5SDimitry Andric bool isAAPCS_ABI() const; 3580b57cec5SDimitry Andric bool isAAPCS16_ABI() const; 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric bool isROPI() const; 3610b57cec5SDimitry Andric bool isRWPI() const; 3620b57cec5SDimitry Andric useMachineScheduler()3630b57cec5SDimitry Andric bool useMachineScheduler() const { return UseMISched; } useMachinePipeliner()36481ad6265SDimitry Andric bool useMachinePipeliner() const { return UseMIPipeliner; } hasMinSize()3650b57cec5SDimitry Andric bool hasMinSize() const { return OptMinSize; } isThumb1Only()36681ad6265SDimitry Andric bool isThumb1Only() const { return isThumb() && !hasThumb2(); } isThumb2()36781ad6265SDimitry Andric bool isThumb2() const { return isThumb() && hasThumb2(); } isMClass()3680b57cec5SDimitry Andric bool isMClass() const { return ARMProcClass == MClass; } isRClass()3690b57cec5SDimitry Andric bool isRClass() const { return ARMProcClass == RClass; } isAClass()3700b57cec5SDimitry Andric bool isAClass() const { return ARMProcClass == AClass; } 3710b57cec5SDimitry Andric isR9Reserved()3720b57cec5SDimitry Andric bool isR9Reserved() const { 3730b57cec5SDimitry Andric return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric getFramePointerReg()376fe6060f1SDimitry Andric MCPhysReg getFramePointerReg() const { 37781ad6265SDimitry Andric if (isTargetDarwin() || 37881ad6265SDimitry Andric (!isTargetWindows() && isThumb() && !createAAPCSFrameChain())) 379fe6060f1SDimitry Andric return ARM::R7; 380fe6060f1SDimitry Andric return ARM::R11; 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3830b57cec5SDimitry Andric /// Returns true if the frame setup is split into two separate pushes (first 3840b57cec5SDimitry Andric /// r0-r7,lr then r8-r11), principally so that the frame pointer is adjacent 3850b57cec5SDimitry Andric /// to lr. This is always required on Thumb1-only targets, as the push and 3860b57cec5SDimitry Andric /// pop instructions can't access the high registers. splitFramePushPop(const MachineFunction & MF)3870b57cec5SDimitry Andric bool splitFramePushPop(const MachineFunction &MF) const { 3880eae32dcSDimitry Andric if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress()) 3890eae32dcSDimitry Andric return true; 390fe6060f1SDimitry Andric return (getFramePointerReg() == ARM::R7 && 3910b57cec5SDimitry Andric MF.getTarget().Options.DisableFramePointerElim(MF)) || 3920b57cec5SDimitry Andric isThumb1Only(); 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric 39581ad6265SDimitry Andric bool splitFramePointerPush(const MachineFunction &MF) const; 39681ad6265SDimitry Andric 3970b57cec5SDimitry Andric bool useStride4VFPs() const; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric bool useMovt() const; 4000b57cec5SDimitry Andric supportsTailCall()4010b57cec5SDimitry Andric bool supportsTailCall() const { return SupportsTailCall; } 4020b57cec5SDimitry Andric allowsUnalignedMem()4030b57cec5SDimitry Andric bool allowsUnalignedMem() const { return !StrictAlign; } 4040b57cec5SDimitry Andric restrictIT()4050b57cec5SDimitry Andric bool restrictIT() const { return RestrictIT; } 4060b57cec5SDimitry Andric getCPUString()4070b57cec5SDimitry Andric const std::string & getCPUString() const { return CPUString; } 4080b57cec5SDimitry Andric isLittle()4090b57cec5SDimitry Andric bool isLittle() const { return IsLittle; } 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric unsigned getMispredictionPenalty() const; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric /// Returns true if machine scheduler should be enabled. 4140b57cec5SDimitry Andric bool enableMachineScheduler() const override; 4150b57cec5SDimitry Andric 41681ad6265SDimitry Andric /// Returns true if machine pipeliner should be enabled. 41781ad6265SDimitry Andric bool enableMachinePipeliner() const override; 41881ad6265SDimitry Andric bool useDFAforSMS() const override; 41981ad6265SDimitry Andric 4200b57cec5SDimitry Andric /// True for some subtargets at > -O0. 4210b57cec5SDimitry Andric bool enablePostRAScheduler() const override; 4220b57cec5SDimitry Andric 423480093f4SDimitry Andric /// True for some subtargets at > -O0. 424480093f4SDimitry Andric bool enablePostRAMachineScheduler() const override; 425480093f4SDimitry Andric 426480093f4SDimitry Andric /// Check whether this subtarget wants to use subregister liveness. 427480093f4SDimitry Andric bool enableSubRegLiveness() const override; 428480093f4SDimitry Andric 4290b57cec5SDimitry Andric /// Enable use of alias analysis during code generation (during MI 4300b57cec5SDimitry Andric /// scheduling, DAGCombine, etc.). useAA()431480093f4SDimitry Andric bool useAA() const override { return true; } 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric /// getInstrItins - Return the instruction itineraries based on subtarget 4340b57cec5SDimitry Andric /// selection. getInstrItineraryData()4350b57cec5SDimitry Andric const InstrItineraryData *getInstrItineraryData() const override { 4360b57cec5SDimitry Andric return &InstrItins; 4370b57cec5SDimitry Andric } 4380b57cec5SDimitry Andric 4390b57cec5SDimitry Andric /// getStackAlignment - Returns the minimum alignment known to hold of the 4400b57cec5SDimitry Andric /// stack frame on entry to the function and which must be maintained by every 4410b57cec5SDimitry Andric /// function for this subtarget. getStackAlignment()4428bcb0991SDimitry Andric Align getStackAlignment() const { return stackAlignment; } 4430b57cec5SDimitry Andric 44406c3fb27SDimitry Andric // Returns the required alignment for LDRD/STRD instructions getDualLoadStoreAlignment()44506c3fb27SDimitry Andric Align getDualLoadStoreAlignment() const { 44606c3fb27SDimitry Andric return Align(hasV7Ops() || allowsUnalignedMem() ? 4 : 8); 44706c3fb27SDimitry Andric } 44806c3fb27SDimitry Andric getMaxInterleaveFactor()4490b57cec5SDimitry Andric unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } 4500b57cec5SDimitry Andric getPartialUpdateClearance()4510b57cec5SDimitry Andric unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; } 4520b57cec5SDimitry Andric getLdStMultipleTiming()4530b57cec5SDimitry Andric ARMLdStMultipleTiming getLdStMultipleTiming() const { 4540b57cec5SDimitry Andric return LdStMultipleTiming; 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric getPreISelOperandLatencyAdjustment()4570b57cec5SDimitry Andric int getPreISelOperandLatencyAdjustment() const { 4580b57cec5SDimitry Andric return PreISelOperandLatencyAdjustment; 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric /// True if the GV will be accessed via an indirect symbol. 4620b57cec5SDimitry Andric bool isGVIndirectSymbol(const GlobalValue *GV) const; 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric /// Returns the constant pool modifier needed to access the GV. 4650b57cec5SDimitry Andric bool isGVInGOT(const GlobalValue *GV) const; 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric /// True if fast-isel is used. 4680b57cec5SDimitry Andric bool useFastISel() const; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric /// Returns the correct return opcode for the current feature set. 4710b57cec5SDimitry Andric /// Use BX if available to allow mixing thumb/arm code, but fall back 4720b57cec5SDimitry Andric /// to plain mov pc,lr on ARMv4. getReturnOpcode()4730b57cec5SDimitry Andric unsigned getReturnOpcode() const { 4740b57cec5SDimitry Andric if (isThumb()) 4750b57cec5SDimitry Andric return ARM::tBX_RET; 4760b57cec5SDimitry Andric if (hasV4TOps()) 4770b57cec5SDimitry Andric return ARM::BX_RET; 4780b57cec5SDimitry Andric return ARM::MOVPCLR; 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric /// Allow movt+movw for PIC global address calculation. 4820b57cec5SDimitry Andric /// ELF does not have GOT relocations for movt+movw. 4830b57cec5SDimitry Andric /// ROPI does not use GOT. allowPositionIndependentMovt()4840b57cec5SDimitry Andric bool allowPositionIndependentMovt() const { 4850b57cec5SDimitry Andric return isROPI() || !isTargetELF(); 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric getPrefLoopLogAlignment()4888bcb0991SDimitry Andric unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; } 4898bcb0991SDimitry Andric 490fe6060f1SDimitry Andric unsigned getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind)491fe6060f1SDimitry Andric getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind) const { 492fe6060f1SDimitry Andric if (CostKind == TargetTransformInfo::TCK_CodeSize) 493fe6060f1SDimitry Andric return 1; 494fe6060f1SDimitry Andric return MVEVectorCostFactor; 495fe6060f1SDimitry Andric } 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric bool ignoreCSRForAllocationOrder(const MachineFunction &MF, 4980b57cec5SDimitry Andric unsigned PhysReg) const override; 4990b57cec5SDimitry Andric unsigned getGPRAllocationOrder(const MachineFunction &MF) const; 5000b57cec5SDimitry Andric }; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric } // end namespace llvm 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H 505