1 //===--- AArch64Subtarget.h - Define Subtarget for the AArch64 -*- C++ -*--===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares the AArch64 specific subclass of TargetSubtarget.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H
14 #define LLVM_LIB_TARGET_AARCH64_AARCH64SUBTARGET_H
15 
16 #include "AArch64FrameLowering.h"
17 #include "AArch64ISelLowering.h"
18 #include "AArch64InstrInfo.h"
19 #include "AArch64RegisterInfo.h"
20 #include "AArch64SelectionDAGInfo.h"
21 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
22 #include "llvm/CodeGen/GlobalISel/InlineAsmLowering.h"
23 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
24 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
25 #include "llvm/CodeGen/RegisterBankInfo.h"
26 #include "llvm/CodeGen/TargetSubtargetInfo.h"
27 #include "llvm/IR/DataLayout.h"
28 #include <string>
29 
30 #define GET_SUBTARGETINFO_HEADER
31 #include "AArch64GenSubtargetInfo.inc"
32 
33 namespace llvm {
34 class GlobalValue;
35 class StringRef;
36 class Triple;
37 
38 class AArch64Subtarget final : public AArch64GenSubtargetInfo {
39 public:
40   enum ARMProcFamilyEnum : uint8_t {
41     Others,
42     A64FX,
43     Ampere1,
44     Ampere1A,
45     AppleA7,
46     AppleA10,
47     AppleA11,
48     AppleA12,
49     AppleA13,
50     AppleA14,
51     AppleA15,
52     AppleA16,
53     Carmel,
54     CortexA35,
55     CortexA53,
56     CortexA55,
57     CortexA510,
58     CortexA57,
59     CortexA65,
60     CortexA72,
61     CortexA73,
62     CortexA75,
63     CortexA76,
64     CortexA77,
65     CortexA78,
66     CortexA78C,
67     CortexA710,
68     CortexA715,
69     CortexR82,
70     CortexX1,
71     CortexX1C,
72     CortexX2,
73     CortexX3,
74     ExynosM3,
75     Falkor,
76     Kryo,
77     NeoverseE1,
78     NeoverseN1,
79     NeoverseN2,
80     Neoverse512TVB,
81     NeoverseV1,
82     NeoverseV2,
83     Saphira,
84     ThunderX2T99,
85     ThunderX,
86     ThunderXT81,
87     ThunderXT83,
88     ThunderXT88,
89     ThunderX3T110,
90     TSV110
91   };
92 
93 protected:
94   /// ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others.
95   ARMProcFamilyEnum ARMProcFamily = Others;
96 
97   // Enable 64-bit vectorization in SLP.
98   unsigned MinVectorRegisterBitWidth = 64;
99 
100 // Bool members corresponding to the SubtargetFeatures defined in tablegen
101 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
102   bool ATTRIBUTE = DEFAULT;
103 #include "AArch64GenSubtargetInfo.inc"
104 
105   uint8_t MaxInterleaveFactor = 2;
106   uint8_t VectorInsertExtractBaseCost = 3;
107   uint16_t CacheLineSize = 0;
108   uint16_t PrefetchDistance = 0;
109   uint16_t MinPrefetchStride = 1;
110   unsigned MaxPrefetchIterationsAhead = UINT_MAX;
111   unsigned PrefFunctionLogAlignment = 0;
112   unsigned PrefLoopLogAlignment = 0;
113   unsigned MaxBytesForLoopAlignment = 0;
114   unsigned MaxJumpTableSize = 0;
115 
116   // ReserveXRegister[i] - X#i is not available as a general purpose register.
117   BitVector ReserveXRegister;
118 
119   // ReserveXRegisterForRA[i] - X#i is not available for register allocator.
120   BitVector ReserveXRegisterForRA;
121 
122   // CustomCallUsedXRegister[i] - X#i call saved.
123   BitVector CustomCallSavedXRegs;
124 
125   bool IsLittle;
126 
127   bool StreamingSVEModeDisabled;
128   unsigned MinSVEVectorSizeInBits;
129   unsigned MaxSVEVectorSizeInBits;
130   unsigned VScaleForTuning = 2;
131 
132   /// TargetTriple - What processor and OS we're targeting.
133   Triple TargetTriple;
134 
135   AArch64FrameLowering FrameLowering;
136   AArch64InstrInfo InstrInfo;
137   AArch64SelectionDAGInfo TSInfo;
138   AArch64TargetLowering TLInfo;
139 
140   /// GlobalISel related APIs.
141   std::unique_ptr<CallLowering> CallLoweringInfo;
142   std::unique_ptr<InlineAsmLowering> InlineAsmLoweringInfo;
143   std::unique_ptr<InstructionSelector> InstSelector;
144   std::unique_ptr<LegalizerInfo> Legalizer;
145   std::unique_ptr<RegisterBankInfo> RegBankInfo;
146 
147 private:
148   /// initializeSubtargetDependencies - Initializes using CPUString and the
149   /// passed in feature string so that we can use initializer lists for
150   /// subtarget initialization.
151   AArch64Subtarget &initializeSubtargetDependencies(StringRef FS,
152                                                     StringRef CPUString,
153                                                     StringRef TuneCPUString);
154 
155   /// Initialize properties based on the selected processor family.
156   void initializeProperties();
157 
158 public:
159   /// This constructor initializes the data members to match that
160   /// of the specified triple.
161   AArch64Subtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
162                    StringRef FS, const TargetMachine &TM, bool LittleEndian,
163                    unsigned MinSVEVectorSizeInBitsOverride = 0,
164                    unsigned MaxSVEVectorSizeInBitsOverride = 0,
165                    bool StreamingSVEModeDisabled = true);
166 
167 // Getters for SubtargetFeatures defined in tablegen
168 #define GET_SUBTARGETINFO_MACRO(ATTRIBUTE, DEFAULT, GETTER)                    \
169   bool GETTER() const { return ATTRIBUTE; }
170 #include "AArch64GenSubtargetInfo.inc"
171 
getSelectionDAGInfo()172   const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override {
173     return &TSInfo;
174   }
getFrameLowering()175   const AArch64FrameLowering *getFrameLowering() const override {
176     return &FrameLowering;
177   }
getTargetLowering()178   const AArch64TargetLowering *getTargetLowering() const override {
179     return &TLInfo;
180   }
getInstrInfo()181   const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; }
getRegisterInfo()182   const AArch64RegisterInfo *getRegisterInfo() const override {
183     return &getInstrInfo()->getRegisterInfo();
184   }
185   const CallLowering *getCallLowering() const override;
186   const InlineAsmLowering *getInlineAsmLowering() const override;
187   InstructionSelector *getInstructionSelector() const override;
188   const LegalizerInfo *getLegalizerInfo() const override;
189   const RegisterBankInfo *getRegBankInfo() const override;
getTargetTriple()190   const Triple &getTargetTriple() const { return TargetTriple; }
enableMachineScheduler()191   bool enableMachineScheduler() const override { return true; }
enablePostRAScheduler()192   bool enablePostRAScheduler() const override { return usePostRAScheduler(); }
193 
194   /// Returns ARM processor family.
195   /// Avoid this function! CPU specifics should be kept local to this class
196   /// and preferably modeled with SubtargetFeatures or properties in
197   /// initializeProperties().
getProcFamily()198   ARMProcFamilyEnum getProcFamily() const {
199     return ARMProcFamily;
200   }
201 
isXRaySupported()202   bool isXRaySupported() const override { return true; }
203 
getMinVectorRegisterBitWidth()204   unsigned getMinVectorRegisterBitWidth() const {
205     // Don't assume any minimum vector size when PSTATE.SM may not be 0.
206     if (!isStreamingSVEModeDisabled())
207       return 0;
208     return MinVectorRegisterBitWidth;
209   }
210 
isXRegisterReserved(size_t i)211   bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; }
isXRegisterReservedForRA(size_t i)212   bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; }
getNumXRegisterReserved()213   unsigned getNumXRegisterReserved() const {
214     BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs());
215     AllReservedX |= ReserveXRegister;
216     AllReservedX |= ReserveXRegisterForRA;
217     return AllReservedX.count();
218   }
isXRegCustomCalleeSaved(size_t i)219   bool isXRegCustomCalleeSaved(size_t i) const {
220     return CustomCallSavedXRegs[i];
221   }
hasCustomCallingConv()222   bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); }
223 
224   /// Return true if the CPU supports any kind of instruction fusion.
hasFusion()225   bool hasFusion() const {
226     return hasArithmeticBccFusion() || hasArithmeticCbzFusion() ||
227            hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCCSelect() ||
228            hasFuseAdrpAdd() || hasFuseLiterals();
229   }
230 
getMaxInterleaveFactor()231   unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
232   unsigned getVectorInsertExtractBaseCost() const;
getCacheLineSize()233   unsigned getCacheLineSize() const override { return CacheLineSize; }
getPrefetchDistance()234   unsigned getPrefetchDistance() const override { return PrefetchDistance; }
getMinPrefetchStride(unsigned NumMemAccesses,unsigned NumStridedMemAccesses,unsigned NumPrefetches,bool HasCall)235   unsigned getMinPrefetchStride(unsigned NumMemAccesses,
236                                 unsigned NumStridedMemAccesses,
237                                 unsigned NumPrefetches,
238                                 bool HasCall) const override {
239     return MinPrefetchStride;
240   }
getMaxPrefetchIterationsAhead()241   unsigned getMaxPrefetchIterationsAhead() const override {
242     return MaxPrefetchIterationsAhead;
243   }
getPrefFunctionLogAlignment()244   unsigned getPrefFunctionLogAlignment() const {
245     return PrefFunctionLogAlignment;
246   }
getPrefLoopLogAlignment()247   unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
248 
getMaxBytesForLoopAlignment()249   unsigned getMaxBytesForLoopAlignment() const {
250     return MaxBytesForLoopAlignment;
251   }
252 
getMaximumJumpTableSize()253   unsigned getMaximumJumpTableSize() const { return MaxJumpTableSize; }
254 
255   /// CPU has TBI (top byte of addresses is ignored during HW address
256   /// translation) and OS enables it.
257   bool supportsAddressTopByteIgnored() const;
258 
isLittleEndian()259   bool isLittleEndian() const { return IsLittle; }
260 
isTargetDarwin()261   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
isTargetIOS()262   bool isTargetIOS() const { return TargetTriple.isiOS(); }
isTargetLinux()263   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
isTargetOpenBSD()264   bool isTargetOpenBSD() const { return TargetTriple.isOSOpenBSD(); }
isTargetWindows()265   bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
isTargetAndroid()266   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
isTargetFuchsia()267   bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
isWindowsArm64EC()268   bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); }
269 
isTargetCOFF()270   bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
isTargetELF()271   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
isTargetMachO()272   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
273 
isTargetILP32()274   bool isTargetILP32() const {
275     return TargetTriple.isArch32Bit() ||
276            TargetTriple.getEnvironment() == Triple::GNUILP32;
277   }
278 
279   bool useAA() const override;
280 
addrSinkUsingGEPs()281   bool addrSinkUsingGEPs() const override {
282     // Keeping GEPs inbounds is important for exploiting AArch64
283     // addressing-modes in ILP32 mode.
284     return useAA() || isTargetILP32();
285   }
286 
useSmallAddressing()287   bool useSmallAddressing() const {
288     switch (TLInfo.getTargetMachine().getCodeModel()) {
289       case CodeModel::Kernel:
290         // Kernel is currently allowed only for Fuchsia targets,
291         // where it is the same as Small for almost all purposes.
292       case CodeModel::Small:
293         return true;
294       default:
295         return false;
296     }
297   }
298 
299   /// ParseSubtargetFeatures - Parses features string setting specified
300   /// subtarget options.  Definition of function is auto generated by tblgen.
301   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
302 
303   /// ClassifyGlobalReference - Find the target operand flags that describe
304   /// how a global value should be referenced for the current subtarget.
305   unsigned ClassifyGlobalReference(const GlobalValue *GV,
306                                    const TargetMachine &TM) const;
307 
308   unsigned classifyGlobalFunctionReference(const GlobalValue *GV,
309                                            const TargetMachine &TM) const;
310 
311   /// This function is design to compatible with the function def in other
312   /// targets and escape build error about the virtual function def in base
313   /// class TargetSubtargetInfo. Updeate me if AArch64 target need to use it.
314   unsigned char
classifyGlobalFunctionReference(const GlobalValue * GV)315   classifyGlobalFunctionReference(const GlobalValue *GV) const override {
316     return 0;
317   }
318 
319   void overrideSchedPolicy(MachineSchedPolicy &Policy,
320                            unsigned NumRegionInstrs) const override;
321 
322   bool enableEarlyIfConversion() const override;
323 
324   std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override;
325 
isCallingConvWin64(CallingConv::ID CC)326   bool isCallingConvWin64(CallingConv::ID CC) const {
327     switch (CC) {
328     case CallingConv::C:
329     case CallingConv::Fast:
330     case CallingConv::Swift:
331       return isTargetWindows();
332     case CallingConv::Win64:
333       return true;
334     default:
335       return false;
336     }
337   }
338 
339   /// Return whether FrameLowering should always set the "extended frame
340   /// present" bit in FP, or set it based on a symbol in the runtime.
swiftAsyncContextIsDynamicallySet()341   bool swiftAsyncContextIsDynamicallySet() const {
342     // Older OS versions (particularly system unwinders) are confused by the
343     // Swift extended frame, so when building code that might be run on them we
344     // must dynamically query the concurrency library to determine whether
345     // extended frames should be flagged as present.
346     const Triple &TT = getTargetTriple();
347 
348     unsigned Major = TT.getOSVersion().getMajor();
349     switch(TT.getOS()) {
350     default:
351       return false;
352     case Triple::IOS:
353     case Triple::TvOS:
354       return Major < 15;
355     case Triple::WatchOS:
356       return Major < 8;
357     case Triple::MacOSX:
358     case Triple::Darwin:
359       return Major < 12;
360     }
361   }
362 
363   void mirFileLoaded(MachineFunction &MF) const override;
364 
hasSVEorSME()365   bool hasSVEorSME() const { return hasSVE() || hasSME(); }
366 
367   // Return the known range for the bit length of SVE data registers. A value
368   // of 0 means nothing is known about that particular limit beyong what's
369   // implied by the architecture.
getMaxSVEVectorSizeInBits()370   unsigned getMaxSVEVectorSizeInBits() const {
371     assert(hasSVEorSME() &&
372            "Tried to get SVE vector length without SVE support!");
373     return MaxSVEVectorSizeInBits;
374   }
375 
getMinSVEVectorSizeInBits()376   unsigned getMinSVEVectorSizeInBits() const {
377     assert(hasSVEorSME() &&
378            "Tried to get SVE vector length without SVE support!");
379     return MinSVEVectorSizeInBits;
380   }
381 
useSVEForFixedLengthVectors()382   bool useSVEForFixedLengthVectors() const {
383     if (forceStreamingCompatibleSVE())
384       return true;
385 
386     // Prefer NEON unless larger SVE registers are available.
387     return hasSVE() && getMinSVEVectorSizeInBits() >= 256;
388   }
389 
390   bool forceStreamingCompatibleSVE() const;
391 
getVScaleForTuning()392   unsigned getVScaleForTuning() const { return VScaleForTuning; }
393 
getChkStkName()394   const char* getChkStkName() const {
395     if (isWindowsArm64EC())
396       return "__chkstk_arm64ec";
397     return "__chkstk";
398   }
399 
getSecurityCheckCookieName()400   const char* getSecurityCheckCookieName() const {
401     if (isWindowsArm64EC())
402       return "__security_check_cookie_arm64ec";
403     return "__security_check_cookie";
404   }
405 
isStreamingSVEModeDisabled()406   bool isStreamingSVEModeDisabled() const { return StreamingSVEModeDisabled; }
407 };
408 } // End llvm namespace
409 
410 #endif
411