xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMTargetMachine.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
1 //===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
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 //
10 //===----------------------------------------------------------------------===//
11 
12 #include "ARMTargetMachine.h"
13 #include "ARM.h"
14 #include "ARMMachineFunctionInfo.h"
15 #include "ARMMacroFusion.h"
16 #include "ARMSubtarget.h"
17 #include "ARMTargetObjectFile.h"
18 #include "ARMTargetTransformInfo.h"
19 #include "MCTargetDesc/ARMMCTargetDesc.h"
20 #include "TargetInfo/ARMTargetInfo.h"
21 #include "llvm/ADT/STLExtras.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/Analysis/TargetTransformInfo.h"
24 #include "llvm/CodeGen/ExecutionDomainFix.h"
25 #include "llvm/CodeGen/GlobalISel/CSEInfo.h"
26 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
27 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
28 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
29 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
30 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
31 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
32 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
33 #include "llvm/CodeGen/MIRParser/MIParser.h"
34 #include "llvm/CodeGen/MachineFunction.h"
35 #include "llvm/CodeGen/MachineScheduler.h"
36 #include "llvm/CodeGen/Passes.h"
37 #include "llvm/CodeGen/RegisterBankInfo.h"
38 #include "llvm/CodeGen/TargetPassConfig.h"
39 #include "llvm/IR/Attributes.h"
40 #include "llvm/IR/DataLayout.h"
41 #include "llvm/IR/Function.h"
42 #include "llvm/MC/TargetRegistry.h"
43 #include "llvm/Pass.h"
44 #include "llvm/Support/CodeGen.h"
45 #include "llvm/Support/CommandLine.h"
46 #include "llvm/Support/ErrorHandling.h"
47 #include "llvm/Target/TargetLoweringObjectFile.h"
48 #include "llvm/Target/TargetOptions.h"
49 #include "llvm/TargetParser/ARMTargetParser.h"
50 #include "llvm/TargetParser/TargetParser.h"
51 #include "llvm/TargetParser/Triple.h"
52 #include "llvm/Transforms/CFGuard.h"
53 #include "llvm/Transforms/IPO.h"
54 #include "llvm/Transforms/Scalar.h"
55 #include <cassert>
56 #include <memory>
57 #include <optional>
58 #include <string>
59 
60 using namespace llvm;
61 
62 static cl::opt<bool>
63 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
64                    cl::desc("Inhibit optimization of S->D register accesses on A15"),
65                    cl::init(false));
66 
67 static cl::opt<bool>
68 EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
69                  cl::desc("Run SimplifyCFG after expanding atomic operations"
70                           " to make use of cmpxchg flow-based information"),
71                  cl::init(true));
72 
73 static cl::opt<bool>
74 EnableARMLoadStoreOpt("arm-load-store-opt", cl::Hidden,
75                       cl::desc("Enable ARM load/store optimization pass"),
76                       cl::init(true));
77 
78 // FIXME: Unify control over GlobalMerge.
79 static cl::opt<cl::boolOrDefault>
80 EnableGlobalMerge("arm-global-merge", cl::Hidden,
81                   cl::desc("Enable the global merge pass"));
82 
83 namespace llvm {
84   void initializeARMExecutionDomainFixPass(PassRegistry&);
85 }
86 
LLVMInitializeARMTarget()87 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() {
88   // Register the target.
89   RegisterTargetMachine<ARMLETargetMachine> X(getTheARMLETarget());
90   RegisterTargetMachine<ARMLETargetMachine> A(getTheThumbLETarget());
91   RegisterTargetMachine<ARMBETargetMachine> Y(getTheARMBETarget());
92   RegisterTargetMachine<ARMBETargetMachine> B(getTheThumbBETarget());
93 
94   PassRegistry &Registry = *PassRegistry::getPassRegistry();
95   initializeGlobalISel(Registry);
96   initializeARMLoadStoreOptPass(Registry);
97   initializeARMPreAllocLoadStoreOptPass(Registry);
98   initializeARMParallelDSPPass(Registry);
99   initializeARMBranchTargetsPass(Registry);
100   initializeARMConstantIslandsPass(Registry);
101   initializeARMExecutionDomainFixPass(Registry);
102   initializeARMExpandPseudoPass(Registry);
103   initializeThumb2SizeReducePass(Registry);
104   initializeMVEVPTBlockPass(Registry);
105   initializeMVETPAndVPTOptimisationsPass(Registry);
106   initializeMVETailPredicationPass(Registry);
107   initializeARMLowOverheadLoopsPass(Registry);
108   initializeARMBlockPlacementPass(Registry);
109   initializeMVEGatherScatterLoweringPass(Registry);
110   initializeARMSLSHardeningPass(Registry);
111   initializeMVELaneInterleavingPass(Registry);
112   initializeARMFixCortexA57AES1742098Pass(Registry);
113   initializeARMDAGToDAGISelLegacyPass(Registry);
114 }
115 
createTLOF(const Triple & TT)116 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
117   if (TT.isOSBinFormatMachO())
118     return std::make_unique<TargetLoweringObjectFileMachO>();
119   if (TT.isOSWindows())
120     return std::make_unique<TargetLoweringObjectFileCOFF>();
121   return std::make_unique<ARMElfTargetObjectFile>();
122 }
123 
124 static ARMBaseTargetMachine::ARMABI
computeTargetABI(const Triple & TT,StringRef CPU,const TargetOptions & Options)125 computeTargetABI(const Triple &TT, StringRef CPU,
126                  const TargetOptions &Options) {
127   StringRef ABIName = Options.MCOptions.getABIName();
128 
129   if (ABIName.empty())
130     ABIName = ARM::computeDefaultTargetABI(TT, CPU);
131 
132   if (ABIName == "aapcs16")
133     return ARMBaseTargetMachine::ARM_ABI_AAPCS16;
134   else if (ABIName.starts_with("aapcs"))
135     return ARMBaseTargetMachine::ARM_ABI_AAPCS;
136   else if (ABIName.starts_with("apcs"))
137     return ARMBaseTargetMachine::ARM_ABI_APCS;
138 
139   llvm_unreachable("Unhandled/unknown ABI Name!");
140   return ARMBaseTargetMachine::ARM_ABI_UNKNOWN;
141 }
142 
computeDataLayout(const Triple & TT,StringRef CPU,const TargetOptions & Options,bool isLittle)143 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
144                                      const TargetOptions &Options,
145                                      bool isLittle) {
146   auto ABI = computeTargetABI(TT, CPU, Options);
147   std::string Ret;
148 
149   if (isLittle)
150     // Little endian.
151     Ret += "e";
152   else
153     // Big endian.
154     Ret += "E";
155 
156   Ret += DataLayout::getManglingComponent(TT);
157 
158   // Pointers are 32 bits and aligned to 32 bits.
159   Ret += "-p:32:32";
160 
161   // Function pointers are aligned to 8 bits (because the LSB stores the
162   // ARM/Thumb state).
163   Ret += "-Fi8";
164 
165   // ABIs other than APCS have 64 bit integers with natural alignment.
166   if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS)
167     Ret += "-i64:64";
168 
169   // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
170   // bits, others to 64 bits. We always try to align to 64 bits.
171   if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
172     Ret += "-f64:32:64";
173 
174   // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
175   // to 64. We always ty to give them natural alignment.
176   if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
177     Ret += "-v64:32:64-v128:32:128";
178   else if (ABI != ARMBaseTargetMachine::ARM_ABI_AAPCS16)
179     Ret += "-v128:64:128";
180 
181   // Try to align aggregates to 32 bits (the default is 64 bits, which has no
182   // particular hardware support on 32-bit ARM).
183   Ret += "-a:0:32";
184 
185   // Integer registers are 32 bits.
186   Ret += "-n32";
187 
188   // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
189   // aligned everywhere else.
190   if (TT.isOSNaCl() || ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16)
191     Ret += "-S128";
192   else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS)
193     Ret += "-S64";
194   else
195     Ret += "-S32";
196 
197   return Ret;
198 }
199 
getEffectiveRelocModel(const Triple & TT,std::optional<Reloc::Model> RM)200 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
201                                            std::optional<Reloc::Model> RM) {
202   if (!RM)
203     // Default relocation model on Darwin is PIC.
204     return TT.isOSBinFormatMachO() ? Reloc::PIC_ : Reloc::Static;
205 
206   if (*RM == Reloc::ROPI || *RM == Reloc::RWPI || *RM == Reloc::ROPI_RWPI)
207     assert(TT.isOSBinFormatELF() &&
208            "ROPI/RWPI currently only supported for ELF");
209 
210   // DynamicNoPIC is only used on darwin.
211   if (*RM == Reloc::DynamicNoPIC && !TT.isOSDarwin())
212     return Reloc::Static;
213 
214   return *RM;
215 }
216 
217 /// Create an ARM architecture model.
218 ///
ARMBaseTargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool isLittle)219 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
220                                            StringRef CPU, StringRef FS,
221                                            const TargetOptions &Options,
222                                            std::optional<Reloc::Model> RM,
223                                            std::optional<CodeModel::Model> CM,
224                                            CodeGenOptLevel OL, bool isLittle)
225     : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
226                         CPU, FS, Options, getEffectiveRelocModel(TT, RM),
227                         getEffectiveCodeModel(CM, CodeModel::Small), OL),
228       TargetABI(computeTargetABI(TT, CPU, Options)),
229       TLOF(createTLOF(getTargetTriple())), isLittle(isLittle) {
230 
231   // Default to triple-appropriate float ABI
232   if (Options.FloatABIType == FloatABI::Default) {
233     if (isTargetHardFloat())
234       this->Options.FloatABIType = FloatABI::Hard;
235     else
236       this->Options.FloatABIType = FloatABI::Soft;
237   }
238 
239   // Default to triple-appropriate EABI
240   if (Options.EABIVersion == EABI::Default ||
241       Options.EABIVersion == EABI::Unknown) {
242     // musl is compatible with glibc with regard to EABI version
243     if ((TargetTriple.getEnvironment() == Triple::GNUEABI ||
244          TargetTriple.getEnvironment() == Triple::GNUEABIT64 ||
245          TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
246          TargetTriple.getEnvironment() == Triple::GNUEABIHFT64 ||
247          TargetTriple.getEnvironment() == Triple::MuslEABI ||
248          TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
249          TargetTriple.getEnvironment() == Triple::OpenHOS) &&
250         !(TargetTriple.isOSWindows() || TargetTriple.isOSDarwin()))
251       this->Options.EABIVersion = EABI::GNU;
252     else
253       this->Options.EABIVersion = EABI::EABI5;
254   }
255 
256   if (TT.isOSBinFormatMachO()) {
257     this->Options.TrapUnreachable = true;
258     this->Options.NoTrapAfterNoreturn = true;
259   }
260 
261   // ARM supports the debug entry values.
262   setSupportsDebugEntryValues(true);
263 
264   initAsmInfo();
265 
266   // ARM supports the MachineOutliner.
267   setMachineOutliner(true);
268   setSupportsDefaultOutlining(true);
269 }
270 
271 ARMBaseTargetMachine::~ARMBaseTargetMachine() = default;
272 
createMachineFunctionInfo(BumpPtrAllocator & Allocator,const Function & F,const TargetSubtargetInfo * STI) const273 MachineFunctionInfo *ARMBaseTargetMachine::createMachineFunctionInfo(
274     BumpPtrAllocator &Allocator, const Function &F,
275     const TargetSubtargetInfo *STI) const {
276   return ARMFunctionInfo::create<ARMFunctionInfo>(
277       Allocator, F, static_cast<const ARMSubtarget *>(STI));
278 }
279 
280 const ARMSubtarget *
getSubtargetImpl(const Function & F) const281 ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
282   Attribute CPUAttr = F.getFnAttribute("target-cpu");
283   Attribute FSAttr = F.getFnAttribute("target-features");
284 
285   std::string CPU =
286       CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
287   std::string FS =
288       FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
289 
290   // FIXME: This is related to the code below to reset the target options,
291   // we need to know whether or not the soft float flag is set on the
292   // function before we can generate a subtarget. We also need to use
293   // it as a key for the subtarget since that can be the only difference
294   // between two functions.
295   bool SoftFloat = F.getFnAttribute("use-soft-float").getValueAsBool();
296   // If the soft float attribute is set on the function turn on the soft float
297   // subtarget feature.
298   if (SoftFloat)
299     FS += FS.empty() ? "+soft-float" : ",+soft-float";
300 
301   // Use the optminsize to identify the subtarget, but don't use it in the
302   // feature string.
303   std::string Key = CPU + FS;
304   if (F.hasMinSize())
305     Key += "+minsize";
306 
307   auto &I = SubtargetMap[Key];
308   if (!I) {
309     // This needs to be done before we create a new subtarget since any
310     // creation will depend on the TM and the code generation flags on the
311     // function that reside in TargetOptions.
312     resetTargetOptions(F);
313     I = std::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle,
314                                         F.hasMinSize());
315 
316     if (!I->isThumb() && !I->hasARMOps())
317       F.getContext().emitError("Function '" + F.getName() + "' uses ARM "
318           "instructions, but the target does not support ARM mode execution.");
319   }
320 
321   return I.get();
322 }
323 
324 TargetTransformInfo
getTargetTransformInfo(const Function & F) const325 ARMBaseTargetMachine::getTargetTransformInfo(const Function &F) const {
326   return TargetTransformInfo(ARMTTIImpl(this, F));
327 }
328 
ARMLETargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)329 ARMLETargetMachine::ARMLETargetMachine(const Target &T, const Triple &TT,
330                                        StringRef CPU, StringRef FS,
331                                        const TargetOptions &Options,
332                                        std::optional<Reloc::Model> RM,
333                                        std::optional<CodeModel::Model> CM,
334                                        CodeGenOptLevel OL, bool JIT)
335     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
336 
ARMBETargetMachine(const Target & T,const Triple & TT,StringRef CPU,StringRef FS,const TargetOptions & Options,std::optional<Reloc::Model> RM,std::optional<CodeModel::Model> CM,CodeGenOptLevel OL,bool JIT)337 ARMBETargetMachine::ARMBETargetMachine(const Target &T, const Triple &TT,
338                                        StringRef CPU, StringRef FS,
339                                        const TargetOptions &Options,
340                                        std::optional<Reloc::Model> RM,
341                                        std::optional<CodeModel::Model> CM,
342                                        CodeGenOptLevel OL, bool JIT)
343     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
344 
345 namespace {
346 
347 /// ARM Code Generator Pass Configuration Options.
348 class ARMPassConfig : public TargetPassConfig {
349 public:
ARMPassConfig(ARMBaseTargetMachine & TM,PassManagerBase & PM)350   ARMPassConfig(ARMBaseTargetMachine &TM, PassManagerBase &PM)
351       : TargetPassConfig(TM, PM) {}
352 
getARMTargetMachine() const353   ARMBaseTargetMachine &getARMTargetMachine() const {
354     return getTM<ARMBaseTargetMachine>();
355   }
356 
357   ScheduleDAGInstrs *
createMachineScheduler(MachineSchedContext * C) const358   createMachineScheduler(MachineSchedContext *C) const override {
359     ScheduleDAGMILive *DAG = createGenericSchedLive(C);
360     // add DAG Mutations here.
361     const ARMSubtarget &ST = C->MF->getSubtarget<ARMSubtarget>();
362     if (ST.hasFusion())
363       DAG->addMutation(createARMMacroFusionDAGMutation());
364     return DAG;
365   }
366 
367   ScheduleDAGInstrs *
createPostMachineScheduler(MachineSchedContext * C) const368   createPostMachineScheduler(MachineSchedContext *C) const override {
369     ScheduleDAGMI *DAG = createGenericSchedPostRA(C);
370     // add DAG Mutations here.
371     const ARMSubtarget &ST = C->MF->getSubtarget<ARMSubtarget>();
372     if (ST.hasFusion())
373       DAG->addMutation(createARMMacroFusionDAGMutation());
374     return DAG;
375   }
376 
377   void addIRPasses() override;
378   void addCodeGenPrepare() override;
379   bool addPreISel() override;
380   bool addInstSelector() override;
381   bool addIRTranslator() override;
382   bool addLegalizeMachineIR() override;
383   bool addRegBankSelect() override;
384   bool addGlobalInstructionSelect() override;
385   void addPreRegAlloc() override;
386   void addPreSched2() override;
387   void addPreEmitPass() override;
388   void addPreEmitPass2() override;
389 
390   std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
391 };
392 
393 class ARMExecutionDomainFix : public ExecutionDomainFix {
394 public:
395   static char ID;
ARMExecutionDomainFix()396   ARMExecutionDomainFix() : ExecutionDomainFix(ID, ARM::DPRRegClass) {}
getPassName() const397   StringRef getPassName() const override {
398     return "ARM Execution Domain Fix";
399   }
400 };
401 char ARMExecutionDomainFix::ID;
402 
403 } // end anonymous namespace
404 
405 INITIALIZE_PASS_BEGIN(ARMExecutionDomainFix, "arm-execution-domain-fix",
406   "ARM Execution Domain Fix", false, false)
INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis)407 INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis)
408 INITIALIZE_PASS_END(ARMExecutionDomainFix, "arm-execution-domain-fix",
409   "ARM Execution Domain Fix", false, false)
410 
411 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
412   return new ARMPassConfig(*this, PM);
413 }
414 
getCSEConfig() const415 std::unique_ptr<CSEConfigBase> ARMPassConfig::getCSEConfig() const {
416   return getStandardCSEConfigForOpt(TM->getOptLevel());
417 }
418 
addIRPasses()419 void ARMPassConfig::addIRPasses() {
420   if (TM->Options.ThreadModel == ThreadModel::Single)
421     addPass(createLowerAtomicPass());
422   else
423     addPass(createAtomicExpandLegacyPass());
424 
425   // Cmpxchg instructions are often used with a subsequent comparison to
426   // determine whether it succeeded. We can exploit existing control-flow in
427   // ldrex/strex loops to simplify this, but it needs tidying up.
428   if (TM->getOptLevel() != CodeGenOptLevel::None && EnableAtomicTidy)
429     addPass(createCFGSimplificationPass(
430         SimplifyCFGOptions().hoistCommonInsts(true).sinkCommonInsts(true),
431         [this](const Function &F) {
432           const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
433           return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
434         }));
435 
436   addPass(createMVEGatherScatterLoweringPass());
437   addPass(createMVELaneInterleavingPass());
438 
439   TargetPassConfig::addIRPasses();
440 
441   // Run the parallel DSP pass.
442   if (getOptLevel() == CodeGenOptLevel::Aggressive)
443     addPass(createARMParallelDSPPass());
444 
445   // Match complex arithmetic patterns
446   if (TM->getOptLevel() >= CodeGenOptLevel::Default)
447     addPass(createComplexDeinterleavingPass(TM));
448 
449   // Match interleaved memory accesses to ldN/stN intrinsics.
450   if (TM->getOptLevel() != CodeGenOptLevel::None)
451     addPass(createInterleavedAccessPass());
452 
453   // Add Control Flow Guard checks.
454   if (TM->getTargetTriple().isOSWindows())
455     addPass(createCFGuardCheckPass());
456 
457   if (TM->Options.JMCInstrument)
458     addPass(createJMCInstrumenterPass());
459 }
460 
addCodeGenPrepare()461 void ARMPassConfig::addCodeGenPrepare() {
462   if (getOptLevel() != CodeGenOptLevel::None)
463     addPass(createTypePromotionLegacyPass());
464   TargetPassConfig::addCodeGenPrepare();
465 }
466 
addPreISel()467 bool ARMPassConfig::addPreISel() {
468   if ((TM->getOptLevel() != CodeGenOptLevel::None &&
469        EnableGlobalMerge == cl::BOU_UNSET) ||
470       EnableGlobalMerge == cl::BOU_TRUE) {
471     // FIXME: This is using the thumb1 only constant value for
472     // maximal global offset for merging globals. We may want
473     // to look into using the old value for non-thumb1 code of
474     // 4095 based on the TargetMachine, but this starts to become
475     // tricky when doing code gen per function.
476     bool OnlyOptimizeForSize =
477         (TM->getOptLevel() < CodeGenOptLevel::Aggressive) &&
478         (EnableGlobalMerge == cl::BOU_UNSET);
479     // Merging of extern globals is enabled by default on non-Mach-O as we
480     // expect it to be generally either beneficial or harmless. On Mach-O it
481     // is disabled as we emit the .subsections_via_symbols directive which
482     // means that merging extern globals is not safe.
483     bool MergeExternalByDefault = !TM->getTargetTriple().isOSBinFormatMachO();
484     addPass(createGlobalMergePass(TM, 127, OnlyOptimizeForSize,
485                                   MergeExternalByDefault));
486   }
487 
488   if (TM->getOptLevel() != CodeGenOptLevel::None) {
489     addPass(createHardwareLoopsLegacyPass());
490     addPass(createMVETailPredicationPass());
491     // FIXME: IR passes can delete address-taken basic blocks, deleting
492     // corresponding blockaddresses. ARMConstantPoolConstant holds references to
493     // address-taken basic blocks which can be invalidated if the function
494     // containing the blockaddress has already been codegen'd and the basic
495     // block is removed. Work around this by forcing all IR passes to run before
496     // any ISel takes place. We should have a more principled way of handling
497     // this. See D99707 for more details.
498     addPass(createBarrierNoopPass());
499   }
500 
501   return false;
502 }
503 
addInstSelector()504 bool ARMPassConfig::addInstSelector() {
505   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
506   return false;
507 }
508 
addIRTranslator()509 bool ARMPassConfig::addIRTranslator() {
510   addPass(new IRTranslator(getOptLevel()));
511   return false;
512 }
513 
addLegalizeMachineIR()514 bool ARMPassConfig::addLegalizeMachineIR() {
515   addPass(new Legalizer());
516   return false;
517 }
518 
addRegBankSelect()519 bool ARMPassConfig::addRegBankSelect() {
520   addPass(new RegBankSelect());
521   return false;
522 }
523 
addGlobalInstructionSelect()524 bool ARMPassConfig::addGlobalInstructionSelect() {
525   addPass(new InstructionSelect(getOptLevel()));
526   return false;
527 }
528 
addPreRegAlloc()529 void ARMPassConfig::addPreRegAlloc() {
530   if (getOptLevel() != CodeGenOptLevel::None) {
531     if (getOptLevel() == CodeGenOptLevel::Aggressive)
532       addPass(&MachinePipelinerID);
533 
534     addPass(createMVETPAndVPTOptimisationsPass());
535 
536     addPass(createMLxExpansionPass());
537 
538     if (EnableARMLoadStoreOpt)
539       addPass(createARMLoadStoreOptimizationPass(/* pre-register alloc */ true));
540 
541     if (!DisableA15SDOptimization)
542       addPass(createA15SDOptimizerPass());
543   }
544 }
545 
addPreSched2()546 void ARMPassConfig::addPreSched2() {
547   if (getOptLevel() != CodeGenOptLevel::None) {
548     if (EnableARMLoadStoreOpt)
549       addPass(createARMLoadStoreOptimizationPass());
550 
551     addPass(new ARMExecutionDomainFix());
552     addPass(createBreakFalseDeps());
553   }
554 
555   // Expand some pseudo instructions into multiple instructions to allow
556   // proper scheduling.
557   addPass(createARMExpandPseudoPass());
558 
559   if (getOptLevel() != CodeGenOptLevel::None) {
560     // When optimising for size, always run the Thumb2SizeReduction pass before
561     // IfConversion. Otherwise, check whether IT blocks are restricted
562     // (e.g. in v8, IfConversion depends on Thumb instruction widths)
563     addPass(createThumb2SizeReductionPass([this](const Function &F) {
564       return this->TM->getSubtarget<ARMSubtarget>(F).hasMinSize() ||
565              this->TM->getSubtarget<ARMSubtarget>(F).restrictIT();
566     }));
567 
568     addPass(createIfConverter([](const MachineFunction &MF) {
569       return !MF.getSubtarget<ARMSubtarget>().isThumb1Only();
570     }));
571   }
572   addPass(createThumb2ITBlockPass());
573 
574   // Add both scheduling passes to give the subtarget an opportunity to pick
575   // between them.
576   if (getOptLevel() != CodeGenOptLevel::None) {
577     addPass(&PostMachineSchedulerID);
578     addPass(&PostRASchedulerID);
579   }
580 
581   addPass(createMVEVPTBlockPass());
582   addPass(createARMIndirectThunks());
583   addPass(createARMSLSHardeningPass());
584 }
585 
addPreEmitPass()586 void ARMPassConfig::addPreEmitPass() {
587   addPass(createThumb2SizeReductionPass());
588 
589   // Constant island pass work on unbundled instructions.
590   addPass(createUnpackMachineBundles([](const MachineFunction &MF) {
591     return MF.getSubtarget<ARMSubtarget>().isThumb2();
592   }));
593 
594   // Don't optimize barriers or block placement at -O0.
595   if (getOptLevel() != CodeGenOptLevel::None) {
596     addPass(createARMBlockPlacementPass());
597     addPass(createARMOptimizeBarriersPass());
598   }
599 }
600 
addPreEmitPass2()601 void ARMPassConfig::addPreEmitPass2() {
602   // Inserts fixup instructions before unsafe AES operations. Instructions may
603   // be inserted at the start of blocks and at within blocks so this pass has to
604   // come before those below.
605   addPass(createARMFixCortexA57AES1742098Pass());
606   // Inserts BTIs at the start of functions and indirectly-called basic blocks,
607   // so passes cannot add to the start of basic blocks once this has run.
608   addPass(createARMBranchTargetsPass());
609   // Inserts Constant Islands. Block sizes cannot be increased after this point,
610   // as this may push the branch ranges and load offsets of accessing constant
611   // pools out of range..
612   addPass(createARMConstantIslandPass());
613   // Finalises Low-Overhead Loops. This replaces pseudo instructions with real
614   // instructions, but the pseudos all have conservative sizes so that block
615   // sizes will only be decreased by this pass.
616   addPass(createARMLowOverheadLoopsPass());
617 
618   if (TM->getTargetTriple().isOSWindows()) {
619     // Identify valid longjmp targets for Windows Control Flow Guard.
620     addPass(createCFGuardLongjmpPass());
621     // Identify valid eh continuation targets for Windows EHCont Guard.
622     addPass(createEHContGuardCatchretPass());
623   }
624 }
625 
626 yaml::MachineFunctionInfo *
createDefaultFuncInfoYAML() const627 ARMBaseTargetMachine::createDefaultFuncInfoYAML() const {
628   return new yaml::ARMFunctionInfo();
629 }
630 
631 yaml::MachineFunctionInfo *
convertFuncInfoToYAML(const MachineFunction & MF) const632 ARMBaseTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
633   const auto *MFI = MF.getInfo<ARMFunctionInfo>();
634   return new yaml::ARMFunctionInfo(*MFI);
635 }
636 
parseMachineFunctionInfo(const yaml::MachineFunctionInfo & MFI,PerFunctionMIParsingState & PFS,SMDiagnostic & Error,SMRange & SourceRange) const637 bool ARMBaseTargetMachine::parseMachineFunctionInfo(
638     const yaml::MachineFunctionInfo &MFI, PerFunctionMIParsingState &PFS,
639     SMDiagnostic &Error, SMRange &SourceRange) const {
640   const auto &YamlMFI = static_cast<const yaml::ARMFunctionInfo &>(MFI);
641   MachineFunction &MF = PFS.MF;
642   MF.getInfo<ARMFunctionInfo>()->initializeBaseYamlFields(YamlMFI);
643   return false;
644 }
645