106f32e7eSjoerg //===-- AArch64Subtarget.cpp - AArch64 Subtarget Information ----*- C++ -*-===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file implements the AArch64 specific subclass of TargetSubtarget.
1006f32e7eSjoerg //
1106f32e7eSjoerg //===----------------------------------------------------------------------===//
1206f32e7eSjoerg 
1306f32e7eSjoerg #include "AArch64Subtarget.h"
1406f32e7eSjoerg 
1506f32e7eSjoerg #include "AArch64.h"
1606f32e7eSjoerg #include "AArch64InstrInfo.h"
1706f32e7eSjoerg #include "AArch64PBQPRegAlloc.h"
1806f32e7eSjoerg #include "AArch64TargetMachine.h"
19*da58b97aSjoerg #include "GISel/AArch64CallLowering.h"
20*da58b97aSjoerg #include "GISel/AArch64LegalizerInfo.h"
21*da58b97aSjoerg #include "GISel/AArch64RegisterBankInfo.h"
2206f32e7eSjoerg #include "MCTargetDesc/AArch64AddressingModes.h"
2306f32e7eSjoerg #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
2406f32e7eSjoerg #include "llvm/CodeGen/MachineScheduler.h"
2506f32e7eSjoerg #include "llvm/IR/GlobalValue.h"
2606f32e7eSjoerg #include "llvm/Support/TargetParser.h"
2706f32e7eSjoerg 
2806f32e7eSjoerg using namespace llvm;
2906f32e7eSjoerg 
3006f32e7eSjoerg #define DEBUG_TYPE "aarch64-subtarget"
3106f32e7eSjoerg 
3206f32e7eSjoerg #define GET_SUBTARGETINFO_CTOR
3306f32e7eSjoerg #define GET_SUBTARGETINFO_TARGET_DESC
3406f32e7eSjoerg #include "AArch64GenSubtargetInfo.inc"
3506f32e7eSjoerg 
3606f32e7eSjoerg static cl::opt<bool>
3706f32e7eSjoerg EnableEarlyIfConvert("aarch64-early-ifcvt", cl::desc("Enable the early if "
3806f32e7eSjoerg                      "converter pass"), cl::init(true), cl::Hidden);
3906f32e7eSjoerg 
4006f32e7eSjoerg // If OS supports TBI, use this flag to enable it.
4106f32e7eSjoerg static cl::opt<bool>
4206f32e7eSjoerg UseAddressTopByteIgnored("aarch64-use-tbi", cl::desc("Assume that top byte of "
4306f32e7eSjoerg                          "an address is ignored"), cl::init(false), cl::Hidden);
4406f32e7eSjoerg 
4506f32e7eSjoerg static cl::opt<bool>
4606f32e7eSjoerg     UseNonLazyBind("aarch64-enable-nonlazybind",
4706f32e7eSjoerg                    cl::desc("Call nonlazybind functions via direct GOT load"),
4806f32e7eSjoerg                    cl::init(false), cl::Hidden);
4906f32e7eSjoerg 
50*da58b97aSjoerg static cl::opt<unsigned> SVEVectorBitsMax(
51*da58b97aSjoerg     "aarch64-sve-vector-bits-max",
52*da58b97aSjoerg     cl::desc("Assume SVE vector registers are at most this big, "
53*da58b97aSjoerg              "with zero meaning no maximum size is assumed."),
54*da58b97aSjoerg     cl::init(0), cl::Hidden);
55*da58b97aSjoerg 
56*da58b97aSjoerg static cl::opt<unsigned> SVEVectorBitsMin(
57*da58b97aSjoerg     "aarch64-sve-vector-bits-min",
58*da58b97aSjoerg     cl::desc("Assume SVE vector registers are at least this big, "
59*da58b97aSjoerg              "with zero meaning no minimum size is assumed."),
60*da58b97aSjoerg     cl::init(0), cl::Hidden);
61*da58b97aSjoerg 
62*da58b97aSjoerg static cl::opt<bool> UseAA("aarch64-use-aa", cl::init(true),
63*da58b97aSjoerg                            cl::desc("Enable the use of AA during codegen."));
64*da58b97aSjoerg 
6506f32e7eSjoerg AArch64Subtarget &
initializeSubtargetDependencies(StringRef FS,StringRef CPUString)6606f32e7eSjoerg AArch64Subtarget::initializeSubtargetDependencies(StringRef FS,
6706f32e7eSjoerg                                                   StringRef CPUString) {
6806f32e7eSjoerg   // Determine default and user-specified characteristics
6906f32e7eSjoerg 
7006f32e7eSjoerg   if (CPUString.empty())
7106f32e7eSjoerg     CPUString = "generic";
7206f32e7eSjoerg 
73*da58b97aSjoerg   ParseSubtargetFeatures(CPUString, /*TuneCPU*/ CPUString, FS);
7406f32e7eSjoerg   initializeProperties();
7506f32e7eSjoerg 
7606f32e7eSjoerg   return *this;
7706f32e7eSjoerg }
7806f32e7eSjoerg 
initializeProperties()7906f32e7eSjoerg void AArch64Subtarget::initializeProperties() {
8006f32e7eSjoerg   // Initialize CPU specific properties. We should add a tablegen feature for
8106f32e7eSjoerg   // this in the future so we can specify it together with the subtarget
8206f32e7eSjoerg   // features.
8306f32e7eSjoerg   switch (ARMProcFamily) {
8406f32e7eSjoerg   case Others:
8506f32e7eSjoerg     break;
86*da58b97aSjoerg   case Carmel:
87*da58b97aSjoerg     CacheLineSize = 64;
88*da58b97aSjoerg     break;
8906f32e7eSjoerg   case CortexA35:
9006f32e7eSjoerg     break;
9106f32e7eSjoerg   case CortexA53:
9206f32e7eSjoerg   case CortexA55:
93*da58b97aSjoerg     PrefFunctionLogAlignment = 4;
9406f32e7eSjoerg     break;
9506f32e7eSjoerg   case CortexA57:
9606f32e7eSjoerg     MaxInterleaveFactor = 4;
9706f32e7eSjoerg     PrefFunctionLogAlignment = 4;
9806f32e7eSjoerg     break;
9906f32e7eSjoerg   case CortexA65:
10006f32e7eSjoerg     PrefFunctionLogAlignment = 3;
10106f32e7eSjoerg     break;
10206f32e7eSjoerg   case CortexA72:
10306f32e7eSjoerg   case CortexA73:
10406f32e7eSjoerg   case CortexA75:
10506f32e7eSjoerg   case CortexA76:
106*da58b97aSjoerg   case CortexA77:
107*da58b97aSjoerg   case CortexA78:
108*da58b97aSjoerg   case CortexA78C:
109*da58b97aSjoerg   case CortexR82:
110*da58b97aSjoerg   case CortexX1:
11106f32e7eSjoerg     PrefFunctionLogAlignment = 4;
11206f32e7eSjoerg     break;
113*da58b97aSjoerg   case A64FX:
114*da58b97aSjoerg     CacheLineSize = 256;
115*da58b97aSjoerg     PrefFunctionLogAlignment = 3;
116*da58b97aSjoerg     PrefLoopLogAlignment = 2;
117*da58b97aSjoerg     MaxInterleaveFactor = 4;
118*da58b97aSjoerg     PrefetchDistance = 128;
119*da58b97aSjoerg     MinPrefetchStride = 1024;
120*da58b97aSjoerg     MaxPrefetchIterationsAhead = 4;
121*da58b97aSjoerg     break;
122*da58b97aSjoerg   case AppleA7:
123*da58b97aSjoerg   case AppleA10:
124*da58b97aSjoerg   case AppleA11:
125*da58b97aSjoerg   case AppleA12:
126*da58b97aSjoerg   case AppleA13:
127*da58b97aSjoerg   case AppleA14:
12806f32e7eSjoerg     CacheLineSize = 64;
12906f32e7eSjoerg     PrefetchDistance = 280;
13006f32e7eSjoerg     MinPrefetchStride = 2048;
13106f32e7eSjoerg     MaxPrefetchIterationsAhead = 3;
13206f32e7eSjoerg     break;
13306f32e7eSjoerg   case ExynosM3:
13406f32e7eSjoerg     MaxInterleaveFactor = 4;
13506f32e7eSjoerg     MaxJumpTableSize = 20;
13606f32e7eSjoerg     PrefFunctionLogAlignment = 5;
13706f32e7eSjoerg     PrefLoopLogAlignment = 4;
13806f32e7eSjoerg     break;
13906f32e7eSjoerg   case Falkor:
14006f32e7eSjoerg     MaxInterleaveFactor = 4;
14106f32e7eSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
14206f32e7eSjoerg     MinVectorRegisterBitWidth = 128;
14306f32e7eSjoerg     CacheLineSize = 128;
14406f32e7eSjoerg     PrefetchDistance = 820;
14506f32e7eSjoerg     MinPrefetchStride = 2048;
14606f32e7eSjoerg     MaxPrefetchIterationsAhead = 8;
14706f32e7eSjoerg     break;
14806f32e7eSjoerg   case Kryo:
14906f32e7eSjoerg     MaxInterleaveFactor = 4;
15006f32e7eSjoerg     VectorInsertExtractBaseCost = 2;
15106f32e7eSjoerg     CacheLineSize = 128;
15206f32e7eSjoerg     PrefetchDistance = 740;
15306f32e7eSjoerg     MinPrefetchStride = 1024;
15406f32e7eSjoerg     MaxPrefetchIterationsAhead = 11;
15506f32e7eSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
15606f32e7eSjoerg     MinVectorRegisterBitWidth = 128;
15706f32e7eSjoerg     break;
15806f32e7eSjoerg   case NeoverseE1:
15906f32e7eSjoerg     PrefFunctionLogAlignment = 3;
16006f32e7eSjoerg     break;
16106f32e7eSjoerg   case NeoverseN1:
162*da58b97aSjoerg   case NeoverseN2:
163*da58b97aSjoerg   case NeoverseV1:
16406f32e7eSjoerg     PrefFunctionLogAlignment = 4;
16506f32e7eSjoerg     break;
16606f32e7eSjoerg   case Saphira:
16706f32e7eSjoerg     MaxInterleaveFactor = 4;
16806f32e7eSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
16906f32e7eSjoerg     MinVectorRegisterBitWidth = 128;
17006f32e7eSjoerg     break;
17106f32e7eSjoerg   case ThunderX2T99:
17206f32e7eSjoerg     CacheLineSize = 64;
17306f32e7eSjoerg     PrefFunctionLogAlignment = 3;
17406f32e7eSjoerg     PrefLoopLogAlignment = 2;
17506f32e7eSjoerg     MaxInterleaveFactor = 4;
17606f32e7eSjoerg     PrefetchDistance = 128;
17706f32e7eSjoerg     MinPrefetchStride = 1024;
17806f32e7eSjoerg     MaxPrefetchIterationsAhead = 4;
17906f32e7eSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
18006f32e7eSjoerg     MinVectorRegisterBitWidth = 128;
18106f32e7eSjoerg     break;
18206f32e7eSjoerg   case ThunderX:
18306f32e7eSjoerg   case ThunderXT88:
18406f32e7eSjoerg   case ThunderXT81:
18506f32e7eSjoerg   case ThunderXT83:
18606f32e7eSjoerg     CacheLineSize = 128;
18706f32e7eSjoerg     PrefFunctionLogAlignment = 3;
18806f32e7eSjoerg     PrefLoopLogAlignment = 2;
18906f32e7eSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
19006f32e7eSjoerg     MinVectorRegisterBitWidth = 128;
19106f32e7eSjoerg     break;
19206f32e7eSjoerg   case TSV110:
19306f32e7eSjoerg     CacheLineSize = 64;
19406f32e7eSjoerg     PrefFunctionLogAlignment = 4;
19506f32e7eSjoerg     PrefLoopLogAlignment = 2;
19606f32e7eSjoerg     break;
197*da58b97aSjoerg   case ThunderX3T110:
198*da58b97aSjoerg     CacheLineSize = 64;
199*da58b97aSjoerg     PrefFunctionLogAlignment = 4;
200*da58b97aSjoerg     PrefLoopLogAlignment = 2;
201*da58b97aSjoerg     MaxInterleaveFactor = 4;
202*da58b97aSjoerg     PrefetchDistance = 128;
203*da58b97aSjoerg     MinPrefetchStride = 1024;
204*da58b97aSjoerg     MaxPrefetchIterationsAhead = 4;
205*da58b97aSjoerg     // FIXME: remove this to enable 64-bit SLP if performance looks good.
206*da58b97aSjoerg     MinVectorRegisterBitWidth = 128;
207*da58b97aSjoerg     break;
20806f32e7eSjoerg   }
20906f32e7eSjoerg }
21006f32e7eSjoerg 
AArch64Subtarget(const Triple & TT,const std::string & CPU,const std::string & FS,const TargetMachine & TM,bool LittleEndian)21106f32e7eSjoerg AArch64Subtarget::AArch64Subtarget(const Triple &TT, const std::string &CPU,
21206f32e7eSjoerg                                    const std::string &FS,
21306f32e7eSjoerg                                    const TargetMachine &TM, bool LittleEndian)
214*da58b97aSjoerg     : AArch64GenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
21506f32e7eSjoerg       ReserveXRegister(AArch64::GPR64commonRegClass.getNumRegs()),
21606f32e7eSjoerg       CustomCallSavedXRegs(AArch64::GPR64commonRegClass.getNumRegs()),
21706f32e7eSjoerg       IsLittle(LittleEndian),
21806f32e7eSjoerg       TargetTriple(TT), FrameLowering(),
21906f32e7eSjoerg       InstrInfo(initializeSubtargetDependencies(FS, CPU)), TSInfo(),
22006f32e7eSjoerg       TLInfo(TM, *this) {
22106f32e7eSjoerg   if (AArch64::isX18ReservedByDefault(TT))
22206f32e7eSjoerg     ReserveXRegister.set(18);
22306f32e7eSjoerg 
22406f32e7eSjoerg   CallLoweringInfo.reset(new AArch64CallLowering(*getTargetLowering()));
225*da58b97aSjoerg   InlineAsmLoweringInfo.reset(new InlineAsmLowering(getTargetLowering()));
22606f32e7eSjoerg   Legalizer.reset(new AArch64LegalizerInfo(*this));
22706f32e7eSjoerg 
22806f32e7eSjoerg   auto *RBI = new AArch64RegisterBankInfo(*getRegisterInfo());
22906f32e7eSjoerg 
23006f32e7eSjoerg   // FIXME: At this point, we can't rely on Subtarget having RBI.
23106f32e7eSjoerg   // It's awkward to mix passing RBI and the Subtarget; should we pass
23206f32e7eSjoerg   // TII/TRI as well?
23306f32e7eSjoerg   InstSelector.reset(createAArch64InstructionSelector(
23406f32e7eSjoerg       *static_cast<const AArch64TargetMachine *>(&TM), *this, *RBI));
23506f32e7eSjoerg 
23606f32e7eSjoerg   RegBankInfo.reset(RBI);
23706f32e7eSjoerg }
23806f32e7eSjoerg 
getCallLowering() const23906f32e7eSjoerg const CallLowering *AArch64Subtarget::getCallLowering() const {
24006f32e7eSjoerg   return CallLoweringInfo.get();
24106f32e7eSjoerg }
24206f32e7eSjoerg 
getInlineAsmLowering() const243*da58b97aSjoerg const InlineAsmLowering *AArch64Subtarget::getInlineAsmLowering() const {
244*da58b97aSjoerg   return InlineAsmLoweringInfo.get();
245*da58b97aSjoerg }
246*da58b97aSjoerg 
getInstructionSelector() const24706f32e7eSjoerg InstructionSelector *AArch64Subtarget::getInstructionSelector() const {
24806f32e7eSjoerg   return InstSelector.get();
24906f32e7eSjoerg }
25006f32e7eSjoerg 
getLegalizerInfo() const25106f32e7eSjoerg const LegalizerInfo *AArch64Subtarget::getLegalizerInfo() const {
25206f32e7eSjoerg   return Legalizer.get();
25306f32e7eSjoerg }
25406f32e7eSjoerg 
getRegBankInfo() const25506f32e7eSjoerg const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const {
25606f32e7eSjoerg   return RegBankInfo.get();
25706f32e7eSjoerg }
25806f32e7eSjoerg 
25906f32e7eSjoerg /// Find the target operand flags that describe how a global value should be
26006f32e7eSjoerg /// referenced for the current subtarget.
26106f32e7eSjoerg unsigned
ClassifyGlobalReference(const GlobalValue * GV,const TargetMachine & TM) const26206f32e7eSjoerg AArch64Subtarget::ClassifyGlobalReference(const GlobalValue *GV,
26306f32e7eSjoerg                                           const TargetMachine &TM) const {
26406f32e7eSjoerg   // MachO large model always goes via a GOT, simply to get a single 8-byte
26506f32e7eSjoerg   // absolute relocation on all global addresses.
26606f32e7eSjoerg   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO())
26706f32e7eSjoerg     return AArch64II::MO_GOT;
26806f32e7eSjoerg 
26906f32e7eSjoerg   if (!TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) {
27006f32e7eSjoerg     if (GV->hasDLLImportStorageClass())
27106f32e7eSjoerg       return AArch64II::MO_GOT | AArch64II::MO_DLLIMPORT;
27206f32e7eSjoerg     if (getTargetTriple().isOSWindows())
27306f32e7eSjoerg       return AArch64II::MO_GOT | AArch64II::MO_COFFSTUB;
27406f32e7eSjoerg     return AArch64II::MO_GOT;
27506f32e7eSjoerg   }
27606f32e7eSjoerg 
27706f32e7eSjoerg   // The small code model's direct accesses use ADRP, which cannot
27806f32e7eSjoerg   // necessarily produce the value 0 (if the code is above 4GB).
27906f32e7eSjoerg   // Same for the tiny code model, where we have a pc relative LDR.
28006f32e7eSjoerg   if ((useSmallAddressing() || TM.getCodeModel() == CodeModel::Tiny) &&
28106f32e7eSjoerg       GV->hasExternalWeakLinkage())
28206f32e7eSjoerg     return AArch64II::MO_GOT;
28306f32e7eSjoerg 
28406f32e7eSjoerg   // References to tagged globals are marked with MO_NC | MO_TAGGED to indicate
28506f32e7eSjoerg   // that their nominal addresses are tagged and outside of the code model. In
28606f32e7eSjoerg   // AArch64ExpandPseudo::expandMI we emit an additional instruction to set the
28706f32e7eSjoerg   // tag if necessary based on MO_TAGGED.
28806f32e7eSjoerg   if (AllowTaggedGlobals && !isa<FunctionType>(GV->getValueType()))
28906f32e7eSjoerg     return AArch64II::MO_NC | AArch64II::MO_TAGGED;
29006f32e7eSjoerg 
29106f32e7eSjoerg   return AArch64II::MO_NO_FLAG;
29206f32e7eSjoerg }
29306f32e7eSjoerg 
classifyGlobalFunctionReference(const GlobalValue * GV,const TargetMachine & TM) const29406f32e7eSjoerg unsigned AArch64Subtarget::classifyGlobalFunctionReference(
29506f32e7eSjoerg     const GlobalValue *GV, const TargetMachine &TM) const {
29606f32e7eSjoerg   // MachO large model always goes via a GOT, because we don't have the
29706f32e7eSjoerg   // relocations available to do anything else..
29806f32e7eSjoerg   if (TM.getCodeModel() == CodeModel::Large && isTargetMachO() &&
29906f32e7eSjoerg       !GV->hasInternalLinkage())
30006f32e7eSjoerg     return AArch64II::MO_GOT;
30106f32e7eSjoerg 
30206f32e7eSjoerg   // NonLazyBind goes via GOT unless we know it's available locally.
30306f32e7eSjoerg   auto *F = dyn_cast<Function>(GV);
30406f32e7eSjoerg   if (UseNonLazyBind && F && F->hasFnAttribute(Attribute::NonLazyBind) &&
30506f32e7eSjoerg       !TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
30606f32e7eSjoerg     return AArch64II::MO_GOT;
30706f32e7eSjoerg 
308*da58b97aSjoerg   // Use ClassifyGlobalReference for setting MO_DLLIMPORT/MO_COFFSTUB.
309*da58b97aSjoerg   if (getTargetTriple().isOSWindows())
310*da58b97aSjoerg     return ClassifyGlobalReference(GV, TM);
311*da58b97aSjoerg 
31206f32e7eSjoerg   return AArch64II::MO_NO_FLAG;
31306f32e7eSjoerg }
31406f32e7eSjoerg 
overrideSchedPolicy(MachineSchedPolicy & Policy,unsigned NumRegionInstrs) const31506f32e7eSjoerg void AArch64Subtarget::overrideSchedPolicy(MachineSchedPolicy &Policy,
31606f32e7eSjoerg                                            unsigned NumRegionInstrs) const {
31706f32e7eSjoerg   // LNT run (at least on Cyclone) showed reasonably significant gains for
31806f32e7eSjoerg   // bi-directional scheduling. 253.perlbmk.
31906f32e7eSjoerg   Policy.OnlyTopDown = false;
32006f32e7eSjoerg   Policy.OnlyBottomUp = false;
32106f32e7eSjoerg   // Enabling or Disabling the latency heuristic is a close call: It seems to
32206f32e7eSjoerg   // help nearly no benchmark on out-of-order architectures, on the other hand
32306f32e7eSjoerg   // it regresses register pressure on a few benchmarking.
32406f32e7eSjoerg   Policy.DisableLatencyHeuristic = DisableLatencySchedHeuristic;
32506f32e7eSjoerg }
32606f32e7eSjoerg 
enableEarlyIfConversion() const32706f32e7eSjoerg bool AArch64Subtarget::enableEarlyIfConversion() const {
32806f32e7eSjoerg   return EnableEarlyIfConvert;
32906f32e7eSjoerg }
33006f32e7eSjoerg 
supportsAddressTopByteIgnored() const33106f32e7eSjoerg bool AArch64Subtarget::supportsAddressTopByteIgnored() const {
33206f32e7eSjoerg   if (!UseAddressTopByteIgnored)
33306f32e7eSjoerg     return false;
33406f32e7eSjoerg 
33506f32e7eSjoerg   if (TargetTriple.isiOS()) {
33606f32e7eSjoerg     unsigned Major, Minor, Micro;
33706f32e7eSjoerg     TargetTriple.getiOSVersion(Major, Minor, Micro);
33806f32e7eSjoerg     return Major >= 8;
33906f32e7eSjoerg   }
34006f32e7eSjoerg 
34106f32e7eSjoerg   return false;
34206f32e7eSjoerg }
34306f32e7eSjoerg 
34406f32e7eSjoerg std::unique_ptr<PBQPRAConstraint>
getCustomPBQPConstraints() const34506f32e7eSjoerg AArch64Subtarget::getCustomPBQPConstraints() const {
34606f32e7eSjoerg   return balanceFPOps() ? std::make_unique<A57ChainingConstraint>() : nullptr;
34706f32e7eSjoerg }
34806f32e7eSjoerg 
mirFileLoaded(MachineFunction & MF) const34906f32e7eSjoerg void AArch64Subtarget::mirFileLoaded(MachineFunction &MF) const {
35006f32e7eSjoerg   // We usually compute max call frame size after ISel. Do the computation now
35106f32e7eSjoerg   // if the .mir file didn't specify it. Note that this will probably give you
35206f32e7eSjoerg   // bogus values after PEI has eliminated the callframe setup/destroy pseudo
35306f32e7eSjoerg   // instructions, specify explicitly if you need it to be correct.
35406f32e7eSjoerg   MachineFrameInfo &MFI = MF.getFrameInfo();
35506f32e7eSjoerg   if (!MFI.isMaxCallFrameSizeComputed())
35606f32e7eSjoerg     MFI.computeMaxCallFrameSize(MF);
35706f32e7eSjoerg }
358*da58b97aSjoerg 
getMaxSVEVectorSizeInBits() const359*da58b97aSjoerg unsigned AArch64Subtarget::getMaxSVEVectorSizeInBits() const {
360*da58b97aSjoerg   assert(HasSVE && "Tried to get SVE vector length without SVE support!");
361*da58b97aSjoerg   assert(SVEVectorBitsMax % 128 == 0 &&
362*da58b97aSjoerg          "SVE requires vector length in multiples of 128!");
363*da58b97aSjoerg   assert((SVEVectorBitsMax >= SVEVectorBitsMin || SVEVectorBitsMax == 0) &&
364*da58b97aSjoerg          "Minimum SVE vector size should not be larger than its maximum!");
365*da58b97aSjoerg   if (SVEVectorBitsMax == 0)
366*da58b97aSjoerg     return 0;
367*da58b97aSjoerg   return (std::max(SVEVectorBitsMin, SVEVectorBitsMax) / 128) * 128;
368*da58b97aSjoerg }
369*da58b97aSjoerg 
getMinSVEVectorSizeInBits() const370*da58b97aSjoerg unsigned AArch64Subtarget::getMinSVEVectorSizeInBits() const {
371*da58b97aSjoerg   assert(HasSVE && "Tried to get SVE vector length without SVE support!");
372*da58b97aSjoerg   assert(SVEVectorBitsMin % 128 == 0 &&
373*da58b97aSjoerg          "SVE requires vector length in multiples of 128!");
374*da58b97aSjoerg   assert((SVEVectorBitsMax >= SVEVectorBitsMin || SVEVectorBitsMax == 0) &&
375*da58b97aSjoerg          "Minimum SVE vector size should not be larger than its maximum!");
376*da58b97aSjoerg   if (SVEVectorBitsMax == 0)
377*da58b97aSjoerg     return (SVEVectorBitsMin / 128) * 128;
378*da58b97aSjoerg   return (std::min(SVEVectorBitsMin, SVEVectorBitsMax) / 128) * 128;
379*da58b97aSjoerg }
380*da58b97aSjoerg 
useSVEForFixedLengthVectors() const381*da58b97aSjoerg bool AArch64Subtarget::useSVEForFixedLengthVectors() const {
382*da58b97aSjoerg   // Prefer NEON unless larger SVE registers are available.
383*da58b97aSjoerg   return hasSVE() && getMinSVEVectorSizeInBits() >= 256;
384*da58b97aSjoerg }
385*da58b97aSjoerg 
useAA() const386*da58b97aSjoerg bool AArch64Subtarget::useAA() const { return UseAA; }
387