#ifndef LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
#define LLVM_LIB_TARGET_ARM_ARMSUBTARGET_H
#include "ARMBaseInstrInfo.h"
#include "ARMBaseRegisterInfo.h"
#include "ARMConstantPoolValue.h"
#include "ARMFrameLowering.h"
#include "ARMISelLowering.h"
#include "ARMMachineFunctionInfo.h"
#include "ARMSelectionDAGInfo.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/GlobalISel/CallLowering.h"
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/RegisterBankInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/MC/MCSchedule.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <memory>
#include <string>
#define GET_SUBTARGETINFO_HEADER
#include "ARMGenSubtargetInfo.inc"
namespace llvm {
class ARMBaseTargetMachine;
class GlobalValue;
class StringRef;
class ARMSubtarget : public ARMGenSubtargetInfo {
protected:
enum ARMProcFamilyEnum {
Others,
CortexA12,
CortexA15,
CortexA17,
CortexA32,
CortexA35,
CortexA5,
CortexA53,
CortexA55,
CortexA57,
CortexA7,
CortexA72,
CortexA73,
CortexA75,
CortexA76,
CortexA77,
CortexA78,
CortexA78C,
CortexA710,
CortexA8,
CortexA9,
CortexM3,
CortexM7,
CortexR4,
CortexR4F,
CortexR5,
CortexR52,
CortexR7,
CortexX1,
CortexX1C,
Exynos,
Krait,
Kryo,
NeoverseN1,
NeoverseN2,
NeoverseV1,
Swift
};
enum ARMProcClassEnum {
None,
AClass,
MClass,
RClass
};
enum ARMArchEnum {
ARMv2,
ARMv2a,
ARMv3,
ARMv3m,
ARMv4,
ARMv4t,
ARMv5,
ARMv5t,
ARMv5te,
ARMv5tej,
ARMv6,
ARMv6k,
ARMv6kz,
ARMv6m,
ARMv6sm,
ARMv6t2,
ARMv7a,
ARMv7em,
ARMv7m,
ARMv7r,
ARMv7ve,
ARMv81a,
ARMv82a,
ARMv83a,
ARMv84a,
ARMv85a,
ARMv86a,
ARMv87a,
ARMv88a,
ARMv8a,
ARMv8mBaseline,
ARMv8mMainline,
ARMv8r,
ARMv81mMainline,
ARMv9a,
ARMv91a,
ARMv92a,
ARMv93a,
};
public:
enum ARMLdStMultipleTiming {
DoubleIssue,
DoubleIssueCheckUnalignedAccess,
SingleIssue,
SingleIssuePlusExtras,
};
protected:
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool ATTRIBUTE = DEFAULT;
#include "ARMGenSubtargetInfo.inc"
ARMProcFamilyEnum ARMProcFamily = Others;
ARMProcClassEnum ARMProcClass = None;
ARMArchEnum ARMArch = ARMv4t;
bool UseMulOps = false;
bool SupportsTailCall = false;
bool RestrictIT = false;
bool UseSjLjEH = false;
Align stackAlignment = Align(4);
std::string CPUString;
unsigned MaxInterleaveFactor = 1;
unsigned PartialUpdateClearance = 0;
ARMLdStMultipleTiming LdStMultipleTiming = SingleIssue;
int PreISelOperandLatencyAdjustment = 2;
unsigned PrefLoopLogAlignment = 0;
unsigned MVEVectorCostFactor = 0;
bool OptMinSize = false;
bool IsLittle;
Triple TargetTriple;
MCSchedModel SchedModel;
InstrItineraryData InstrItins;
const TargetOptions &Options;
const ARMBaseTargetMachine &TM;
public:
ARMSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS,
const ARMBaseTargetMachine &TM, bool IsLittle,
bool MinSize = false);
unsigned getMaxInlineSizeThreshold() const {
return 64;
}
unsigned getMaxMemcpyTPInlineSizeThreshold() const { return 128; }
void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
ARMSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS);
const ARMSelectionDAGInfo *getSelectionDAGInfo() const override {
return &TSInfo;
}
const ARMBaseInstrInfo *getInstrInfo() const override {
return InstrInfo.get();
}
const ARMTargetLowering *getTargetLowering() const override {
return &TLInfo;
}
const ARMFrameLowering *getFrameLowering() const override {
return FrameLowering.get();
}
const ARMBaseRegisterInfo *getRegisterInfo() const override {
return &InstrInfo->getRegisterInfo();
}
const CallLowering *getCallLowering() const override;
InstructionSelector *getInstructionSelector() const override;
const LegalizerInfo *getLegalizerInfo() const override;
const RegisterBankInfo *getRegBankInfo() const override;
private:
ARMSelectionDAGInfo TSInfo;
std::unique_ptr<ARMFrameLowering> FrameLowering;
std::unique_ptr<ARMBaseInstrInfo> InstrInfo;
ARMTargetLowering TLInfo;
std::unique_ptr<CallLowering> CallLoweringInfo;
std::unique_ptr<InstructionSelector> InstSelector;
std::unique_ptr<LegalizerInfo> Legalizer;
std::unique_ptr<RegisterBankInfo> RegBankInfo;
void initializeEnvironment();
void initSubtargetFeatures(StringRef CPU, StringRef FS);
ARMFrameLowering *initializeFrameLowering(StringRef CPU, StringRef FS);
std::bitset<8> CoprocCDE = {};
public:
#define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \
bool GETTER() const { return ATTRIBUTE; }
#include "ARMGenSubtargetInfo.inc"
void computeIssueWidth();
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 ARMProcFamily == CortexM3; }
bool isCortexM7() const { return ARMProcFamily == CortexM7; }
bool isLikeA9() const { return isCortexA9() || isCortexA15() || isKrait(); }
bool isCortexR5() const { return ARMProcFamily == CortexR5; }
bool isKrait() const { return ARMProcFamily == Krait; }
bool hasARMOps() const { return !NoARM; }
bool useNEONForSinglePrecisionFP() const {
return hasNEON() && hasNEONForFP();
}
bool hasVFP2Base() const { return hasVFPv2SP(); }
bool hasVFP3Base() const { return hasVFPv3D16SP(); }
bool hasVFP4Base() const { return hasVFPv4D16SP(); }
bool hasFPARMv8Base() const { return hasFPARMv8D16SP(); }
bool hasAnyDataBarrier() const {
return HasDataBarrier || (hasV6Ops() && !isThumb());
}
bool useMulOps() const { return UseMulOps; }
bool useFPVMLx() const { return !SlowFPVMLx; }
bool useFPVFMx() const {
return !isTargetDarwin() && hasVFP4Base() && !SlowFPVFMx;
}
bool useFPVFMx16() const { return useFPVFMx() && hasFullFP16(); }
bool useFPVFMx64() const { return useFPVFMx() && hasFP64(); }
bool useSjLjEH() const { return UseSjLjEH; }
bool hasBaseDSP() const {
if (isThumb())
return hasDSP();
else
return hasV5TEOps();
}
bool hasFusion() const { return hasFuseAES() || hasFuseLiterals(); }
const Triple &getTargetTriple() const { return TargetTriple; }
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 isTargetDriverKit() const { return TargetTriple.isDriverKit(); }
bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
bool isTargetNetBSD() const { return TargetTriple.isOSNetBSD(); }
bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
bool isTargetAEABI() const {
return (TargetTriple.getEnvironment() == Triple::EABI ||
TargetTriple.getEnvironment() == Triple::EABIHF) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetGNUAEABI() const {
return (TargetTriple.getEnvironment() == Triple::GNUEABI ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetMuslAEABI() const {
return (TargetTriple.getEnvironment() == Triple::MuslEABI ||
TargetTriple.getEnvironment() == Triple::MuslEABIHF) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetEHABICompatible() const {
return TargetTriple.isTargetEHABICompatible();
}
bool isTargetHardFloat() const;
bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
bool isXRaySupported() const override;
bool isAPCS_ABI() const;
bool isAAPCS_ABI() const;
bool isAAPCS16_ABI() const;
bool isROPI() const;
bool isRWPI() const;
bool useMachineScheduler() const { return UseMISched; }
bool useMachinePipeliner() const { return UseMIPipeliner; }
bool hasMinSize() const { return OptMinSize; }
bool isThumb1Only() const { return isThumb() && !hasThumb2(); }
bool isThumb2() const { return isThumb() && hasThumb2(); }
bool isMClass() const { return ARMProcClass == MClass; }
bool isRClass() const { return ARMProcClass == RClass; }
bool isAClass() const { return ARMProcClass == AClass; }
bool isR9Reserved() const {
return isTargetMachO() ? (ReserveR9 || !HasV6Ops) : ReserveR9;
}
MCPhysReg getFramePointerReg() const {
if (isTargetDarwin() ||
(!isTargetWindows() && isThumb() && !createAAPCSFrameChain()))
return ARM::R7;
return ARM::R11;
}
bool splitFramePushPop(const MachineFunction &MF) const {
if (MF.getInfo<ARMFunctionInfo>()->shouldSignReturnAddress())
return true;
return (getFramePointerReg() == ARM::R7 &&
MF.getTarget().Options.DisableFramePointerElim(MF)) ||
isThumb1Only();
}
bool splitFramePointerPush(const MachineFunction &MF) const;
bool useStride4VFPs() const;
bool useMovt() const;
bool supportsTailCall() const { return SupportsTailCall; }
bool allowsUnalignedMem() const { return !StrictAlign; }
bool restrictIT() const { return RestrictIT; }
const std::string & getCPUString() const { return CPUString; }
bool isLittle() const { return IsLittle; }
unsigned getMispredictionPenalty() const;
bool enableMachineScheduler() const override;
bool enableMachinePipeliner() const override;
bool useDFAforSMS() const override;
bool enablePostRAScheduler() const override;
bool enablePostRAMachineScheduler() const override;
bool enableSubRegLiveness() const override;
bool useAA() const override { return true; }
const InstrItineraryData *getInstrItineraryData() const override {
return &InstrItins;
}
Align getStackAlignment() const { return stackAlignment; }
unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
unsigned getPartialUpdateClearance() const { return PartialUpdateClearance; }
ARMLdStMultipleTiming getLdStMultipleTiming() const {
return LdStMultipleTiming;
}
int getPreISelOperandLatencyAdjustment() const {
return PreISelOperandLatencyAdjustment;
}
bool isGVIndirectSymbol(const GlobalValue *GV) const;
bool isGVInGOT(const GlobalValue *GV) const;
bool useFastISel() const;
unsigned getReturnOpcode() const {
if (isThumb())
return ARM::tBX_RET;
if (hasV4TOps())
return ARM::BX_RET;
return ARM::MOVPCLR;
}
bool allowPositionIndependentMovt() const {
return isROPI() || !isTargetELF();
}
unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
unsigned
getMVEVectorCostFactor(TargetTransformInfo::TargetCostKind CostKind) const {
if (CostKind == TargetTransformInfo::TCK_CodeSize)
return 1;
return MVEVectorCostFactor;
}
bool ignoreCSRForAllocationOrder(const MachineFunction &MF,
unsigned PhysReg) const override;
unsigned getGPRAllocationOrder(const MachineFunction &MF) const;
};
}
#endif