LLVM  10.0.0svn
AArch64Subtarget.cpp
Go to the documentation of this file.
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 "AArch64CallLowering.h"
17 #include "AArch64InstrInfo.h"
18 #include "AArch64LegalizerInfo.h"
19 #include "AArch64PBQPRegAlloc.h"
21 #include "AArch64TargetMachine.h"
25 #include "llvm/IR/GlobalValue.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 
51 AArch64Subtarget::initializeSubtargetDependencies(StringRef FS,
52  StringRef CPUString) {
53  // Determine default and user-specified characteristics
54 
55  if (CPUString.empty())
56  CPUString = "generic";
57 
58  ParseSubtargetFeatures(CPUString, FS);
59  initializeProperties();
60 
61  return *this;
62 }
63 
64 void AArch64Subtarget::initializeProperties() {
65  // Initialize CPU specific properties. We should add a tablegen feature for
66  // this in the future so we can specify it together with the subtarget
67  // features.
68  switch (ARMProcFamily) {
69  case Others:
70  break;
71  case CortexA35:
72  break;
73  case CortexA53:
75  break;
76  case CortexA55:
77  break;
78  case CortexA57:
81  break;
82  case CortexA65:
84  break;
85  case CortexA72:
86  case CortexA73:
87  case CortexA75:
88  case CortexA76:
90  break;
91  case Cyclone:
92  CacheLineSize = 64;
93  PrefetchDistance = 280;
94  MinPrefetchStride = 2048;
96  break;
97  case ExynosM1:
99  MaxJumpTableSize = 8;
102  break;
103  case ExynosM3:
105  MaxJumpTableSize = 20;
108  break;
109  case Falkor:
111  // FIXME: remove this to enable 64-bit SLP if performance looks good.
113  CacheLineSize = 128;
114  PrefetchDistance = 820;
115  MinPrefetchStride = 2048;
117  break;
118  case Kryo:
121  CacheLineSize = 128;
122  PrefetchDistance = 740;
123  MinPrefetchStride = 1024;
125  // FIXME: remove this to enable 64-bit SLP if performance looks good.
127  break;
128  case NeoverseE1:
130  break;
131  case NeoverseN1:
133  break;
134  case Saphira:
136  // FIXME: remove this to enable 64-bit SLP if performance looks good.
138  break;
139  case ThunderX2T99:
140  CacheLineSize = 64;
144  PrefetchDistance = 128;
145  MinPrefetchStride = 1024;
147  // FIXME: remove this to enable 64-bit SLP if performance looks good.
149  break;
150  case ThunderX:
151  case ThunderXT88:
152  case ThunderXT81:
153  case ThunderXT83:
154  CacheLineSize = 128;
157  // FIXME: remove this to enable 64-bit SLP if performance looks good.
159  break;
160  case TSV110:
161  CacheLineSize = 64;
164  break;
165  }
166 }
167 
168 AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
169  const std::string &FS,
170  const TargetMachine &TM, bool LittleEndian)
171  : AArch64GenSubtargetInfo(TT, CPU, FS),
172  ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()),
173  CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()),
174  IsLittle(LittleEndian),
176  InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
177  TLInfo(TM, *this) {
179  ReserveXRegister.set(18);
180 
182  Legalizer.reset(new AArch64LegalizerInfo(*this));
183 
184  auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo());
185 
186  // FIXME: At this point, we can't rely on Subtarget having RBI.
187  // It's awkward to mix passing RBI and the Subtarget; should we pass
188  // TII/TRI as well?
190  *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
191 
192  RegBankInfo.reset(RBI);
193 }
194 
196  return CallLoweringInfo.get();
197 }
198 
200  return InstSelector.get();
201 }
202 
204  return Legalizer.get();
205 }
206 
208  return RegBankInfo.get();
209 }
210 
211 /// Find the target operand flags that describe how a global value should be
212 /// referenced for the current subtarget.
213 unsigned
215  const TargetMachine &TM) const {
216  // MachO large model always goes via a GOT, simply to get a single 8-byte
217  // absolute relocation on all global addresses.
219  return AArch64II::MO_GOT;
220 
221  if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) {
222  if (GV->hasDLLImportStorageClass())
226  return AArch64II::MO_GOT;
227  }
228 
229  // The small code model's direct accesses use ADRP, which cannot
230  // necessarily produce the value 0 (if the code is above 4GB).
231  // Same for the tiny code model, where we have a pc relative LDR.
232  if ((useSmallAddressing() || TM.getCodeModel() == CodeModel::Tiny) &&
234  return AArch64II::MO_GOT;
235 
236  // References to tagged globals are marked with MO_NC | MO_TAGGED to indicate
237  // that their nominal addresses are tagged and outside of the code model. In
238  // AArch64ExpandPseudo::expandMI we emit an additional instruction to set the
239  // tag if necessary based on MO_TAGGED.
240  if (AllowTaggedGlobals && !isa<FunctionType>(GV->getValueType()))
242 
243  return AArch64II::MO_NO_FLAG;
244 }
245 
247  const GlobalValue *GV, const TargetMachine &TM) const {
248  // MachO large model always goes via a GOT, because we don't have the
249  // relocations available to do anything else..
250  if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() &&
251  !GV->hasInternalLinkage())
252  return AArch64II::MO_GOT;
253 
254  // NonLazyBind goes via GOT unless we know it's available locally.
255  auto *F = dyn_cast<Function>(GV);
256  if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) &&
257  !TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
258  return AArch64II::MO_GOT;
259 
260  return AArch64II::MO_NO_FLAG;
261 }
262 
264  unsigned NumRegionInstrs) const {
265  // LNT run (at least on Cyclone) showed reasonably significant gains for
266  // bi-directional scheduling. 253.perlbmk.
267  Policy.OnlyTopDown = false;
268  Policy.OnlyBottomUp = false;
269  // Enabling or Disabling the latency heuristic is a close call: It seems to
270  // help nearly no benchmark on out-of-order architectures, on the other hand
271  // it regresses register pressure on a few benchmarking.
273 }
274 
276  return EnableEarlyIfConvert;
277 }
278 
281  return false;
282 
283  if (TargetTriple.isiOS()) {
284  unsigned Major, Minor, Micro;
285  TargetTriple.getiOSVersion(Major, Minor, Micro);
286  return Major >= 8;
287  }
288 
289  return false;
290 }
291 
292 std::unique_ptr<PBQPRAConstraint>
294  return balanceFPOps() ? std::make_unique<A57ChainingConstraint>() : nullptr;
295 }
296 
298  // We usually compute max call frame size after ISel. Do the computation now
299  // if the .mir file didn't specify it. Note that this will probably give you
300  // bogus values after PEI has eliminated the callframe setup/destroy pseudo
301  // instructions, specify explicitly if you need it to be correct.
302  MachineFrameInfo &MFI = MF.getFrameInfo();
303  if (!MFI.isMaxCallFrameSizeComputed())
304  MFI.computeMaxCallFrameSize(MF);
305 }
const Triple & getTargetTriple() const
void getiOSVersion(unsigned &Major, unsigned &Minor, unsigned &Micro) const
getiOSVersion - Parse the version number as with getOSVersion.
Definition: Triple.cpp:1114
BitVector & set()
Definition: BitVector.h:397
unsigned ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const
ClassifyGlobalReference - Find the target operand flags that describe how a global value should be re...
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MO_TAGGED - With MO_PAGE, indicates that the page includes a memory tag in bits 56-63.
This class provides the information for the target register banks.
InstructionSelector * getInstructionSelector() const override
AArch64SelectionDAGInfo TSInfo
bool hasDLLImportStorageClass() const
Definition: GlobalValue.h:265
F(f)
bool hasExternalWeakLinkage() const
Definition: GlobalValue.h:446
const CallLowering * getCallLowering() const override
void mirFileLoaded(MachineFunction &MF) const override
void overrideSchedPolicy(MachineSchedPolicy &Policy, unsigned NumRegionInstrs) const override
This file declares the targeting of the RegisterBankInfo class for AArch64.
unsigned classifyGlobalFunctionReference(const GlobalValue *GV, const TargetMachine &TM) const
Holds all the information related to register banks.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted...
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:140
static cl::opt< bool > EnableEarlyIfConvert("aarch64-early-ifcvt", cl::desc("Enable the early if " "converter pass"), cl::init(true), cl::Hidden)
std::unique_ptr< InstructionSelector > InstSelector
MO_GOT - This flag indicates that a symbol operand represents the address of the GOT entry for the sy...
const AArch64RegisterInfo * getRegisterInfo() const override
This file declares the targeting of the Machinelegalizer class for AArch64.
bool isiOS() const
Is this an iOS triple.
Definition: Triple.h:462
bool supportsAddressTopByteIgnored() const
CPU has TBI (top byte of addresses is ignored during HW address translation) and OS enables it...
bool enableEarlyIfConversion() const override
bool isOSWindows() const
Tests whether the OS is Windows.
Definition: Triple.h:538
const AArch64TargetLowering * getTargetLowering() const override
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:432
bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
bool isX18ReservedByDefault(const Triple &TT)
bool useSmallAddressing() const
bool hasInternalLinkage() const
Definition: GlobalValue.h:443
void computeMaxCallFrameSize(const MachineFunction &MF)
Computes the maximum size of a callframe and the AdjustsStack property.
std::unique_ptr< CallLowering > CallLoweringInfo
GlobalISel related APIs.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:43
AArch64InstrInfo InstrInfo
void ParseSubtargetFeatures(StringRef CPU, StringRef FS)
ParseSubtargetFeatures - Parses features string setting specified subtarget options.
CodeModel::Model getCodeModel() const
Returns the code model.
std::unique_ptr< RegisterBankInfo > RegBankInfo
Provides the logic to select generic machine instructions.
Define a generic scheduling policy for targets that don&#39;t provide their own MachineSchedStrategy.
This class provides the information for the target register banks.
std::unique_ptr< PBQPRAConstraint > getCustomPBQPConstraints() const override
AArch64Subtarget(const Triple &TT, const std::string &CPU, const std::string &FS, const TargetMachine &TM, bool LittleEndian)
This constructor initializes the data members to match that of the specified triple.
const LegalizerInfo * getLegalizerInfo() const override
static cl::opt< bool > UseNonLazyBind("aarch64-enable-nonlazybind", cl::desc("Call nonlazybind functions via direct GOT load"), cl::init(false), cl::Hidden)
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "...
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
AArch64FrameLowering FrameLowering
InstructionSelector * createAArch64InstructionSelector(const AArch64TargetMachine &, AArch64Subtarget &, AArch64RegisterBankInfo &)
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
Type * getValueType() const
Definition: GlobalValue.h:279
This file describes how to lower LLVM calls to machine code calls.
Triple TargetTriple
TargetTriple - What processor and OS we&#39;re targeting.
ARMProcFamilyEnum ARMProcFamily
ARMProcFamily - ARM processor family: Cortex-A53, Cortex-A57, and others.
Module * getParent()
Get the module that this global value is contained inside of...
Definition: GlobalValue.h:575
const RegisterBankInfo * getRegBankInfo() const override
bool isMaxCallFrameSizeComputed() const
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
MO_NC - Indicates whether the linker is expected to check the symbol reference for overflow...
AArch64TargetLowering TLInfo
static cl::opt< bool > UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of " "an address is ignored"), cl::init(false), cl::Hidden)