ARMTargetMachine.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  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. #include "ARMTargetMachine.h"
  12. #include "ARM.h"
  13. #include "ARMMacroFusion.h"
  14. #include "ARMSubtarget.h"
  15. #include "ARMTargetObjectFile.h"
  16. #include "ARMTargetTransformInfo.h"
  17. #include "MCTargetDesc/ARMMCTargetDesc.h"
  18. #include "TargetInfo/ARMTargetInfo.h"
  19. #include "llvm/ADT/Optional.h"
  20. #include "llvm/ADT/STLExtras.h"
  21. #include "llvm/ADT/StringRef.h"
  22. #include "llvm/ADT/Triple.h"
  23. #include "llvm/Analysis/TargetTransformInfo.h"
  24. #include "llvm/CodeGen/ExecutionDomainFix.h"
  25. #include "llvm/CodeGen/GlobalISel/CallLowering.h"
  26. #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
  27. #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
  28. #include "llvm/CodeGen/GlobalISel/InstructionSelector.h"
  29. #include "llvm/CodeGen/GlobalISel/Legalizer.h"
  30. #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
  31. #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
  32. #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
  33. #include "llvm/CodeGen/MachineFunction.h"
  34. #include "llvm/CodeGen/MachineScheduler.h"
  35. #include "llvm/CodeGen/Passes.h"
  36. #include "llvm/CodeGen/TargetPassConfig.h"
  37. #include "llvm/IR/Attributes.h"
  38. #include "llvm/IR/DataLayout.h"
  39. #include "llvm/IR/Function.h"
  40. #include "llvm/Pass.h"
  41. #include "llvm/Support/CodeGen.h"
  42. #include "llvm/Support/CommandLine.h"
  43. #include "llvm/Support/ErrorHandling.h"
  44. #include "llvm/Support/TargetParser.h"
  45. #include "llvm/Support/TargetRegistry.h"
  46. #include "llvm/Target/TargetLoweringObjectFile.h"
  47. #include "llvm/Target/TargetOptions.h"
  48. #include "llvm/Transforms/CFGuard.h"
  49. #include "llvm/Transforms/Scalar.h"
  50. #include <cassert>
  51. #include <memory>
  52. #include <string>
  53. using namespace llvm;
  54. static cl::opt<bool>
  55. DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
  56. cl::desc("Inhibit optimization of S->D register accesses on A15"),
  57. cl::init(false));
  58. static cl::opt<bool>
  59. EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
  60. cl::desc("Run SimplifyCFG after expanding atomic operations"
  61. " to make use of cmpxchg flow-based information"),
  62. cl::init(true));
  63. static cl::opt<bool>
  64. EnableARMLoadStoreOpt("arm-load-store-opt", cl::Hidden,
  65. cl::desc("Enable ARM load/store optimization pass"),
  66. cl::init(true));
  67. // FIXME: Unify control over GlobalMerge.
  68. static cl::opt<cl::boolOrDefault>
  69. EnableGlobalMerge("arm-global-merge", cl::Hidden,
  70. cl::desc("Enable the global merge pass"));
  71. namespace llvm {
  72. void initializeARMExecutionDomainFixPass(PassRegistry&);
  73. }
  74. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTarget() {
  75. // Register the target.
  76. RegisterTargetMachine<ARMLETargetMachine> X(getTheARMLETarget());
  77. RegisterTargetMachine<ARMLETargetMachine> A(getTheThumbLETarget());
  78. RegisterTargetMachine<ARMBETargetMachine> Y(getTheARMBETarget());
  79. RegisterTargetMachine<ARMBETargetMachine> B(getTheThumbBETarget());
  80. PassRegistry &Registry = *PassRegistry::getPassRegistry();
  81. initializeGlobalISel(Registry);
  82. initializeARMLoadStoreOptPass(Registry);
  83. initializeARMPreAllocLoadStoreOptPass(Registry);
  84. initializeARMParallelDSPPass(Registry);
  85. initializeARMConstantIslandsPass(Registry);
  86. initializeARMExecutionDomainFixPass(Registry);
  87. initializeARMExpandPseudoPass(Registry);
  88. initializeThumb2SizeReducePass(Registry);
  89. initializeMVEVPTBlockPass(Registry);
  90. initializeMVEVPTOptimisationsPass(Registry);
  91. initializeMVETailPredicationPass(Registry);
  92. initializeARMLowOverheadLoopsPass(Registry);
  93. initializeARMBlockPlacementPass(Registry);
  94. initializeMVEGatherScatterLoweringPass(Registry);
  95. initializeARMSLSHardeningPass(Registry);
  96. }
  97. static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
  98. if (TT.isOSBinFormatMachO())
  99. return std::make_unique<TargetLoweringObjectFileMachO>();
  100. if (TT.isOSWindows())
  101. return std::make_unique<TargetLoweringObjectFileCOFF>();
  102. return std::make_unique<ARMElfTargetObjectFile>();
  103. }
  104. static ARMBaseTargetMachine::ARMABI
  105. computeTargetABI(const Triple &TT, StringRef CPU,
  106. const TargetOptions &Options) {
  107. StringRef ABIName = Options.MCOptions.getABIName();
  108. if (ABIName.empty())
  109. ABIName = ARM::computeDefaultTargetABI(TT, CPU);
  110. if (ABIName == "aapcs16")
  111. return ARMBaseTargetMachine::ARM_ABI_AAPCS16;
  112. else if (ABIName.startswith("aapcs"))
  113. return ARMBaseTargetMachine::ARM_ABI_AAPCS;
  114. else if (ABIName.startswith("apcs"))
  115. return ARMBaseTargetMachine::ARM_ABI_APCS;
  116. llvm_unreachable("Unhandled/unknown ABI Name!");
  117. return ARMBaseTargetMachine::ARM_ABI_UNKNOWN;
  118. }
  119. static std::string computeDataLayout(const Triple &TT, StringRef CPU,
  120. const TargetOptions &Options,
  121. bool isLittle) {
  122. auto ABI = computeTargetABI(TT, CPU, Options);
  123. std::string Ret;
  124. if (isLittle)
  125. // Little endian.
  126. Ret += "e";
  127. else
  128. // Big endian.
  129. Ret += "E";
  130. Ret += DataLayout::getManglingComponent(TT);
  131. // Pointers are 32 bits and aligned to 32 bits.
  132. Ret += "-p:32:32";
  133. // Function pointers are aligned to 8 bits (because the LSB stores the
  134. // ARM/Thumb state).
  135. Ret += "-Fi8";
  136. // ABIs other than APCS have 64 bit integers with natural alignment.
  137. if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS)
  138. Ret += "-i64:64";
  139. // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
  140. // bits, others to 64 bits. We always try to align to 64 bits.
  141. if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
  142. Ret += "-f64:32:64";
  143. // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
  144. // to 64. We always ty to give them natural alignment.
  145. if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
  146. Ret += "-v64:32:64-v128:32:128";
  147. else if (ABI != ARMBaseTargetMachine::ARM_ABI_AAPCS16)
  148. Ret += "-v128:64:128";
  149. // Try to align aggregates to 32 bits (the default is 64 bits, which has no
  150. // particular hardware support on 32-bit ARM).
  151. Ret += "-a:0:32";
  152. // Integer registers are 32 bits.
  153. Ret += "-n32";
  154. // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
  155. // aligned everywhere else.
  156. if (TT.isOSNaCl() || ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS16)
  157. Ret += "-S128";
  158. else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS)
  159. Ret += "-S64";
  160. else
  161. Ret += "-S32";
  162. return Ret;
  163. }
  164. static Reloc::Model getEffectiveRelocModel(const Triple &TT,
  165. Optional<Reloc::Model> RM) {
  166. if (!RM.hasValue())
  167. // Default relocation model on Darwin is PIC.
  168. return TT.isOSBinFormatMachO() ? Reloc::PIC_ : Reloc::Static;
  169. if (*RM == Reloc::ROPI || *RM == Reloc::RWPI || *RM == Reloc::ROPI_RWPI)
  170. assert(TT.isOSBinFormatELF() &&
  171. "ROPI/RWPI currently only supported for ELF");
  172. // DynamicNoPIC is only used on darwin.
  173. if (*RM == Reloc::DynamicNoPIC && !TT.isOSDarwin())
  174. return Reloc::Static;
  175. return *RM;
  176. }
  177. /// Create an ARM architecture model.
  178. ///
  179. ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
  180. StringRef CPU, StringRef FS,
  181. const TargetOptions &Options,
  182. Optional<Reloc::Model> RM,
  183. Optional<CodeModel::Model> CM,
  184. CodeGenOpt::Level OL, bool isLittle)
  185. : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
  186. CPU, FS, Options, getEffectiveRelocModel(TT, RM),
  187. getEffectiveCodeModel(CM, CodeModel::Small), OL),
  188. TargetABI(computeTargetABI(TT, CPU, Options)),
  189. TLOF(createTLOF(getTargetTriple())), isLittle(isLittle) {
  190. // Default to triple-appropriate float ABI
  191. if (Options.FloatABIType == FloatABI::Default) {
  192. if (isTargetHardFloat())
  193. this->Options.FloatABIType = FloatABI::Hard;
  194. else
  195. this->Options.FloatABIType = FloatABI::Soft;
  196. }
  197. // Default to triple-appropriate EABI
  198. if (Options.EABIVersion == EABI::Default ||
  199. Options.EABIVersion == EABI::Unknown) {
  200. // musl is compatible with glibc with regard to EABI version
  201. if ((TargetTriple.getEnvironment() == Triple::GNUEABI ||
  202. TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
  203. TargetTriple.getEnvironment() == Triple::MuslEABI ||
  204. TargetTriple.getEnvironment() == Triple::MuslEABIHF) &&
  205. !(TargetTriple.isOSWindows() || TargetTriple.isOSDarwin()))
  206. this->Options.EABIVersion = EABI::GNU;
  207. else
  208. this->Options.EABIVersion = EABI::EABI5;
  209. }
  210. if (TT.isOSBinFormatMachO()) {
  211. this->Options.TrapUnreachable = true;
  212. this->Options.NoTrapAfterNoreturn = true;
  213. }
  214. // ARM supports the debug entry values.
  215. setSupportsDebugEntryValues(true);
  216. initAsmInfo();
  217. // ARM supports the MachineOutliner.
  218. setMachineOutliner(true);
  219. setSupportsDefaultOutlining(true);
  220. }
  221. ARMBaseTargetMachine::~ARMBaseTargetMachine() = default;
  222. const ARMSubtarget *
  223. ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
  224. Attribute CPUAttr = F.getFnAttribute("target-cpu");
  225. Attribute FSAttr = F.getFnAttribute("target-features");
  226. std::string CPU =
  227. CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
  228. std::string FS =
  229. FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
  230. // FIXME: This is related to the code below to reset the target options,
  231. // we need to know whether or not the soft float flag is set on the
  232. // function before we can generate a subtarget. We also need to use
  233. // it as a key for the subtarget since that can be the only difference
  234. // between two functions.
  235. bool SoftFloat =
  236. F.getFnAttribute("use-soft-float").getValueAsString() == "true";
  237. // If the soft float attribute is set on the function turn on the soft float
  238. // subtarget feature.
  239. if (SoftFloat)
  240. FS += FS.empty() ? "+soft-float" : ",+soft-float";
  241. // Use the optminsize to identify the subtarget, but don't use it in the
  242. // feature string.
  243. std::string Key = CPU + FS;
  244. if (F.hasMinSize())
  245. Key += "+minsize";
  246. auto &I = SubtargetMap[Key];
  247. if (!I) {
  248. // This needs to be done before we create a new subtarget since any
  249. // creation will depend on the TM and the code generation flags on the
  250. // function that reside in TargetOptions.
  251. resetTargetOptions(F);
  252. I = std::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle,
  253. F.hasMinSize());
  254. if (!I->isThumb() && !I->hasARMOps())
  255. F.getContext().emitError("Function '" + F.getName() + "' uses ARM "
  256. "instructions, but the target does not support ARM mode execution.");
  257. }
  258. return I.get();
  259. }
  260. TargetTransformInfo
  261. ARMBaseTargetMachine::getTargetTransformInfo(const Function &F) {
  262. return TargetTransformInfo(ARMTTIImpl(this, F));
  263. }
  264. ARMLETargetMachine::ARMLETargetMachine(const Target &T, const Triple &TT,
  265. StringRef CPU, StringRef FS,
  266. const TargetOptions &Options,
  267. Optional<Reloc::Model> RM,
  268. Optional<CodeModel::Model> CM,
  269. CodeGenOpt::Level OL, bool JIT)
  270. : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
  271. ARMBETargetMachine::ARMBETargetMachine(const Target &T, const Triple &TT,
  272. StringRef CPU, StringRef FS,
  273. const TargetOptions &Options,
  274. Optional<Reloc::Model> RM,
  275. Optional<CodeModel::Model> CM,
  276. CodeGenOpt::Level OL, bool JIT)
  277. : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
  278. namespace {
  279. /// ARM Code Generator Pass Configuration Options.
  280. class ARMPassConfig : public TargetPassConfig {
  281. public:
  282. ARMPassConfig(ARMBaseTargetMachine &TM, PassManagerBase &PM)
  283. : TargetPassConfig(TM, PM) {}
  284. ARMBaseTargetMachine &getARMTargetMachine() const {
  285. return getTM<ARMBaseTargetMachine>();
  286. }
  287. ScheduleDAGInstrs *
  288. createMachineScheduler(MachineSchedContext *C) const override {
  289. ScheduleDAGMILive *DAG = createGenericSchedLive(C);
  290. // add DAG Mutations here.
  291. const ARMSubtarget &ST = C->MF->getSubtarget<ARMSubtarget>();
  292. if (ST.hasFusion())
  293. DAG->addMutation(createARMMacroFusionDAGMutation());
  294. return DAG;
  295. }
  296. ScheduleDAGInstrs *
  297. createPostMachineScheduler(MachineSchedContext *C) const override {
  298. ScheduleDAGMI *DAG = createGenericSchedPostRA(C);
  299. // add DAG Mutations here.
  300. const ARMSubtarget &ST = C->MF->getSubtarget<ARMSubtarget>();
  301. if (ST.hasFusion())
  302. DAG->addMutation(createARMMacroFusionDAGMutation());
  303. return DAG;
  304. }
  305. void addIRPasses() override;
  306. void addCodeGenPrepare() override;
  307. bool addPreISel() override;
  308. bool addInstSelector() override;
  309. bool addIRTranslator() override;
  310. bool addLegalizeMachineIR() override;
  311. bool addRegBankSelect() override;
  312. bool addGlobalInstructionSelect() override;
  313. void addPreRegAlloc() override;
  314. void addPreSched2() override;
  315. void addPreEmitPass() override;
  316. void addPreEmitPass2() override;
  317. std::unique_ptr<CSEConfigBase> getCSEConfig() const override;
  318. };
  319. class ARMExecutionDomainFix : public ExecutionDomainFix {
  320. public:
  321. static char ID;
  322. ARMExecutionDomainFix() : ExecutionDomainFix(ID, ARM::DPRRegClass) {}
  323. StringRef getPassName() const override {
  324. return "ARM Execution Domain Fix";
  325. }
  326. };
  327. char ARMExecutionDomainFix::ID;
  328. } // end anonymous namespace
  329. INITIALIZE_PASS_BEGIN(ARMExecutionDomainFix, "arm-execution-domain-fix",
  330. "ARM Execution Domain Fix", false, false)
  331. INITIALIZE_PASS_DEPENDENCY(ReachingDefAnalysis)
  332. INITIALIZE_PASS_END(ARMExecutionDomainFix, "arm-execution-domain-fix",
  333. "ARM Execution Domain Fix", false, false)
  334. TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
  335. return new ARMPassConfig(*this, PM);
  336. }
  337. std::unique_ptr<CSEConfigBase> ARMPassConfig::getCSEConfig() const {
  338. return getStandardCSEConfigForOpt(TM->getOptLevel());
  339. }
  340. void ARMPassConfig::addIRPasses() {
  341. if (TM->Options.ThreadModel == ThreadModel::Single)
  342. addPass(createLowerAtomicPass());
  343. else
  344. addPass(createAtomicExpandPass());
  345. // Cmpxchg instructions are often used with a subsequent comparison to
  346. // determine whether it succeeded. We can exploit existing control-flow in
  347. // ldrex/strex loops to simplify this, but it needs tidying up.
  348. if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
  349. addPass(createCFGSimplificationPass(
  350. SimplifyCFGOptions().hoistCommonInsts(true).sinkCommonInsts(true),
  351. [this](const Function &F) {
  352. const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
  353. return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
  354. }));
  355. addPass(createMVEGatherScatterLoweringPass());
  356. TargetPassConfig::addIRPasses();
  357. // Run the parallel DSP pass.
  358. if (getOptLevel() == CodeGenOpt::Aggressive)
  359. addPass(createARMParallelDSPPass());
  360. // Match interleaved memory accesses to ldN/stN intrinsics.
  361. if (TM->getOptLevel() != CodeGenOpt::None)
  362. addPass(createInterleavedAccessPass());
  363. // Add Control Flow Guard checks.
  364. if (TM->getTargetTriple().isOSWindows())
  365. addPass(createCFGuardCheckPass());
  366. }
  367. void ARMPassConfig::addCodeGenPrepare() {
  368. if (getOptLevel() != CodeGenOpt::None)
  369. addPass(createTypePromotionPass());
  370. TargetPassConfig::addCodeGenPrepare();
  371. }
  372. bool ARMPassConfig::addPreISel() {
  373. if ((TM->getOptLevel() != CodeGenOpt::None &&
  374. EnableGlobalMerge == cl::BOU_UNSET) ||
  375. EnableGlobalMerge == cl::BOU_TRUE) {
  376. // FIXME: This is using the thumb1 only constant value for
  377. // maximal global offset for merging globals. We may want
  378. // to look into using the old value for non-thumb1 code of
  379. // 4095 based on the TargetMachine, but this starts to become
  380. // tricky when doing code gen per function.
  381. bool OnlyOptimizeForSize = (TM->getOptLevel() < CodeGenOpt::Aggressive) &&
  382. (EnableGlobalMerge == cl::BOU_UNSET);
  383. // Merging of extern globals is enabled by default on non-Mach-O as we
  384. // expect it to be generally either beneficial or harmless. On Mach-O it
  385. // is disabled as we emit the .subsections_via_symbols directive which
  386. // means that merging extern globals is not safe.
  387. bool MergeExternalByDefault = !TM->getTargetTriple().isOSBinFormatMachO();
  388. addPass(createGlobalMergePass(TM, 127, OnlyOptimizeForSize,
  389. MergeExternalByDefault));
  390. }
  391. if (TM->getOptLevel() != CodeGenOpt::None) {
  392. addPass(createHardwareLoopsPass());
  393. addPass(createMVETailPredicationPass());
  394. }
  395. return false;
  396. }
  397. bool ARMPassConfig::addInstSelector() {
  398. addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
  399. return false;
  400. }
  401. bool ARMPassConfig::addIRTranslator() {
  402. addPass(new IRTranslator(getOptLevel()));
  403. return false;
  404. }
  405. bool ARMPassConfig::addLegalizeMachineIR() {
  406. addPass(new Legalizer());
  407. return false;
  408. }
  409. bool ARMPassConfig::addRegBankSelect() {
  410. addPass(new RegBankSelect());
  411. return false;
  412. }
  413. bool ARMPassConfig::addGlobalInstructionSelect() {
  414. addPass(new InstructionSelect());
  415. return false;
  416. }
  417. void ARMPassConfig::addPreRegAlloc() {
  418. if (getOptLevel() != CodeGenOpt::None) {
  419. addPass(createMVEVPTOptimisationsPass());
  420. addPass(createMLxExpansionPass());
  421. if (EnableARMLoadStoreOpt)
  422. addPass(createARMLoadStoreOptimizationPass(/* pre-register alloc */ true));
  423. if (!DisableA15SDOptimization)
  424. addPass(createA15SDOptimizerPass());
  425. }
  426. }
  427. void ARMPassConfig::addPreSched2() {
  428. if (getOptLevel() != CodeGenOpt::None) {
  429. if (EnableARMLoadStoreOpt)
  430. addPass(createARMLoadStoreOptimizationPass());
  431. addPass(new ARMExecutionDomainFix());
  432. addPass(createBreakFalseDeps());
  433. }
  434. // Expand some pseudo instructions into multiple instructions to allow
  435. // proper scheduling.
  436. addPass(createARMExpandPseudoPass());
  437. if (getOptLevel() != CodeGenOpt::None) {
  438. // When optimising for size, always run the Thumb2SizeReduction pass before
  439. // IfConversion. Otherwise, check whether IT blocks are restricted
  440. // (e.g. in v8, IfConversion depends on Thumb instruction widths)
  441. addPass(createThumb2SizeReductionPass([this](const Function &F) {
  442. return this->TM->getSubtarget<ARMSubtarget>(F).hasMinSize() ||
  443. this->TM->getSubtarget<ARMSubtarget>(F).restrictIT();
  444. }));
  445. addPass(createIfConverter([](const MachineFunction &MF) {
  446. return !MF.getSubtarget<ARMSubtarget>().isThumb1Only();
  447. }));
  448. }
  449. addPass(createMVEVPTBlockPass());
  450. addPass(createThumb2ITBlockPass());
  451. // Add both scheduling passes to give the subtarget an opportunity to pick
  452. // between them.
  453. if (getOptLevel() != CodeGenOpt::None) {
  454. addPass(&PostMachineSchedulerID);
  455. addPass(&PostRASchedulerID);
  456. }
  457. addPass(createARMIndirectThunks());
  458. addPass(createARMSLSHardeningPass());
  459. }
  460. void ARMPassConfig::addPreEmitPass() {
  461. addPass(createThumb2SizeReductionPass());
  462. // Constant island pass work on unbundled instructions.
  463. addPass(createUnpackMachineBundles([](const MachineFunction &MF) {
  464. return MF.getSubtarget<ARMSubtarget>().isThumb2();
  465. }));
  466. // Don't optimize barriers or block placement at -O0.
  467. if (getOptLevel() != CodeGenOpt::None) {
  468. addPass(createARMBlockPlacementPass());
  469. addPass(createARMOptimizeBarriersPass());
  470. }
  471. }
  472. void ARMPassConfig::addPreEmitPass2() {
  473. addPass(createARMConstantIslandPass());
  474. addPass(createARMLowOverheadLoopsPass());
  475. // Identify valid longjmp targets for Windows Control Flow Guard.
  476. if (TM->getTargetTriple().isOSWindows())
  477. addPass(createCFGuardLongjmpPass());
  478. }