1 //===-- AArch64Subtarget.cpp - AArch64 Subtarget Information ----*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the AArch64 specific subclass of TargetSubtarget.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "AArch64Subtarget.h"
15 
16 #include "AArch64.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64PBQPRegAlloc.h"
19 #include "AArch64TargetMachine.h"
20 
21 #include "AArch64CallLowering.h"
22 #include "AArch64LegalizerInfo.h"
23 #include "AArch64RegisterBankInfo.h"
24 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
25 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
26 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
27 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
28 #include "llvm/CodeGen/MachineScheduler.h"
29 #include "llvm/IR/GlobalValue.h"
30 #include "llvm/Support/TargetRegistry.h"
31 
32 using namespace llvm;
33 
34 #define DEBUG_TYPE "aarch64-subtarget"
35 
36 #define GET_SUBTARGETINFO_CTOR
37 #define GET_SUBTARGETINFO_TARGET_DESC
38 #include "AArch64GenSubtargetInfo.inc"
39 
40 static cl::opt<bool>
41 EnableEarlyIfConvert("aarch64-early-ifcvt", cl::desc("Enable the early if "
42                      "converter pass"), cl::init(true), cl::Hidden);
43 
44 // If OS supports TBI, use this flag to enable it.
45 static cl::opt<bool>
46 UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of "
47                          "an address is ignored"), cl::init(false), cl::Hidden);
48 
49 static cl::opt<bool>
50     UseNonLazyBind("aarch64-enable-nonlazybind",
51                    cl::desc("Call nonlazybind functions via direct GOT load"),
52                    cl::init(false), cl::Hidden);
53 
54 AArch64Subtarget &
55 AArch64Subtarget::initializeSubtargetDependencies(StringRef FS,
56                                                   StringRef CPUString) {
57   // Determine default and user-specified characteristics
58 
59   if (CPUString.empty())
60     CPUString = "generic";
61 
62   ParseSubtargetFeatures(CPUString, FS);
63   initializeProperties();
64 
65   return *this;
66 }
67 
68 void AArch64Subtarget::initializeProperties() {
69   // Initialize CPU specific properties. We should add a tablegen feature for
70   // this in the future so we can specify it together with the subtarget
71   // features.
72   switch (ARMProcFamily) {
73   case Cyclone:
74     CacheLineSize = 64;
75     PrefetchDistance = 280;
76     MinPrefetchStride = 2048;
77     MaxPrefetchIterationsAhead = 3;
78     break;
79   case CortexA57:
80     MaxInterleaveFactor = 4;
81     PrefFunctionAlignment = 4;
82     break;
83   case ExynosM1:
84     MaxInterleaveFactor = 4;
85     MaxJumpTableSize = 8;
86     PrefFunctionAlignment = 4;
87     PrefLoopAlignment = 3;
88     break;
89   case Falkor:
90     MaxInterleaveFactor = 4;
91     // FIXME: remove this to enable 64-bit SLP if performance looks good.
92     MinVectorRegisterBitWidth = 128;
93     CacheLineSize = 128;
94     PrefetchDistance = 820;
95     MinPrefetchStride = 2048;
96     MaxPrefetchIterationsAhead = 8;
97     break;
98   case Saphira:
99     MaxInterleaveFactor = 4;
100     // FIXME: remove this to enable 64-bit SLP if performance looks good.
101     MinVectorRegisterBitWidth = 128;
102     break;
103   case Kryo:
104     MaxInterleaveFactor = 4;
105     VectorInsertExtractBaseCost = 2;
106     CacheLineSize = 128;
107     PrefetchDistance = 740;
108     MinPrefetchStride = 1024;
109     MaxPrefetchIterationsAhead = 11;
110     // FIXME: remove this to enable 64-bit SLP if performance looks good.
111     MinVectorRegisterBitWidth = 128;
112     break;
113   case ThunderX2T99:
114     CacheLineSize = 64;
115     PrefFunctionAlignment = 3;
116     PrefLoopAlignment = 2;
117     MaxInterleaveFactor = 4;
118     PrefetchDistance = 128;
119     MinPrefetchStride = 1024;
120     MaxPrefetchIterationsAhead = 4;
121     // FIXME: remove this to enable 64-bit SLP if performance looks good.
122     MinVectorRegisterBitWidth = 128;
123     break;
124   case ThunderX:
125   case ThunderXT88:
126   case ThunderXT81:
127   case ThunderXT83:
128     CacheLineSize = 128;
129     PrefFunctionAlignment = 3;
130     PrefLoopAlignment = 2;
131     // FIXME: remove this to enable 64-bit SLP if performance looks good.
132     MinVectorRegisterBitWidth = 128;
133     break;
134   case CortexA35: break;
135   case CortexA53:
136     PrefFunctionAlignment = 3;
137     break;
138   case CortexA55: break;
139   case CortexA72:
140   case CortexA73:
141   case CortexA75:
142     PrefFunctionAlignment = 4;
143     break;
144   case Others: break;
145   }
146 }
147 
148 AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
149                                    const std::string &FS,
150                                    const TargetMachine &TM, bool LittleEndian)
151     : AArch64GenSubtargetInfo(TT, CPU, FS),
152       ReserveX18(TT.isOSDarwin() || TT.isOSWindows()), IsLittle(LittleEndian),
153       TargetTriple(TT), FrameLowering(),
154       InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
155       TLInfo(TM, *this) {
156   CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
157   Legalizer.reset(new AArch64LegalizerInfo());
158 
159   auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo());
160 
161   // FIXME: At this point, we can't rely on Subtarget having RBI.
162   // It's awkward to mix passing RBI and the Subtarget; should we pass
163   // TII/TRI as well?
164   InstSelector.reset(createAArch64InstructionSelector(
165       *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
166 
167   RegBankInfo.reset(RBI);
168 }
169 
170 const CallLowering *AArch64Subtarget::getCallLowering() const {
171   return CallLoweringInfo.get();
172 }
173 
174 const InstructionSelector *AArch64Subtarget::getInstructionSelector() const {
175   return InstSelector.get();
176 }
177 
178 const LegalizerInfo *AArch64Subtarget::getLegalizerInfo() const {
179   return Legalizer.get();
180 }
181 
182 const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const {
183   return RegBankInfo.get();
184 }
185 
186 /// Find the target operand flags that describe how a global value should be
187 /// referenced for the current subtarget.
188 unsigned char
189 AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
190                                           const TargetMachine &TM) const {
191   // MachO large model always goes via a GOT, simply to get a single 8-byte
192   // absolute relocation on all global addresses.
193   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO())
194     return AArch64II::MO_GOT;
195 
196   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
197     return AArch64II::MO_GOT;
198 
199   // The small code model's direct accesses use ADRP, which cannot
200   // necessarily produce the value 0 (if the code is above 4GB).
201   if (useSmallAddressing() && GV->hasExternalWeakLinkage())
202     return AArch64II::MO_GOT;
203 
204   return AArch64II::MO_NO_FLAG;
205 }
206 
207 unsigned char AArch64Subtarget::classifyGlobalFunctionReference(
208     const GlobalValue *GV, const TargetMachine &TM) const {
209   // MachO large model always goes via a GOT, because we don't have the
210   // relocations available to do anything else..
211   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() &&
212       !GV->hasInternalLinkage())
213     return AArch64II::MO_GOT;
214 
215   // NonLazyBind goes via GOT unless we know it's available locally.
216   auto *F = dyn_cast<Function>(GV);
217   if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) &&
218       !TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
219     return AArch64II::MO_GOT;
220 
221   return AArch64II::MO_NO_FLAG;
222 }
223 
224 /// This function returns the name of a function which has an interface
225 /// like the non-standard bzero function, if such a function exists on
226 /// the current subtarget and it is considered prefereable over
227 /// memset with zero passed as the second argument. Otherwise it
228 /// returns null.
229 const char *AArch64Subtarget::getBZeroEntry() const {
230   // Prefer bzero on Darwin only.
231   if(isTargetDarwin())
232     return "bzero";
233 
234   return nullptr;
235 }
236 
237 void AArch64Subtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
238                                            unsigned NumRegionInstrs) const {
239   // LNT run (at least on Cyclone) showed reasonably significant gains for
240   // bi-directional scheduling. 253.perlbmk.
241   Policy.OnlyTopDown = false;
242   Policy.OnlyBottomUp = false;
243   // Enabling or Disabling the latency heuristic is a close call: It seems to
244   // help nearly no benchmark on out-of-order architectures, on the other hand
245   // it regresses register pressure on a few benchmarking.
246   Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic;
247 }
248 
249 bool AArch64Subtarget::enableEarlyIfConversion() const {
250   return EnableEarlyIfConvert;
251 }
252 
253 bool AArch64Subtarget::supportsAddressTopByteIgnored() const {
254   if (!UseAddressTopByteIgnored)
255     return false;
256 
257   if (TargetTriple.isiOS()) {
258     unsigned Major, Minor, Micro;
259     TargetTriple.getiOSVersion(Major, Minor, Micro);
260     return Major >= 8;
261   }
262 
263   return false;
264 }
265 
266 std::unique_ptr<PBQPRAConstraint>
267 AArch64Subtarget::getCustomPBQPConstraints() const {
268   return balanceFPOps() ? llvm::make_unique<A57ChainingConstraint>() : nullptr;
269 }
270