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 
172   const AArch64SelectionDAGInfo *getSelectionDAGInfo() const override {
173     return &TSInfo;
174   }
175   const AArch64FrameLowering *getFrameLowering() const override {
176     return &FrameLowering;
177   }
178   const AArch64TargetLowering *getTargetLowering() const override {
179     return &TLInfo;
180   }
181   const AArch64InstrInfo *getInstrInfo() const override { return &InstrInfo; }
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;
190   const Triple &getTargetTriple() const { return TargetTriple; }
191   bool enableMachineScheduler() const override { return true; }
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().
198   ARMProcFamilyEnum getProcFamily() const {
199     return ARMProcFamily;
200   }
201 
202   bool isXRaySupported() const override { return true; }
203 
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 
211   bool isXRegisterReserved(size_t i) const { return ReserveXRegister[i]; }
212   bool isXRegisterReservedForRA(size_t i) const { return ReserveXRegisterForRA[i]; }
213   unsigned getNumXRegisterReserved() const {
214     BitVector AllReservedX(AArch64::GPR64commonRegClass.getNumRegs());
215     AllReservedX |= ReserveXRegister;
216     AllReservedX |= ReserveXRegisterForRA;
217     return AllReservedX.count();
218   }
219   bool isXRegCustomCalleeSaved(size_t i) const {
220     return CustomCallSavedXRegs[i];
221   }
222   bool hasCustomCallingConv() const { return CustomCallSavedXRegs.any(); }
223 
224   /// Return true if the CPU supports any kind of instruction fusion.
225   bool hasFusion() const {
226     return hasArithmeticBccFusion() || hasArithmeticCbzFusion() ||
227            hasFuseAES() || hasFuseArithmeticLogic() || hasFuseCCSelect() ||
228            hasFuseAdrpAdd() || hasFuseLiterals();
229   }
230 
231   unsigned getMaxInterleaveFactor() const { return MaxInterleaveFactor; }
232   unsigned getVectorInsertExtractBaseCost() const;
233   unsigned getCacheLineSize() const override { return CacheLineSize; }
234   unsigned getPrefetchDistance() const override { return PrefetchDistance; }
235   unsigned getMinPrefetchStride(unsigned NumMemAccesses,
236                                 unsigned NumStridedMemAccesses,
237                                 unsigned NumPrefetches,
238                                 bool HasCall) const override {
239     return MinPrefetchStride;
240   }
241   unsigned getMaxPrefetchIterationsAhead() const override {
242     return MaxPrefetchIterationsAhead;
243   }
244   unsigned getPrefFunctionLogAlignment() const {
245     return PrefFunctionLogAlignment;
246   }
247   unsigned getPrefLoopLogAlignment() const { return PrefLoopLogAlignment; }
248 
249   unsigned getMaxBytesForLoopAlignment() const {
250     return MaxBytesForLoopAlignment;
251   }
252 
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 
259   bool isLittleEndian() const { return IsLittle; }
260 
261   bool isTargetDarwin() const { return TargetTriple.isOSDarwin(); }
262   bool isTargetIOS() const { return TargetTriple.isiOS(); }
263   bool isTargetLinux() const { return TargetTriple.isOSLinux(); }
264   bool isTargetWindows() const { return TargetTriple.isOSWindows(); }
265   bool isTargetAndroid() const { return TargetTriple.isAndroid(); }
266   bool isTargetFuchsia() const { return TargetTriple.isOSFuchsia(); }
267   bool isWindowsArm64EC() const { return TargetTriple.isWindowsArm64EC(); }
268 
269   bool isTargetCOFF() const { return TargetTriple.isOSBinFormatCOFF(); }
270   bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
271   bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
272 
273   bool isTargetILP32() const {
274     return TargetTriple.isArch32Bit() ||
275            TargetTriple.getEnvironment() == Triple::GNUILP32;
276   }
277 
278   bool useAA() const override;
279 
280   bool addrSinkUsingGEPs() const override {
281     // Keeping GEPs inbounds is important for exploiting AArch64
282     // addressing-modes in ILP32 mode.
283     return useAA() || isTargetILP32();
284   }
285 
286   bool useSmallAddressing() const {
287     switch (TLInfo.getTargetMachine().getCodeModel()) {
288       case CodeModel::Kernel:
289         // Kernel is currently allowed only for Fuchsia targets,
290         // where it is the same as Small for almost all purposes.
291       case CodeModel::Small:
292         return true;
293       default:
294         return false;
295     }
296   }
297 
298   /// ParseSubtargetFeatures - Parses features string setting specified
299   /// subtarget options.  Definition of function is auto generated by tblgen.
300   void ParseSubtargetFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS);
301 
302   /// ClassifyGlobalReference - Find the target operand flags that describe
303   /// how a global value should be referenced for the current subtarget.
304   unsigned ClassifyGlobalReference(const GlobalValue *GV,
305                                    const TargetMachine &TM) const;
306 
307   unsigned classifyGlobalFunctionReference(const GlobalValue *GV,
308                                            const TargetMachine &TM) const;
309 
310   /// This function is design to compatible with the function def in other
311   /// targets and escape build error about the virtual function def in base
312   /// class TargetSubtargetInfo. Updeate me if AArch64 target need to use it.
313   unsigned char
314   classifyGlobalFunctionReference(const GlobalValue *GV) const override {
315     return 0;
316   }
317 
318   void overrideSchedPolicy(MachineSchedPolicy &Policy,
319                            unsigned NumRegionInstrs) const override;
320 
321   bool enableEarlyIfConversion() const override;
322 
323   std::unique_ptr<PBQPRAConstraint> getCustomPBQPConstraints() const override;
324 
325   bool isCallingConvWin64(CallingConv::ID CC) const {
326     switch (CC) {
327     case CallingConv::C:
328     case CallingConv::Fast:
329     case CallingConv::Swift:
330       return isTargetWindows();
331     case CallingConv::Win64:
332       return true;
333     default:
334       return false;
335     }
336   }
337 
338   /// Return whether FrameLowering should always set the "extended frame
339   /// present" bit in FP, or set it based on a symbol in the runtime.
340   bool swiftAsyncContextIsDynamicallySet() const {
341     // Older OS versions (particularly system unwinders) are confused by the
342     // Swift extended frame, so when building code that might be run on them we
343     // must dynamically query the concurrency library to determine whether
344     // extended frames should be flagged as present.
345     const Triple &TT = getTargetTriple();
346 
347     unsigned Major = TT.getOSVersion().getMajor();
348     switch(TT.getOS()) {
349     default:
350       return false;
351     case Triple::IOS:
352     case Triple::TvOS:
353       return Major < 15;
354     case Triple::WatchOS:
355       return Major < 8;
356     case Triple::MacOSX:
357     case Triple::Darwin:
358       return Major < 12;
359     }
360   }
361 
362   void mirFileLoaded(MachineFunction &MF) const override;
363 
364   bool hasSVEorSME() const { return hasSVE() || hasSME(); }
365 
366   // Return the known range for the bit length of SVE data registers. A value
367   // of 0 means nothing is known about that particular limit beyong what's
368   // implied by the architecture.
369   unsigned getMaxSVEVectorSizeInBits() const {
370     assert(hasSVEorSME() &&
371            "Tried to get SVE vector length without SVE support!");
372     return MaxSVEVectorSizeInBits;
373   }
374 
375   unsigned getMinSVEVectorSizeInBits() const {
376     assert(hasSVEorSME() &&
377            "Tried to get SVE vector length without SVE support!");
378     return MinSVEVectorSizeInBits;
379   }
380 
381   bool useSVEForFixedLengthVectors() const {
382     if (forceStreamingCompatibleSVE())
383       return true;
384 
385     // Prefer NEON unless larger SVE registers are available.
386     return hasSVE() && getMinSVEVectorSizeInBits() >= 256;
387   }
388 
389   bool forceStreamingCompatibleSVE() const;
390 
391   unsigned getVScaleForTuning() const { return VScaleForTuning; }
392 
393   const char* getChkStkName() const {
394     if (isWindowsArm64EC())
395       return "__chkstk_arm64ec";
396     return "__chkstk";
397   }
398 
399   const char* getSecurityCheckCookieName() const {
400     if (isWindowsArm64EC())
401       return "__security_check_cookie_arm64ec";
402     return "__security_check_cookie";
403   }
404 
405   bool isStreamingSVEModeDisabled() const { return StreamingSVEModeDisabled; }
406 };
407 } // End llvm namespace
408 
409 #endif
410