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