1 //===-- AArch64Subtarget.cpp - AArch64 Subtarget Information ----*- 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 implements the AArch64 specific subclass of TargetSubtarget.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "AArch64Subtarget.h"
14 
15 #include "AArch64.h"
16 #include "AArch64InstrInfo.h"
17 #include "AArch64PBQPRegAlloc.h"
18 #include "AArch64TargetMachine.h"
19 #include "GISel/AArch64CallLowering.h"
20 #include "GISel/AArch64LegalizerInfo.h"
21 #include "GISel/AArch64RegisterBankInfo.h"
22 #include "MCTargetDesc/AArch64AddressingModes.h"
23 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
24 #include "llvm/CodeGen/MachineScheduler.h"
25 #include "llvm/IR/GlobalValue.h"
26 #include "llvm/Support/TargetParser.h"
27 
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "aarch64-subtarget"
31 
32 #define GET_SUBTARGETINFO_CTOR
33 #define GET_SUBTARGETINFO_TARGET_DESC
34 #include "AArch64GenSubtargetInfo.inc"
35 
36 static cl::opt<bool>
37 EnableEarlyIfConvert("aarch64-early-ifcvt", cl::desc("Enable the early if "
38                      "converter pass"), cl::init(true), cl::Hidden);
39 
40 // If OS supports TBI, use this flag to enable it.
41 static cl::opt<bool>
42 UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of "
43                          "an address is ignored"), cl::init(false), cl::Hidden);
44 
45 static cl::opt<bool>
46     UseNonLazyBind("aarch64-enable-nonlazybind",
47                    cl::desc("Call nonlazybind functions via direct GOT load"),
48                    cl::init(false), cl::Hidden);
49 
50 static cl::opt<unsigned> SVEVectorBitsMax(
51     "aarch64-sve-vector-bits-max",
52     cl::desc("Assume SVE vector registers are at most this big, "
53              "with zero meaning no maximum size is assumed."),
54     cl::init(0), cl::Hidden);
55 
56 static cl::opt<unsigned> SVEVectorBitsMin(
57     "aarch64-sve-vector-bits-min",
58     cl::desc("Assume SVE vector registers are at least this big, "
59              "with zero meaning no minimum size is assumed."),
60     cl::init(0), cl::Hidden);
61 
62 static cl::opt<bool> UseAA("aarch64-use-aa", cl::init(true),
63                            cl::desc("Enable the use of AA during codegen."));
64 
65 AArch64Subtarget &
66 AArch64Subtarget::initializeSubtargetDependencies(StringRef FS,
67                                                   StringRef CPUString) {
68   // Determine default and user-specified characteristics
69 
70   if (CPUString.empty())
71     CPUString = "generic";
72 
73   ParseSubtargetFeatures(CPUString, /*TuneCPU*/ CPUString, FS);
74   initializeProperties();
75 
76   return *this;
77 }
78 
79 void AArch64Subtarget::initializeProperties() {
80   // Initialize CPU specific properties. We should add a tablegen feature for
81   // this in the future so we can specify it together with the subtarget
82   // features.
83   switch (ARMProcFamily) {
84   case Others:
85     break;
86   case Carmel:
87     CacheLineSize = 64;
88     break;
89   case CortexA35:
90     break;
91   case CortexA53:
92     PrefFunctionLogAlignment = 3;
93     break;
94   case CortexA55:
95     break;
96   case CortexA57:
97     MaxInterleaveFactor = 4;
98     PrefFunctionLogAlignment = 4;
99     break;
100   case CortexA65:
101     PrefFunctionLogAlignment = 3;
102     break;
103   case CortexA72:
104   case CortexA73:
105   case CortexA75:
106   case CortexA76:
107   case CortexA77:
108   case CortexA78:
109   case CortexA78C:
110   case CortexR82:
111   case CortexX1:
112     PrefFunctionLogAlignment = 4;
113     break;
114   case A64FX:
115     CacheLineSize = 256;
116     PrefFunctionLogAlignment = 3;
117     PrefLoopLogAlignment = 2;
118     MaxInterleaveFactor = 4;
119     PrefetchDistance = 128;
120     MinPrefetchStride = 1024;
121     MaxPrefetchIterationsAhead = 4;
122     break;
123   case AppleA7:
124   case AppleA10:
125   case AppleA11:
126   case AppleA12:
127   case AppleA13:
128   case AppleA14:
129     CacheLineSize = 64;
130     PrefetchDistance = 280;
131     MinPrefetchStride = 2048;
132     MaxPrefetchIterationsAhead = 3;
133     break;
134   case ExynosM3:
135     MaxInterleaveFactor = 4;
136     MaxJumpTableSize = 20;
137     PrefFunctionLogAlignment = 5;
138     PrefLoopLogAlignment = 4;
139     break;
140   case Falkor:
141     MaxInterleaveFactor = 4;
142     // FIXME: remove this to enable 64-bit SLP if performance looks good.
143     MinVectorRegisterBitWidth = 128;
144     CacheLineSize = 128;
145     PrefetchDistance = 820;
146     MinPrefetchStride = 2048;
147     MaxPrefetchIterationsAhead = 8;
148     break;
149   case Kryo:
150     MaxInterleaveFactor = 4;
151     VectorInsertExtractBaseCost = 2;
152     CacheLineSize = 128;
153     PrefetchDistance = 740;
154     MinPrefetchStride = 1024;
155     MaxPrefetchIterationsAhead = 11;
156     // FIXME: remove this to enable 64-bit SLP if performance looks good.
157     MinVectorRegisterBitWidth = 128;
158     break;
159   case NeoverseE1:
160     PrefFunctionLogAlignment = 3;
161     break;
162   case NeoverseN1:
163   case NeoverseN2:
164   case NeoverseV1:
165     PrefFunctionLogAlignment = 4;
166     break;
167   case Saphira:
168     MaxInterleaveFactor = 4;
169     // FIXME: remove this to enable 64-bit SLP if performance looks good.
170     MinVectorRegisterBitWidth = 128;
171     break;
172   case ThunderX2T99:
173     CacheLineSize = 64;
174     PrefFunctionLogAlignment = 3;
175     PrefLoopLogAlignment = 2;
176     MaxInterleaveFactor = 4;
177     PrefetchDistance = 128;
178     MinPrefetchStride = 1024;
179     MaxPrefetchIterationsAhead = 4;
180     // FIXME: remove this to enable 64-bit SLP if performance looks good.
181     MinVectorRegisterBitWidth = 128;
182     break;
183   case ThunderX:
184   case ThunderXT88:
185   case ThunderXT81:
186   case ThunderXT83:
187     CacheLineSize = 128;
188     PrefFunctionLogAlignment = 3;
189     PrefLoopLogAlignment = 2;
190     // FIXME: remove this to enable 64-bit SLP if performance looks good.
191     MinVectorRegisterBitWidth = 128;
192     break;
193   case TSV110:
194     CacheLineSize = 64;
195     PrefFunctionLogAlignment = 4;
196     PrefLoopLogAlignment = 2;
197     break;
198   case ThunderX3T110:
199     CacheLineSize = 64;
200     PrefFunctionLogAlignment = 4;
201     PrefLoopLogAlignment = 2;
202     MaxInterleaveFactor = 4;
203     PrefetchDistance = 128;
204     MinPrefetchStride = 1024;
205     MaxPrefetchIterationsAhead = 4;
206     // FIXME: remove this to enable 64-bit SLP if performance looks good.
207     MinVectorRegisterBitWidth = 128;
208     break;
209   }
210 }
211 
212 AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
213                                    const std::string &FS,
214                                    const TargetMachine &TM, bool LittleEndian)
215     : AArch64GenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
216       ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()),
217       CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()),
218       IsLittle(LittleEndian),
219       TargetTriple(TT), FrameLowering(),
220       InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
221       TLInfo(TM, *this) {
222   if (AArch64::isX18ReservedByDefault(TT))
223     ReserveXRegister.set(18);
224 
225   CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
226   InlineAsmLoweringInfo.reset(new InlineAsmLowering(getTargetLowering()));
227   Legalizer.reset(new AArch64LegalizerInfo(*this));
228 
229   auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo());
230 
231   // FIXME: At this point, we can't rely on Subtarget having RBI.
232   // It's awkward to mix passing RBI and the Subtarget; should we pass
233   // TII/TRI as well?
234   InstSelector.reset(createAArch64InstructionSelector(
235       *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
236 
237   RegBankInfo.reset(RBI);
238 }
239 
240 const CallLowering *AArch64Subtarget::getCallLowering() const {
241   return CallLoweringInfo.get();
242 }
243 
244 const InlineAsmLowering *AArch64Subtarget::getInlineAsmLowering() const {
245   return InlineAsmLoweringInfo.get();
246 }
247 
248 InstructionSelector *AArch64Subtarget::getInstructionSelector() const {
249   return InstSelector.get();
250 }
251 
252 const LegalizerInfo *AArch64Subtarget::getLegalizerInfo() const {
253   return Legalizer.get();
254 }
255 
256 const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const {
257   return RegBankInfo.get();
258 }
259 
260 /// Find the target operand flags that describe how a global value should be
261 /// referenced for the current subtarget.
262 unsigned
263 AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
264                                           const TargetMachine &TM) const {
265   // MachO large model always goes via a GOT, simply to get a single 8-byte
266   // absolute relocation on all global addresses.
267   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO())
268     return AArch64II::MO_GOT;
269 
270   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) {
271     if (GV->hasDLLImportStorageClass())
272       return AArch64II::MO_GOT | AArch64II::MO_DLLIMPORT;
273     if (getTargetTriple().isOSWindows())
274       return AArch64II::MO_GOT | AArch64II::MO_COFFSTUB;
275     return AArch64II::MO_GOT;
276   }
277 
278   // The small code model's direct accesses use ADRP, which cannot
279   // necessarily produce the value 0 (if the code is above 4GB).
280   // Same for the tiny code model, where we have a pc relative LDR.
281   if ((useSmallAddressing() || TM.getCodeModel() == CodeModel::Tiny) &&
282       GV->hasExternalWeakLinkage())
283     return AArch64II::MO_GOT;
284 
285   // References to tagged globals are marked with MO_NC | MO_TAGGED to indicate
286   // that their nominal addresses are tagged and outside of the code model. In
287   // AArch64ExpandPseudo::expandMI we emit an additional instruction to set the
288   // tag if necessary based on MO_TAGGED.
289   if (AllowTaggedGlobals && !isa<FunctionType>(GV->getValueType()))
290     return AArch64II::MO_NC | AArch64II::MO_TAGGED;
291 
292   return AArch64II::MO_NO_FLAG;
293 }
294 
295 unsigned AArch64Subtarget::classifyGlobalFunctionReference(
296     const GlobalValue *GV, const TargetMachine &TM) const {
297   // MachO large model always goes via a GOT, because we don't have the
298   // relocations available to do anything else..
299   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() &&
300       !GV->hasInternalLinkage())
301     return AArch64II::MO_GOT;
302 
303   // NonLazyBind goes via GOT unless we know it's available locally.
304   auto *F = dyn_cast<Function>(GV);
305   if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) &&
306       !TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
307     return AArch64II::MO_GOT;
308 
309   // Use ClassifyGlobalReference for setting MO_DLLIMPORT/MO_COFFSTUB.
310   if (getTargetTriple().isOSWindows())
311     return ClassifyGlobalReference(GV, TM);
312 
313   return AArch64II::MO_NO_FLAG;
314 }
315 
316 void AArch64Subtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
317                                            unsigned NumRegionInstrs) const {
318   // LNT run (at least on Cyclone) showed reasonably significant gains for
319   // bi-directional scheduling. 253.perlbmk.
320   Policy.OnlyTopDown = false;
321   Policy.OnlyBottomUp = false;
322   // Enabling or Disabling the latency heuristic is a close call: It seems to
323   // help nearly no benchmark on out-of-order architectures, on the other hand
324   // it regresses register pressure on a few benchmarking.
325   Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic;
326 }
327 
328 bool AArch64Subtarget::enableEarlyIfConversion() const {
329   return EnableEarlyIfConvert;
330 }
331 
332 bool AArch64Subtarget::supportsAddressTopByteIgnored() const {
333   if (!UseAddressTopByteIgnored)
334     return false;
335 
336   if (TargetTriple.isiOS()) {
337     unsigned Major, Minor, Micro;
338     TargetTriple.getiOSVersion(Major, Minor, Micro);
339     return Major >= 8;
340   }
341 
342   return false;
343 }
344 
345 std::unique_ptr<PBQPRAConstraint>
346 AArch64Subtarget::getCustomPBQPConstraints() const {
347   return balanceFPOps() ? std::make_unique<A57ChainingConstraint>() : nullptr;
348 }
349 
350 void AArch64Subtarget::mirFileLoaded(MachineFunction &MF) const {
351   // We usually compute max call frame size after ISel. Do the computation now
352   // if the .mir file didn't specify it. Note that this will probably give you
353   // bogus values after PEI has eliminated the callframe setup/destroy pseudo
354   // instructions, specify explicitly if you need it to be correct.
355   MachineFrameInfo &MFI = MF.getFrameInfo();
356   if (!MFI.isMaxCallFrameSizeComputed())
357     MFI.computeMaxCallFrameSize(MF);
358 }
359 
360 unsigned AArch64Subtarget::getMaxSVEVectorSizeInBits() const {
361   assert(HasSVE && "Tried to get SVE vector length without SVE support!");
362   assert(SVEVectorBitsMax % 128 == 0 &&
363          "SVE requires vector length in multiples of 128!");
364   assert((SVEVectorBitsMax >= SVEVectorBitsMin || SVEVectorBitsMax == 0) &&
365          "Minimum SVE vector size should not be larger than its maximum!");
366   if (SVEVectorBitsMax == 0)
367     return 0;
368   return (std::max(SVEVectorBitsMin, SVEVectorBitsMax) / 128) * 128;
369 }
370 
371 unsigned AArch64Subtarget::getMinSVEVectorSizeInBits() const {
372   assert(HasSVE && "Tried to get SVE vector length without SVE support!");
373   assert(SVEVectorBitsMin % 128 == 0 &&
374          "SVE requires vector length in multiples of 128!");
375   assert((SVEVectorBitsMax >= SVEVectorBitsMin || SVEVectorBitsMax == 0) &&
376          "Minimum SVE vector size should not be larger than its maximum!");
377   if (SVEVectorBitsMax == 0)
378     return (SVEVectorBitsMin / 128) * 128;
379   return (std::min(SVEVectorBitsMin, SVEVectorBitsMax) / 128) * 128;
380 }
381 
382 bool AArch64Subtarget::useSVEForFixedLengthVectors() const {
383   // Prefer NEON unless larger SVE registers are available.
384   return hasSVE() && getMinSVEVectorSizeInBits() >= 256;
385 }
386 
387 bool AArch64Subtarget::useAA() const { return UseAA; }
388