10b57cec5SDimitry Andric //===--- AArch64Subtarget.h - Define Subtarget for the AArch64 -*- 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 AArch64 specific subclass of TargetSubtarget. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "AArch64FrameLowering.h" 170b57cec5SDimitry Andric #include "AArch64ISelLowering.h" 180b57cec5SDimitry Andric #include "AArch64InstrInfo.h" 195f757f3fSDimitry Andric #include "AArch64PointerAuth.h" 200b57cec5SDimitry Andric #include "AArch64RegisterInfo.h" 210b57cec5SDimitry Andric #include "AArch64SelectionDAGInfo.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/CallLowering.h" 235ffd83dbSDimitry Andric #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/InstructionSelector.h" 250b57cec5SDimitry Andric #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" 2681ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 280b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric #define GET_SUBTARGETINFO_HEADER 310b57cec5SDimitry Andric #include "AArch64GenSubtargetInfo.inc" 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric namespace llvm { 340b57cec5SDimitry Andric class GlobalValue; 350b57cec5SDimitry Andric class StringRef; 360b57cec5SDimitry Andric class Triple; 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric class AArch64Subtarget final : public AArch64GenSubtargetInfo { 390b57cec5SDimitry Andric public: 400b57cec5SDimitry Andric enum ARMProcFamilyEnum : uint8_t { 410b57cec5SDimitry Andric Others, 420fca6ea1SDimitry Andric #define ARM_PROCESSOR_FAMILY(ENUM) ENUM, 430fca6ea1SDimitry Andric #include "llvm/TargetParser/AArch64TargetParserDef.inc" 440fca6ea1SDimitry Andric #undef ARM_PROCESSOR_FAMILY 450b57cec5SDimitry Andric }; 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric protected: 480b57cec5SDimitry Andric /// ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others. 490b57cec5SDimitry Andric ARMProcFamilyEnum ARMProcFamily = Others; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric // Enable 64-bit vectorization in SLP. 520b57cec5SDimitry Andric unsigned MinVectorRegisterBitWidth = 64; 530b57cec5SDimitry Andric 5481ad6265SDimitry Andric // Bool members corresponding to the SubtargetFeatures defined in tablegen 5581ad6265SDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 5681ad6265SDimitry Andric bool ATTRIBUTE = DEFAULT; 5781ad6265SDimitry Andric #include "AArch64GenSubtargetInfo.inc" 583a9a9c0cSDimitry Andric 590b57cec5SDimitry Andric uint8_t MaxInterleaveFactor = 2; 605f757f3fSDimitry Andric uint8_t VectorInsertExtractBaseCost = 2; 610b57cec5SDimitry Andric uint16_t CacheLineSize = 0; 620b57cec5SDimitry Andric uint16_t PrefetchDistance = 0; 630b57cec5SDimitry Andric uint16_t MinPrefetchStride = 1; 640b57cec5SDimitry Andric unsigned MaxPrefetchIterationsAhead = UINT_MAX; 6506c3fb27SDimitry Andric Align PrefFunctionAlignment; 6606c3fb27SDimitry Andric Align PrefLoopAlignment; 6704eeddc0SDimitry Andric unsigned MaxBytesForLoopAlignment = 0; 685f757f3fSDimitry Andric unsigned MinimumJumpTableEntries = 4; 690b57cec5SDimitry Andric unsigned MaxJumpTableSize = 0; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric // ReserveXRegister[i] - X#i is not available as a general purpose register. 720b57cec5SDimitry Andric BitVector ReserveXRegister; 730b57cec5SDimitry Andric 74bdd1243dSDimitry Andric // ReserveXRegisterForRA[i] - X#i is not available for register allocator. 75bdd1243dSDimitry Andric BitVector ReserveXRegisterForRA; 76bdd1243dSDimitry Andric 770b57cec5SDimitry Andric // CustomCallUsedXRegister[i] - X#i call saved. 780b57cec5SDimitry Andric BitVector CustomCallSavedXRegs; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric bool IsLittle; 810b57cec5SDimitry Andric 820fca6ea1SDimitry Andric bool IsStreaming; 830fca6ea1SDimitry Andric bool IsStreamingCompatible; 84fe6060f1SDimitry Andric unsigned MinSVEVectorSizeInBits; 85fe6060f1SDimitry Andric unsigned MaxSVEVectorSizeInBits; 86349cc55cSDimitry Andric unsigned VScaleForTuning = 2; 8706c3fb27SDimitry Andric TailFoldingOpts DefaultSVETFOpts = TailFoldingOpts::Disabled; 88fe6060f1SDimitry Andric 890b57cec5SDimitry Andric /// TargetTriple - What processor and OS we're targeting. 900b57cec5SDimitry Andric Triple TargetTriple; 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric AArch64FrameLowering FrameLowering; 930b57cec5SDimitry Andric AArch64InstrInfo InstrInfo; 940b57cec5SDimitry Andric AArch64SelectionDAGInfo TSInfo; 950b57cec5SDimitry Andric AArch64TargetLowering TLInfo; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric /// GlobalISel related APIs. 980b57cec5SDimitry Andric std::unique_ptr<CallLowering> CallLoweringInfo; 995ffd83dbSDimitry Andric std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo; 1000b57cec5SDimitry Andric std::unique_ptr<InstructionSelector> InstSelector; 1010b57cec5SDimitry Andric std::unique_ptr<LegalizerInfo> Legalizer; 1020b57cec5SDimitry Andric std::unique_ptr<RegisterBankInfo> RegBankInfo; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric private: 1050b57cec5SDimitry Andric /// initializeSubtargetDependencies - Initializes using CPUString and the 1060b57cec5SDimitry Andric /// passed in feature string so that we can use initializer lists for 1070b57cec5SDimitry Andric /// subtarget initialization. 1080b57cec5SDimitry Andric AArch64Subtarget &initializeSubtargetDependencies(StringRef FS, 109349cc55cSDimitry Andric StringRef CPUString, 1105f757f3fSDimitry Andric StringRef TuneCPUString, 1115f757f3fSDimitry Andric bool HasMinSize); 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric /// Initialize properties based on the selected processor family. 1145f757f3fSDimitry Andric void initializeProperties(bool HasMinSize); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric public: 1170b57cec5SDimitry Andric /// This constructor initializes the data members to match that 1180b57cec5SDimitry Andric /// of the specified triple. 119bdd1243dSDimitry Andric AArch64Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU, 120bdd1243dSDimitry Andric StringRef FS, const TargetMachine &TM, bool LittleEndian, 121fe6060f1SDimitry Andric unsigned MinSVEVectorSizeInBitsOverride = 0, 122bdd1243dSDimitry Andric unsigned MaxSVEVectorSizeInBitsOverride = 0, 1230fca6ea1SDimitry Andric bool IsStreaming = false, bool IsStreamingCompatible = false, 1245f757f3fSDimitry Andric bool HasMinSize = false); 1250b57cec5SDimitry Andric 12681ad6265SDimitry Andric // Getters for SubtargetFeatures defined in tablegen 12781ad6265SDimitry Andric #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER) \ 12881ad6265SDimitry Andric bool GETTER() const { return ATTRIBUTE; } 12981ad6265SDimitry Andric #include "AArch64GenSubtargetInfo.inc" 13081ad6265SDimitry Andric getSelectionDAGInfo()1310b57cec5SDimitry Andric const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override { 1320b57cec5SDimitry Andric return &TSInfo; 1330b57cec5SDimitry Andric } getFrameLowering()1340b57cec5SDimitry Andric const AArch64FrameLowering *getFrameLowering() const override { 1350b57cec5SDimitry Andric return &FrameLowering; 1360b57cec5SDimitry Andric } getTargetLowering()1370b57cec5SDimitry Andric const AArch64TargetLowering *getTargetLowering() const override { 1380b57cec5SDimitry Andric return &TLInfo; 1390b57cec5SDimitry Andric } getInstrInfo()1400b57cec5SDimitry Andric const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; } getRegisterInfo()1410b57cec5SDimitry Andric const AArch64RegisterInfo *getRegisterInfo() const override { 1420b57cec5SDimitry Andric return &getInstrInfo()->getRegisterInfo(); 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric const CallLowering *getCallLowering() const override; 1455ffd83dbSDimitry Andric const InlineAsmLowering *getInlineAsmLowering() const override; 1468bcb0991SDimitry Andric InstructionSelector *getInstructionSelector() const override; 1470b57cec5SDimitry Andric const LegalizerInfo *getLegalizerInfo() const override; 1480b57cec5SDimitry Andric const RegisterBankInfo *getRegBankInfo() const override; getTargetTriple()1490b57cec5SDimitry Andric const Triple &getTargetTriple() const { return TargetTriple; } enableMachineScheduler()1500b57cec5SDimitry Andric bool enableMachineScheduler() const override { return true; } enablePostRAScheduler()15181ad6265SDimitry Andric bool enablePostRAScheduler() const override { return usePostRAScheduler(); } 1520b57cec5SDimitry Andric 1530fca6ea1SDimitry Andric bool enableMachinePipeliner() const override; useDFAforSMS()1540fca6ea1SDimitry Andric bool useDFAforSMS() const override { return false; } 1550fca6ea1SDimitry Andric 1560b57cec5SDimitry Andric /// Returns ARM processor family. 1570b57cec5SDimitry Andric /// Avoid this function! CPU specifics should be kept local to this class 1580b57cec5SDimitry Andric /// and preferably modeled with SubtargetFeatures or properties in 1590b57cec5SDimitry Andric /// initializeProperties(). getProcFamily()1600b57cec5SDimitry Andric ARMProcFamilyEnum getProcFamily() const { 1610b57cec5SDimitry Andric return ARMProcFamily; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric isXRaySupported()1640b57cec5SDimitry Andric bool isXRaySupported() const override { return true; } 1650b57cec5SDimitry Andric 1665f757f3fSDimitry Andric /// Returns true if the function has a streaming body. isStreaming()1670fca6ea1SDimitry Andric bool isStreaming() const { return IsStreaming; } 16806c3fb27SDimitry Andric 1695f757f3fSDimitry Andric /// Returns true if the function has a streaming-compatible body. isStreamingCompatible()1700fca6ea1SDimitry Andric bool isStreamingCompatible() const { return IsStreamingCompatible; } 17106c3fb27SDimitry Andric 17206c3fb27SDimitry Andric /// Returns true if the target has NEON and the function at runtime is known 17306c3fb27SDimitry Andric /// to have NEON enabled (e.g. the function is known not to be in streaming-SVE 17406c3fb27SDimitry Andric /// mode, which disables NEON instructions). isNeonAvailable()1750fca6ea1SDimitry Andric bool isNeonAvailable() const { 1760fca6ea1SDimitry Andric return hasNEON() && 1770fca6ea1SDimitry Andric (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); 1780fca6ea1SDimitry Andric } 17906c3fb27SDimitry Andric 1805f757f3fSDimitry Andric /// Returns true if the target has SVE and can use the full range of SVE 1815f757f3fSDimitry Andric /// instructions, for example because it knows the function is known not to be 1825f757f3fSDimitry Andric /// in streaming-SVE mode or when the target has FEAT_FA64 enabled. isSVEAvailable()1830fca6ea1SDimitry Andric bool isSVEAvailable() const { 1840fca6ea1SDimitry Andric return hasSVE() && 1850fca6ea1SDimitry Andric (hasSMEFA64() || (!isStreaming() && !isStreamingCompatible())); 1860fca6ea1SDimitry Andric } 1870fca6ea1SDimitry Andric 1880fca6ea1SDimitry Andric /// Returns true if the target has access to either the full range of SVE instructions, 1890fca6ea1SDimitry Andric /// or the streaming-compatible subset of SVE instructions. isSVEorStreamingSVEAvailable()1900fca6ea1SDimitry Andric bool isSVEorStreamingSVEAvailable() const { 1910fca6ea1SDimitry Andric return hasSVE() || (hasSME() && isStreaming()); 1920fca6ea1SDimitry Andric } 1935f757f3fSDimitry Andric getMinVectorRegisterBitWidth()1940b57cec5SDimitry Andric unsigned getMinVectorRegisterBitWidth() const { 1955f757f3fSDimitry Andric // Don't assume any minimum vector size when PSTATE.SM may not be 0, because 1965f757f3fSDimitry Andric // we don't yet support streaming-compatible codegen support that we trust 1975f757f3fSDimitry Andric // is safe for functions that may be executed in streaming-SVE mode. 1985f757f3fSDimitry Andric // By returning '0' here, we disable vectorization. 1995f757f3fSDimitry Andric if (!isSVEAvailable() && !isNeonAvailable()) 200bdd1243dSDimitry Andric return 0; 2010b57cec5SDimitry Andric return MinVectorRegisterBitWidth; 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric isXRegisterReserved(size_t i)2040b57cec5SDimitry Andric bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; } isXRegisterReservedForRA(size_t i)205bdd1243dSDimitry Andric bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; } getNumXRegisterReserved()206bdd1243dSDimitry Andric unsigned getNumXRegisterReserved() const { 207bdd1243dSDimitry Andric BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs()); 208bdd1243dSDimitry Andric AllReservedX |= ReserveXRegister; 209bdd1243dSDimitry Andric AllReservedX |= ReserveXRegisterForRA; 210bdd1243dSDimitry Andric return AllReservedX.count(); 211bdd1243dSDimitry Andric } isLRReservedForRA()2120fca6ea1SDimitry Andric bool isLRReservedForRA() const { return ReserveLRForRA; } isXRegCustomCalleeSaved(size_t i)2130b57cec5SDimitry Andric bool isXRegCustomCalleeSaved(size_t i) const { 2140b57cec5SDimitry Andric return CustomCallSavedXRegs[i]; 2150b57cec5SDimitry Andric } hasCustomCallingConv()2160b57cec5SDimitry Andric bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); } 2170b57cec5SDimitry Andric 2180b57cec5SDimitry Andric /// Return true if the CPU supports any kind of instruction fusion. hasFusion()2190b57cec5SDimitry Andric bool hasFusion() const { 2200b57cec5SDimitry Andric return hasArithmeticBccFusion() || hasArithmeticCbzFusion() || 22181ad6265SDimitry Andric hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCCSelect() || 22281ad6265SDimitry Andric hasFuseAdrpAdd() || hasFuseLiterals(); 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric getMaxInterleaveFactor()2250b57cec5SDimitry Andric unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; } 22681ad6265SDimitry Andric unsigned getVectorInsertExtractBaseCost() const; getCacheLineSize()2278bcb0991SDimitry Andric unsigned getCacheLineSize() const override { return CacheLineSize; } getPrefetchDistance()2288bcb0991SDimitry Andric unsigned getPrefetchDistance() const override { return PrefetchDistance; } getMinPrefetchStride(unsigned NumMemAccesses,unsigned NumStridedMemAccesses,unsigned NumPrefetches,bool HasCall)2295ffd83dbSDimitry Andric unsigned getMinPrefetchStride(unsigned NumMemAccesses, 2305ffd83dbSDimitry Andric unsigned NumStridedMemAccesses, 2315ffd83dbSDimitry Andric unsigned NumPrefetches, 2325ffd83dbSDimitry Andric bool HasCall) const override { 2335ffd83dbSDimitry Andric return MinPrefetchStride; 2345ffd83dbSDimitry Andric } getMaxPrefetchIterationsAhead()2358bcb0991SDimitry Andric unsigned getMaxPrefetchIterationsAhead() const override { 2360b57cec5SDimitry Andric return MaxPrefetchIterationsAhead; 2370b57cec5SDimitry Andric } getPrefFunctionAlignment()23806c3fb27SDimitry Andric Align getPrefFunctionAlignment() const { 23906c3fb27SDimitry Andric return PrefFunctionAlignment; 2408bcb0991SDimitry Andric } getPrefLoopAlignment()24106c3fb27SDimitry Andric Align getPrefLoopAlignment() const { return PrefLoopAlignment; } 2420b57cec5SDimitry Andric getMaxBytesForLoopAlignment()24304eeddc0SDimitry Andric unsigned getMaxBytesForLoopAlignment() const { 24404eeddc0SDimitry Andric return MaxBytesForLoopAlignment; 24504eeddc0SDimitry Andric } 24604eeddc0SDimitry Andric getMaximumJumpTableSize()2470b57cec5SDimitry Andric unsigned getMaximumJumpTableSize() const { return MaxJumpTableSize; } getMinimumJumpTableEntries()2485f757f3fSDimitry Andric unsigned getMinimumJumpTableEntries() const { 2495f757f3fSDimitry Andric return MinimumJumpTableEntries; 2505f757f3fSDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric /// CPU has TBI (top byte of addresses is ignored during HW address 2530b57cec5SDimitry Andric /// translation) and OS enables it. 2540b57cec5SDimitry Andric bool supportsAddressTopByteIgnored() const; 2550b57cec5SDimitry Andric isLittleEndian()2560b57cec5SDimitry Andric bool isLittleEndian() const { return IsLittle; } 2570b57cec5SDimitry Andric isTargetDarwin()2580b57cec5SDimitry Andric bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); } isTargetIOS()2590b57cec5SDimitry Andric bool isTargetIOS() const { return TargetTriple.isiOS(); } isTargetLinux()2600b57cec5SDimitry Andric bool isTargetLinux() const { return TargetTriple.isOSLinux(); } isTargetWindows()2610b57cec5SDimitry Andric bool isTargetWindows() const { return TargetTriple.isOSWindows(); } isTargetAndroid()2620b57cec5SDimitry Andric bool isTargetAndroid() const { return TargetTriple.isAndroid(); } isTargetFuchsia()2630b57cec5SDimitry Andric bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); } isWindowsArm64EC()264bdd1243dSDimitry Andric bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); } 2650b57cec5SDimitry Andric isTargetCOFF()2660b57cec5SDimitry Andric bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); } isTargetELF()2670b57cec5SDimitry Andric bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); } isTargetMachO()2680b57cec5SDimitry Andric bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); } 2690b57cec5SDimitry Andric isTargetILP32()270e8d8bef9SDimitry Andric bool isTargetILP32() const { 271e8d8bef9SDimitry Andric return TargetTriple.isArch32Bit() || 272e8d8bef9SDimitry Andric TargetTriple.getEnvironment() == Triple::GNUILP32; 273e8d8bef9SDimitry Andric } 2748bcb0991SDimitry Andric 275fe6060f1SDimitry Andric bool useAA() const override; 2760b57cec5SDimitry Andric addrSinkUsingGEPs()2778bcb0991SDimitry Andric bool addrSinkUsingGEPs() const override { 2788bcb0991SDimitry Andric // Keeping GEPs inbounds is important for exploiting AArch64 2798bcb0991SDimitry Andric // addressing-modes in ILP32 mode. 2808bcb0991SDimitry Andric return useAA() || isTargetILP32(); 2818bcb0991SDimitry Andric } 2828bcb0991SDimitry Andric useSmallAddressing()2830b57cec5SDimitry Andric bool useSmallAddressing() const { 2840b57cec5SDimitry Andric switch (TLInfo.getTargetMachine().getCodeModel()) { 2850b57cec5SDimitry Andric case CodeModel::Kernel: 2860b57cec5SDimitry Andric // Kernel is currently allowed only for Fuchsia targets, 2870b57cec5SDimitry Andric // where it is the same as Small for almost all purposes. 2880b57cec5SDimitry Andric case CodeModel::Small: 2890b57cec5SDimitry Andric return true; 2900b57cec5SDimitry Andric default: 2910b57cec5SDimitry Andric return false; 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric /// ParseSubtargetFeatures - Parses features string setting specified 2960b57cec5SDimitry Andric /// subtarget options. Definition of function is auto generated by tblgen. 297e8d8bef9SDimitry Andric void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// ClassifyGlobalReference - Find the target operand flags that describe 3000b57cec5SDimitry Andric /// how a global value should be referenced for the current subtarget. 3018bcb0991SDimitry Andric unsigned ClassifyGlobalReference(const GlobalValue *GV, 3020b57cec5SDimitry Andric const TargetMachine &TM) const; 3030b57cec5SDimitry Andric 3048bcb0991SDimitry Andric unsigned classifyGlobalFunctionReference(const GlobalValue *GV, 3050b57cec5SDimitry Andric const TargetMachine &TM) const; 3060b57cec5SDimitry Andric 307bdd1243dSDimitry Andric /// This function is design to compatible with the function def in other 308bdd1243dSDimitry Andric /// targets and escape build error about the virtual function def in base 309bdd1243dSDimitry Andric /// class TargetSubtargetInfo. Updeate me if AArch64 target need to use it. 310bdd1243dSDimitry Andric unsigned char classifyGlobalFunctionReference(const GlobalValue * GV)311bdd1243dSDimitry Andric classifyGlobalFunctionReference(const GlobalValue *GV) const override { 312bdd1243dSDimitry Andric return 0; 313bdd1243dSDimitry Andric } 314bdd1243dSDimitry Andric 3150b57cec5SDimitry Andric void overrideSchedPolicy(MachineSchedPolicy &Policy, 3160b57cec5SDimitry Andric unsigned NumRegionInstrs) const override; 3170fca6ea1SDimitry Andric void adjustSchedDependency(SUnit *Def, int DefOpIdx, SUnit *Use, int UseOpIdx, 3180fca6ea1SDimitry Andric SDep &Dep, 3190fca6ea1SDimitry Andric const TargetSchedModel *SchedModel) const override; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric bool enableEarlyIfConversion() const override; 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override; 3240b57cec5SDimitry Andric isCallingConvWin64(CallingConv::ID CC,bool IsVarArg)3250fca6ea1SDimitry Andric bool isCallingConvWin64(CallingConv::ID CC, bool IsVarArg) const { 3260b57cec5SDimitry Andric switch (CC) { 3270b57cec5SDimitry Andric case CallingConv::C: 3280b57cec5SDimitry Andric case CallingConv::Fast: 3290b57cec5SDimitry Andric case CallingConv::Swift: 3300fca6ea1SDimitry Andric case CallingConv::SwiftTail: 3310b57cec5SDimitry Andric return isTargetWindows(); 3320fca6ea1SDimitry Andric case CallingConv::PreserveNone: 3330fca6ea1SDimitry Andric return IsVarArg && isTargetWindows(); 3340b57cec5SDimitry Andric case CallingConv::Win64: 3350b57cec5SDimitry Andric return true; 3360b57cec5SDimitry Andric default: 3370b57cec5SDimitry Andric return false; 3380b57cec5SDimitry Andric } 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 341349cc55cSDimitry Andric /// Return whether FrameLowering should always set the "extended frame 342349cc55cSDimitry Andric /// present" bit in FP, or set it based on a symbol in the runtime. swiftAsyncContextIsDynamicallySet()343349cc55cSDimitry Andric bool swiftAsyncContextIsDynamicallySet() const { 344349cc55cSDimitry Andric // Older OS versions (particularly system unwinders) are confused by the 345349cc55cSDimitry Andric // Swift extended frame, so when building code that might be run on them we 346349cc55cSDimitry Andric // must dynamically query the concurrency library to determine whether 347349cc55cSDimitry Andric // extended frames should be flagged as present. 348349cc55cSDimitry Andric const Triple &TT = getTargetTriple(); 349349cc55cSDimitry Andric 3500eae32dcSDimitry Andric unsigned Major = TT.getOSVersion().getMajor(); 351349cc55cSDimitry Andric switch(TT.getOS()) { 352349cc55cSDimitry Andric default: 353349cc55cSDimitry Andric return false; 354349cc55cSDimitry Andric case Triple::IOS: 355349cc55cSDimitry Andric case Triple::TvOS: 356349cc55cSDimitry Andric return Major < 15; 357349cc55cSDimitry Andric case Triple::WatchOS: 358349cc55cSDimitry Andric return Major < 8; 359349cc55cSDimitry Andric case Triple::MacOSX: 360349cc55cSDimitry Andric case Triple::Darwin: 361349cc55cSDimitry Andric return Major < 12; 362349cc55cSDimitry Andric } 363349cc55cSDimitry Andric } 364349cc55cSDimitry Andric 3650b57cec5SDimitry Andric void mirFileLoaded(MachineFunction &MF) const override; 3665ffd83dbSDimitry Andric 3675ffd83dbSDimitry Andric // Return the known range for the bit length of SVE data registers. A value 3685ffd83dbSDimitry Andric // of 0 means nothing is known about that particular limit beyong what's 3695ffd83dbSDimitry Andric // implied by the architecture. getMaxSVEVectorSizeInBits()370fe6060f1SDimitry Andric unsigned getMaxSVEVectorSizeInBits() const { 3710fca6ea1SDimitry Andric assert(isSVEorStreamingSVEAvailable() && 372bdd1243dSDimitry Andric "Tried to get SVE vector length without SVE support!"); 373fe6060f1SDimitry Andric return MaxSVEVectorSizeInBits; 374fe6060f1SDimitry Andric } 375fe6060f1SDimitry Andric getMinSVEVectorSizeInBits()376fe6060f1SDimitry Andric unsigned getMinSVEVectorSizeInBits() const { 3770fca6ea1SDimitry Andric assert(isSVEorStreamingSVEAvailable() && 378bdd1243dSDimitry Andric "Tried to get SVE vector length without SVE support!"); 379fe6060f1SDimitry Andric return MinSVEVectorSizeInBits; 380fe6060f1SDimitry Andric } 381fe6060f1SDimitry Andric useSVEForFixedLengthVectors()38204eeddc0SDimitry Andric bool useSVEForFixedLengthVectors() const { 3830fca6ea1SDimitry Andric if (!isSVEorStreamingSVEAvailable()) 3840fca6ea1SDimitry Andric return false; 385bdd1243dSDimitry Andric 38604eeddc0SDimitry Andric // Prefer NEON unless larger SVE registers are available. 3870fca6ea1SDimitry Andric return !isNeonAvailable() || getMinSVEVectorSizeInBits() >= 256; 38804eeddc0SDimitry Andric } 389349cc55cSDimitry Andric useSVEForFixedLengthVectors(EVT VT)39006c3fb27SDimitry Andric bool useSVEForFixedLengthVectors(EVT VT) const { 39106c3fb27SDimitry Andric if (!useSVEForFixedLengthVectors() || !VT.isFixedLengthVector()) 39206c3fb27SDimitry Andric return false; 39306c3fb27SDimitry Andric return VT.getFixedSizeInBits() > AArch64::SVEBitsPerBlock || 39406c3fb27SDimitry Andric !isNeonAvailable(); 39506c3fb27SDimitry Andric } 396bdd1243dSDimitry Andric getVScaleForTuning()397349cc55cSDimitry Andric unsigned getVScaleForTuning() const { return VScaleForTuning; } 398bdd1243dSDimitry Andric getSVETailFoldingDefaultOpts()39906c3fb27SDimitry Andric TailFoldingOpts getSVETailFoldingDefaultOpts() const { 40006c3fb27SDimitry Andric return DefaultSVETFOpts; 40106c3fb27SDimitry Andric } 40206c3fb27SDimitry Andric getChkStkName()403bdd1243dSDimitry Andric const char* getChkStkName() const { 404bdd1243dSDimitry Andric if (isWindowsArm64EC()) 4057a6dacacSDimitry Andric return "#__chkstk_arm64ec"; 406bdd1243dSDimitry Andric return "__chkstk"; 407bdd1243dSDimitry Andric } 408bdd1243dSDimitry Andric getSecurityCheckCookieName()409bdd1243dSDimitry Andric const char* getSecurityCheckCookieName() const { 410bdd1243dSDimitry Andric if (isWindowsArm64EC()) 4117a6dacacSDimitry Andric return "#__security_check_cookie_arm64ec"; 412bdd1243dSDimitry Andric return "__security_check_cookie"; 413bdd1243dSDimitry Andric } 4145f757f3fSDimitry Andric 4155f757f3fSDimitry Andric /// Choose a method of checking LR before performing a tail call. 416*36b606aeSDimitry Andric AArch64PAuth::AuthCheckMethod 417*36b606aeSDimitry Andric getAuthenticatedLRCheckMethod(const MachineFunction &MF) const; 4185f757f3fSDimitry Andric 4190fca6ea1SDimitry Andric /// Compute the integer discriminator for a given BlockAddress constant, if 4200fca6ea1SDimitry Andric /// blockaddress signing is enabled, or std::nullopt otherwise. 4210fca6ea1SDimitry Andric /// Blockaddress signing is controlled by the function attribute 4220fca6ea1SDimitry Andric /// "ptrauth-indirect-gotos" on the parent function. 4230fca6ea1SDimitry Andric /// Note that this assumes the discriminator is independent of the indirect 4240fca6ea1SDimitry Andric /// goto branch site itself, i.e., it's the same for all BlockAddresses in 4250fca6ea1SDimitry Andric /// a function. 4260fca6ea1SDimitry Andric std::optional<uint16_t> 4270fca6ea1SDimitry Andric getPtrAuthBlockAddressDiscriminatorIfEnabled(const Function &ParentFn) const; 4280fca6ea1SDimitry Andric getAddressCheckPSV()4295f757f3fSDimitry Andric const PseudoSourceValue *getAddressCheckPSV() const { 4305f757f3fSDimitry Andric return AddressCheckPSV.get(); 4315f757f3fSDimitry Andric } 4325f757f3fSDimitry Andric 4335f757f3fSDimitry Andric private: 4345f757f3fSDimitry Andric /// Pseudo value representing memory load performed to check an address. 4355f757f3fSDimitry Andric /// 4365f757f3fSDimitry Andric /// This load operation is solely used for its side-effects: if the address 4375f757f3fSDimitry Andric /// is not mapped (or not readable), it triggers CPU exception, otherwise 4385f757f3fSDimitry Andric /// execution proceeds and the value is not used. 4395f757f3fSDimitry Andric class AddressCheckPseudoSourceValue : public PseudoSourceValue { 4405f757f3fSDimitry Andric public: AddressCheckPseudoSourceValue(const TargetMachine & TM)4415f757f3fSDimitry Andric AddressCheckPseudoSourceValue(const TargetMachine &TM) 4425f757f3fSDimitry Andric : PseudoSourceValue(TargetCustom, TM) {} 4435f757f3fSDimitry Andric isConstant(const MachineFrameInfo *)4445f757f3fSDimitry Andric bool isConstant(const MachineFrameInfo *) const override { return false; } isAliased(const MachineFrameInfo *)4455f757f3fSDimitry Andric bool isAliased(const MachineFrameInfo *) const override { return true; } mayAlias(const MachineFrameInfo *)4465f757f3fSDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { return true; } printCustom(raw_ostream & OS)4475f757f3fSDimitry Andric void printCustom(raw_ostream &OS) const override { OS << "AddressCheck"; } 4485f757f3fSDimitry Andric }; 4495f757f3fSDimitry Andric 4505f757f3fSDimitry Andric std::unique_ptr<AddressCheckPseudoSourceValue> AddressCheckPSV; 4510b57cec5SDimitry Andric }; 4520b57cec5SDimitry Andric } // End llvm namespace 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric #endif 455