xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMSubtarget.h (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
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