xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64Subtarget.h (revision 36b606ae6aa4b24061096ba18582e0a08ccd5dba)
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