1 //===-- ARMTargetMachine.cpp - Define TargetMachine for ARM ---------------===//
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 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "ARM.h"
14 #include "ARMCallLowering.h"
15 #include "ARMLegalizerInfo.h"
16 #include "ARMRegisterBankInfo.h"
17 #include "ARMSubtarget.h"
18 #include "ARMTargetMachine.h"
19 #include "ARMTargetObjectFile.h"
20 #include "ARMTargetTransformInfo.h"
21 #include "MCTargetDesc/ARMMCTargetDesc.h"
22 #include "llvm/ADT/Optional.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/ADT/StringRef.h"
25 #include "llvm/ADT/Triple.h"
26 #include "llvm/Analysis/TargetTransformInfo.h"
27 #include "llvm/CodeGen/ExecutionDepsFix.h"
28 #include "llvm/CodeGen/GlobalISel/CallLowering.h"
29 #include "llvm/CodeGen/GlobalISel/GISelAccessor.h"
30 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
31 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
32 #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
33 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
34 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
35 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
36 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
37 #include "llvm/CodeGen/MachineFunction.h"
38 #include "llvm/CodeGen/Passes.h"
39 #include "llvm/CodeGen/TargetPassConfig.h"
40 #include "llvm/IR/Attributes.h"
41 #include "llvm/IR/DataLayout.h"
42 #include "llvm/IR/Function.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/Support/TargetParser.h"
48 #include "llvm/Support/TargetRegistry.h"
49 #include "llvm/Target/TargetLoweringObjectFile.h"
50 #include "llvm/Target/TargetOptions.h"
51 #include "llvm/Transforms/Scalar.h"
52 #include <cassert>
53 #include <memory>
54 #include <string>
55 
56 using namespace llvm;
57 
58 static cl::opt<bool>
59 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
60                    cl::desc("Inhibit optimization of S->D register accesses on A15"),
61                    cl::init(false));
62 
63 static cl::opt<bool>
64 EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
65                  cl::desc("Run SimplifyCFG after expanding atomic operations"
66                           " to make use of cmpxchg flow-based information"),
67                  cl::init(true));
68 
69 static cl::opt<bool>
70 EnableARMLoadStoreOpt("arm-load-store-opt", cl::Hidden,
71                       cl::desc("Enable ARM load/store optimization pass"),
72                       cl::init(true));
73 
74 // FIXME: Unify control over GlobalMerge.
75 static cl::opt<cl::boolOrDefault>
76 EnableGlobalMerge("arm-global-merge", cl::Hidden,
77                   cl::desc("Enable the global merge pass"));
78 
79 namespace llvm {
80   void initializeARMExecutionDepsFixPass(PassRegistry&);
81 }
82 
83 extern "C" void LLVMInitializeARMTarget() {
84   // Register the target.
85   RegisterTargetMachine<ARMLETargetMachine> X(getTheARMLETarget());
86   RegisterTargetMachine<ARMBETargetMachine> Y(getTheARMBETarget());
87   RegisterTargetMachine<ThumbLETargetMachine> A(getTheThumbLETarget());
88   RegisterTargetMachine<ThumbBETargetMachine> B(getTheThumbBETarget());
89 
90   PassRegistry &Registry = *PassRegistry::getPassRegistry();
91   initializeGlobalISel(Registry);
92   initializeARMLoadStoreOptPass(Registry);
93   initializeARMPreAllocLoadStoreOptPass(Registry);
94   initializeARMConstantIslandsPass(Registry);
95   initializeARMExecutionDepsFixPass(Registry);
96 }
97 
98 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
99   if (TT.isOSBinFormatMachO())
100     return llvm::make_unique<TargetLoweringObjectFileMachO>();
101   if (TT.isOSWindows())
102     return llvm::make_unique<TargetLoweringObjectFileCOFF>();
103   return llvm::make_unique<ARMElfTargetObjectFile>();
104 }
105 
106 static ARMBaseTargetMachine::ARMABI
107 computeTargetABI(const Triple &TT, StringRef CPU,
108                  const TargetOptions &Options) {
109   if (Options.MCOptions.getABIName() == "aapcs16")
110     return ARMBaseTargetMachine::ARM_ABI_AAPCS16;
111   else if (Options.MCOptions.getABIName().startswith("aapcs"))
112     return ARMBaseTargetMachine::ARM_ABI_AAPCS;
113   else if (Options.MCOptions.getABIName().startswith("apcs"))
114     return ARMBaseTargetMachine::ARM_ABI_APCS;
115 
116   assert(Options.MCOptions.getABIName().empty() &&
117          "Unknown target-abi option!");
118 
119   ARMBaseTargetMachine::ARMABI TargetABI =
120       ARMBaseTargetMachine::ARM_ABI_UNKNOWN;
121 
122   unsigned ArchKind = ARM::parseCPUArch(CPU);
123   StringRef ArchName = ARM::getArchName(ArchKind);
124   // FIXME: This is duplicated code from the front end and should be unified.
125   if (TT.isOSBinFormatMachO()) {
126     if (TT.getEnvironment() == Triple::EABI ||
127         (TT.getOS() == Triple::UnknownOS && TT.isOSBinFormatMachO()) ||
128         ARM::parseArchProfile(ArchName) == ARM::PK_M) {
129       TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
130     } else if (TT.isWatchABI()) {
131       TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS16;
132     } else {
133       TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
134     }
135   } else if (TT.isOSWindows()) {
136     // FIXME: this is invalid for WindowsCE
137     TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
138   } else {
139     // Select the default based on the platform.
140     switch (TT.getEnvironment()) {
141     case Triple::Android:
142     case Triple::GNUEABI:
143     case Triple::GNUEABIHF:
144     case Triple::MuslEABI:
145     case Triple::MuslEABIHF:
146     case Triple::EABIHF:
147     case Triple::EABI:
148       TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
149       break;
150     case Triple::GNU:
151       TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
152       break;
153     default:
154       if (TT.isOSNetBSD())
155         TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
156       else
157         TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
158       break;
159     }
160   }
161 
162   return TargetABI;
163 }
164 
165 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
166                                      const TargetOptions &Options,
167                                      bool isLittle) {
168   auto ABI = computeTargetABI(TT, CPU, Options);
169   std::string Ret;
170 
171   if (isLittle)
172     // Little endian.
173     Ret += "e";
174   else
175     // Big endian.
176     Ret += "E";
177 
178   Ret += DataLayout::getManglingComponent(TT);
179 
180   // Pointers are 32 bits and aligned to 32 bits.
181   Ret += "-p:32:32";
182 
183   // ABIs other than APCS have 64 bit integers with natural alignment.
184   if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS)
185     Ret += "-i64:64";
186 
187   // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
188   // bits, others to 64 bits. We always try to align to 64 bits.
189   if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
190     Ret += "-f64:32:64";
191 
192   // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
193   // to 64. We always ty to give them natural alignment.
194   if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
195     Ret += "-v64:32:64-v128:32:128";
196   else if (ABI != ARMBaseTargetMachine::ARM_ABI_AAPCS16)
197     Ret += "-v128:64:128";
198 
199   // Try to align aggregates to 32 bits (the default is 64 bits, which has no
200   // particular hardware support on 32-bit ARM).
201   Ret += "-a:0:32";
202 
203   // Integer registers are 32 bits.
204   Ret += "-n32";
205 
206   // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
207   // aligned everywhere else.
208   if (TT.isOSNaCl() || ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16)
209     Ret += "-S128";
210   else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS)
211     Ret += "-S64";
212   else
213     Ret += "-S32";
214 
215   return Ret;
216 }
217 
218 static Reloc::Model getEffectiveRelocModel(const Triple &TT,
219                                            Optional<Reloc::Model> RM) {
220   if (!RM.hasValue())
221     // Default relocation model on Darwin is PIC.
222     return TT.isOSBinFormatMachO() ? Reloc::PIC_ : Reloc::Static;
223 
224   if (*RM == Reloc::ROPI || *RM == Reloc::RWPI || *RM == Reloc::ROPI_RWPI)
225     assert(TT.isOSBinFormatELF() &&
226            "ROPI/RWPI currently only supported for ELF");
227 
228   // DynamicNoPIC is only used on darwin.
229   if (*RM == Reloc::DynamicNoPIC && !TT.isOSDarwin())
230     return Reloc::Static;
231 
232   return *RM;
233 }
234 
235 /// Create an ARM architecture model.
236 ///
237 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
238                                            StringRef CPU, StringRef FS,
239                                            const TargetOptions &Options,
240                                            Optional<Reloc::Model> RM,
241                                            CodeModel::Model CM,
242                                            CodeGenOpt::Level OL, bool isLittle)
243     : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
244                         CPU, FS, Options, getEffectiveRelocModel(TT, RM), CM,
245                         OL),
246       TargetABI(computeTargetABI(TT, CPU, Options)),
247       TLOF(createTLOF(getTargetTriple())),
248       Subtarget(TT, CPU, FS, *this, isLittle), isLittle(isLittle) {
249 
250   // Default to triple-appropriate float ABI
251   if (Options.FloatABIType == FloatABI::Default)
252     this->Options.FloatABIType =
253         Subtarget.isTargetHardFloat() ? FloatABI::Hard : FloatABI::Soft;
254 
255   // Default to triple-appropriate EABI
256   if (Options.EABIVersion == EABI::Default ||
257       Options.EABIVersion == EABI::Unknown) {
258     // musl is compatible with glibc with regard to EABI version
259     if (Subtarget.isTargetGNUAEABI() || Subtarget.isTargetMuslAEABI())
260       this->Options.EABIVersion = EABI::GNU;
261     else
262       this->Options.EABIVersion = EABI::EABI5;
263   }
264 }
265 
266 ARMBaseTargetMachine::~ARMBaseTargetMachine() = default;
267 
268 #ifdef LLVM_BUILD_GLOBAL_ISEL
269 namespace {
270 
271 struct ARMGISelActualAccessor : public GISelAccessor {
272   std::unique_ptr<CallLowering> CallLoweringInfo;
273   std::unique_ptr<InstructionSelector> InstSelector;
274   std::unique_ptr<LegalizerInfo> Legalizer;
275   std::unique_ptr<RegisterBankInfo> RegBankInfo;
276 
277   const CallLowering *getCallLowering() const override {
278     return CallLoweringInfo.get();
279   }
280 
281   const InstructionSelector *getInstructionSelector() const override {
282     return InstSelector.get();
283   }
284 
285   const LegalizerInfo *getLegalizerInfo() const override {
286     return Legalizer.get();
287   }
288 
289   const RegisterBankInfo *getRegBankInfo() const override {
290     return RegBankInfo.get();
291   }
292 };
293 
294 } // end anonymous namespace
295 #endif
296 
297 const ARMSubtarget *
298 ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
299   Attribute CPUAttr = F.getFnAttribute("target-cpu");
300   Attribute FSAttr = F.getFnAttribute("target-features");
301 
302   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
303                         ? CPUAttr.getValueAsString().str()
304                         : TargetCPU;
305   std::string FS = !FSAttr.hasAttribute(Attribute::None)
306                        ? FSAttr.getValueAsString().str()
307                        : TargetFS;
308 
309   // FIXME: This is related to the code below to reset the target options,
310   // we need to know whether or not the soft float flag is set on the
311   // function before we can generate a subtarget. We also need to use
312   // it as a key for the subtarget since that can be the only difference
313   // between two functions.
314   bool SoftFloat =
315       F.getFnAttribute("use-soft-float").getValueAsString() == "true";
316   // If the soft float attribute is set on the function turn on the soft float
317   // subtarget feature.
318   if (SoftFloat)
319     FS += FS.empty() ? "+soft-float" : ",+soft-float";
320 
321   auto &I = SubtargetMap[CPU + FS];
322   if (!I) {
323     // This needs to be done before we create a new subtarget since any
324     // creation will depend on the TM and the code generation flags on the
325     // function that reside in TargetOptions.
326     resetTargetOptions(F);
327     I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle);
328 
329 #ifndef LLVM_BUILD_GLOBAL_ISEL
330     GISelAccessor *GISel = new GISelAccessor();
331 #else
332     ARMGISelActualAccessor *GISel = new ARMGISelActualAccessor();
333     GISel->CallLoweringInfo.reset(new ARMCallLowering(*I->getTargetLowering()));
334     GISel->Legalizer.reset(new ARMLegalizerInfo(*I));
335 
336     auto *RBI = new ARMRegisterBankInfo(*I->getRegisterInfo());
337 
338     // FIXME: At this point, we can't rely on Subtarget having RBI.
339     // It's awkward to mix passing RBI and the Subtarget; should we pass
340     // TII/TRI as well?
341     GISel->InstSelector.reset(createARMInstructionSelector(*this, *I, *RBI));
342 
343     GISel->RegBankInfo.reset(RBI);
344 #endif
345     I->setGISelAccessor(*GISel);
346   }
347   return I.get();
348 }
349 
350 TargetIRAnalysis ARMBaseTargetMachine::getTargetIRAnalysis() {
351   return TargetIRAnalysis([this](const Function &F) {
352     return TargetTransformInfo(ARMTTIImpl(this, F));
353   });
354 }
355 
356 void ARMTargetMachine::anchor() {}
357 
358 ARMTargetMachine::ARMTargetMachine(const Target &T, const Triple &TT,
359                                    StringRef CPU, StringRef FS,
360                                    const TargetOptions &Options,
361                                    Optional<Reloc::Model> RM,
362                                    CodeModel::Model CM, CodeGenOpt::Level OL,
363                                    bool isLittle)
364     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
365   initAsmInfo();
366   if (!Subtarget.hasARMOps())
367     report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
368                        "support ARM mode execution!");
369 }
370 
371 void ARMLETargetMachine::anchor() {}
372 
373 ARMLETargetMachine::ARMLETargetMachine(const Target &T, const Triple &TT,
374                                        StringRef CPU, StringRef FS,
375                                        const TargetOptions &Options,
376                                        Optional<Reloc::Model> RM,
377                                        CodeModel::Model CM,
378                                        CodeGenOpt::Level OL)
379     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
380 
381 void ARMBETargetMachine::anchor() {}
382 
383 ARMBETargetMachine::ARMBETargetMachine(const Target &T, const Triple &TT,
384                                        StringRef CPU, StringRef FS,
385                                        const TargetOptions &Options,
386                                        Optional<Reloc::Model> RM,
387                                        CodeModel::Model CM,
388                                        CodeGenOpt::Level OL)
389     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
390 
391 void ThumbTargetMachine::anchor() {}
392 
393 ThumbTargetMachine::ThumbTargetMachine(const Target &T, const Triple &TT,
394                                        StringRef CPU, StringRef FS,
395                                        const TargetOptions &Options,
396                                        Optional<Reloc::Model> RM,
397                                        CodeModel::Model CM,
398                                        CodeGenOpt::Level OL, bool isLittle)
399     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
400   initAsmInfo();
401 }
402 
403 void ThumbLETargetMachine::anchor() {}
404 
405 ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, const Triple &TT,
406                                            StringRef CPU, StringRef FS,
407                                            const TargetOptions &Options,
408                                            Optional<Reloc::Model> RM,
409                                            CodeModel::Model CM,
410                                            CodeGenOpt::Level OL)
411     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
412 
413 void ThumbBETargetMachine::anchor() {}
414 
415 ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, const Triple &TT,
416                                            StringRef CPU, StringRef FS,
417                                            const TargetOptions &Options,
418                                            Optional<Reloc::Model> RM,
419                                            CodeModel::Model CM,
420                                            CodeGenOpt::Level OL)
421     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
422 
423 namespace {
424 
425 /// ARM Code Generator Pass Configuration Options.
426 class ARMPassConfig : public TargetPassConfig {
427 public:
428   ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
429     : TargetPassConfig(TM, PM) {}
430 
431   ARMBaseTargetMachine &getARMTargetMachine() const {
432     return getTM<ARMBaseTargetMachine>();
433   }
434 
435   void addIRPasses() override;
436   bool addPreISel() override;
437   bool addInstSelector() override;
438 #ifdef LLVM_BUILD_GLOBAL_ISEL
439   bool addIRTranslator() override;
440   bool addLegalizeMachineIR() override;
441   bool addRegBankSelect() override;
442   bool addGlobalInstructionSelect() override;
443 #endif
444   void addPreRegAlloc() override;
445   void addPreSched2() override;
446   void addPreEmitPass() override;
447 };
448 
449 class ARMExecutionDepsFix : public ExecutionDepsFix {
450 public:
451   static char ID;
452   ARMExecutionDepsFix() : ExecutionDepsFix(ID, ARM::DPRRegClass) {}
453   StringRef getPassName() const override {
454     return "ARM Execution Dependency Fix";
455   }
456 };
457 char ARMExecutionDepsFix::ID;
458 
459 } // end anonymous namespace
460 
461 INITIALIZE_PASS(ARMExecutionDepsFix, "arm-execution-deps-fix",
462                 "ARM Execution Dependency Fix", false, false)
463 
464 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
465   return new ARMPassConfig(this, PM);
466 }
467 
468 void ARMPassConfig::addIRPasses() {
469   if (TM->Options.ThreadModel == ThreadModel::Single)
470     addPass(createLowerAtomicPass());
471   else
472     addPass(createAtomicExpandPass(TM));
473 
474   // Cmpxchg instructions are often used with a subsequent comparison to
475   // determine whether it succeeded. We can exploit existing control-flow in
476   // ldrex/strex loops to simplify this, but it needs tidying up.
477   if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
478     addPass(createCFGSimplificationPass(-1, [this](const Function &F) {
479       const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
480       return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
481     }));
482 
483   TargetPassConfig::addIRPasses();
484 
485   // Match interleaved memory accesses to ldN/stN intrinsics.
486   if (TM->getOptLevel() != CodeGenOpt::None)
487     addPass(createInterleavedAccessPass(TM));
488 }
489 
490 bool ARMPassConfig::addPreISel() {
491   if ((TM->getOptLevel() != CodeGenOpt::None &&
492        EnableGlobalMerge == cl::BOU_UNSET) ||
493       EnableGlobalMerge == cl::BOU_TRUE) {
494     // FIXME: This is using the thumb1 only constant value for
495     // maximal global offset for merging globals. We may want
496     // to look into using the old value for non-thumb1 code of
497     // 4095 based on the TargetMachine, but this starts to become
498     // tricky when doing code gen per function.
499     bool OnlyOptimizeForSize = (TM->getOptLevel() < CodeGenOpt::Aggressive) &&
500                                (EnableGlobalMerge == cl::BOU_UNSET);
501     // Merging of extern globals is enabled by default on non-Mach-O as we
502     // expect it to be generally either beneficial or harmless. On Mach-O it
503     // is disabled as we emit the .subsections_via_symbols directive which
504     // means that merging extern globals is not safe.
505     bool MergeExternalByDefault = !TM->getTargetTriple().isOSBinFormatMachO();
506     addPass(createGlobalMergePass(TM, 127, OnlyOptimizeForSize,
507                                   MergeExternalByDefault));
508   }
509 
510   return false;
511 }
512 
513 bool ARMPassConfig::addInstSelector() {
514   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
515   return false;
516 }
517 
518 #ifdef LLVM_BUILD_GLOBAL_ISEL
519 bool ARMPassConfig::addIRTranslator() {
520   addPass(new IRTranslator());
521   return false;
522 }
523 
524 bool ARMPassConfig::addLegalizeMachineIR() {
525   addPass(new Legalizer());
526   return false;
527 }
528 
529 bool ARMPassConfig::addRegBankSelect() {
530   addPass(new RegBankSelect());
531   return false;
532 }
533 
534 bool ARMPassConfig::addGlobalInstructionSelect() {
535   addPass(new InstructionSelect());
536   return false;
537 }
538 #endif
539 
540 void ARMPassConfig::addPreRegAlloc() {
541   if (getOptLevel() != CodeGenOpt::None) {
542     addPass(createMLxExpansionPass());
543 
544     if (EnableARMLoadStoreOpt)
545       addPass(createARMLoadStoreOptimizationPass(/* pre-register alloc */ true));
546 
547     if (!DisableA15SDOptimization)
548       addPass(createA15SDOptimizerPass());
549   }
550 }
551 
552 void ARMPassConfig::addPreSched2() {
553   if (getOptLevel() != CodeGenOpt::None) {
554     if (EnableARMLoadStoreOpt)
555       addPass(createARMLoadStoreOptimizationPass());
556 
557     addPass(new ARMExecutionDepsFix());
558   }
559 
560   // Expand some pseudo instructions into multiple instructions to allow
561   // proper scheduling.
562   addPass(createARMExpandPseudoPass());
563 
564   if (getOptLevel() != CodeGenOpt::None) {
565     // in v8, IfConversion depends on Thumb instruction widths
566     addPass(createThumb2SizeReductionPass([this](const Function &F) {
567       return this->TM->getSubtarget<ARMSubtarget>(F).restrictIT();
568     }));
569 
570     addPass(createIfConverter([](const MachineFunction &MF) {
571       return !MF.getSubtarget<ARMSubtarget>().isThumb1Only();
572     }));
573   }
574   addPass(createThumb2ITBlockPass());
575 }
576 
577 void ARMPassConfig::addPreEmitPass() {
578   addPass(createThumb2SizeReductionPass());
579 
580   // Constant island pass work on unbundled instructions.
581   addPass(createUnpackMachineBundles([](const MachineFunction &MF) {
582     return MF.getSubtarget<ARMSubtarget>().isThumb2();
583   }));
584 
585   // Don't optimize barriers at -O0.
586   if (getOptLevel() != CodeGenOpt::None)
587     addPass(createARMOptimizeBarriersPass());
588 
589   addPass(createARMConstantIslandPass());
590 }
591