1 //===-- AArch64TargetMachine.cpp - Define TargetMachine for AArch64 -------===// 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 "AArch64.h" 14 #include "AArch64TargetMachine.h" 15 #include "llvm/CodeGen/Passes.h" 16 #include "llvm/CodeGen/RegAllocRegistry.h" 17 #include "llvm/IR/Function.h" 18 #include "llvm/PassManager.h" 19 #include "llvm/Support/CommandLine.h" 20 #include "llvm/Support/TargetRegistry.h" 21 #include "llvm/Target/TargetOptions.h" 22 #include "llvm/Transforms/Scalar.h" 23 using namespace llvm; 24 25 static cl::opt<bool> 26 EnableCCMP("aarch64-ccmp", cl::desc("Enable the CCMP formation pass"), 27 cl::init(true), cl::Hidden); 28 29 static cl::opt<bool> EnableMCR("aarch64-mcr", 30 cl::desc("Enable the machine combiner pass"), 31 cl::init(true), cl::Hidden); 32 33 static cl::opt<bool> 34 EnableStPairSuppress("aarch64-stp-suppress", cl::desc("Suppress STP for AArch64"), 35 cl::init(true), cl::Hidden); 36 37 static cl::opt<bool> 38 EnableAdvSIMDScalar("aarch64-simd-scalar", cl::desc("Enable use of AdvSIMD scalar" 39 " integer instructions"), cl::init(false), cl::Hidden); 40 41 static cl::opt<bool> 42 EnablePromoteConstant("aarch64-promote-const", cl::desc("Enable the promote " 43 "constant pass"), cl::init(true), cl::Hidden); 44 45 static cl::opt<bool> 46 EnableCollectLOH("aarch64-collect-loh", cl::desc("Enable the pass that emits the" 47 " linker optimization hints (LOH)"), cl::init(true), 48 cl::Hidden); 49 50 static cl::opt<bool> 51 EnableDeadRegisterElimination("aarch64-dead-def-elimination", cl::Hidden, 52 cl::desc("Enable the pass that removes dead" 53 " definitons and replaces stores to" 54 " them with stores to the zero" 55 " register"), 56 cl::init(true)); 57 58 static cl::opt<bool> 59 EnableLoadStoreOpt("aarch64-load-store-opt", cl::desc("Enable the load/store pair" 60 " optimization pass"), cl::init(true), cl::Hidden); 61 62 static cl::opt<bool> 63 EnableAtomicTidy("aarch64-atomic-cfg-tidy", cl::Hidden, 64 cl::desc("Run SimplifyCFG after expanding atomic operations" 65 " to make use of cmpxchg flow-based information"), 66 cl::init(true)); 67 68 static cl::opt<bool> 69 EnableEarlyIfConversion("aarch64-enable-early-ifcvt", cl::Hidden, 70 cl::desc("Run early if-conversion"), 71 cl::init(true)); 72 73 static cl::opt<bool> 74 EnableCondOpt("aarch64-condopt", 75 cl::desc("Enable the condition optimizer pass"), 76 cl::init(true), cl::Hidden); 77 78 static cl::opt<bool> 79 EnablePBQP("aarch64-pbqp", cl::Hidden, 80 cl::desc("Use PBQP register allocator (experimental)"), 81 cl::init(false)); 82 83 extern "C" void LLVMInitializeAArch64Target() { 84 // Register the target. 85 RegisterTargetMachine<AArch64leTargetMachine> X(TheAArch64leTarget); 86 RegisterTargetMachine<AArch64beTargetMachine> Y(TheAArch64beTarget); 87 RegisterTargetMachine<AArch64leTargetMachine> Z(TheARM64Target); 88 } 89 90 /// TargetMachine ctor - Create an AArch64 architecture model. 91 /// 92 AArch64TargetMachine::AArch64TargetMachine(const Target &T, StringRef TT, 93 StringRef CPU, StringRef FS, 94 const TargetOptions &Options, 95 Reloc::Model RM, CodeModel::Model CM, 96 CodeGenOpt::Level OL, 97 bool LittleEndian) 98 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 99 Subtarget(TT, CPU, FS, *this, LittleEndian), isLittle(LittleEndian), 100 usingPBQP(false) { 101 initAsmInfo(); 102 103 if (EnablePBQP && Subtarget.isCortexA57() && OL != CodeGenOpt::None) { 104 usingPBQP = true; 105 RegisterRegAlloc::setDefault(createAArch64A57PBQPRegAlloc); 106 } 107 } 108 109 const AArch64Subtarget * 110 AArch64TargetMachine::getSubtargetImpl(const Function &F) const { 111 AttributeSet FnAttrs = F.getAttributes(); 112 Attribute CPUAttr = 113 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu"); 114 Attribute FSAttr = 115 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features"); 116 117 std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 118 ? CPUAttr.getValueAsString().str() 119 : TargetCPU; 120 std::string FS = !FSAttr.hasAttribute(Attribute::None) 121 ? FSAttr.getValueAsString().str() 122 : TargetFS; 123 124 auto &I = SubtargetMap[CPU + FS]; 125 if (!I) { 126 // This needs to be done before we create a new subtarget since any 127 // creation will depend on the TM and the code generation flags on the 128 // function that reside in TargetOptions. 129 resetTargetOptions(F); 130 I = llvm::make_unique<AArch64Subtarget>(TargetTriple, CPU, FS, *this, isLittle); 131 } 132 return I.get(); 133 } 134 135 void AArch64leTargetMachine::anchor() { } 136 137 AArch64leTargetMachine:: 138 AArch64leTargetMachine(const Target &T, StringRef TT, 139 StringRef CPU, StringRef FS, const TargetOptions &Options, 140 Reloc::Model RM, CodeModel::Model CM, 141 CodeGenOpt::Level OL) 142 : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 143 144 void AArch64beTargetMachine::anchor() { } 145 146 AArch64beTargetMachine:: 147 AArch64beTargetMachine(const Target &T, StringRef TT, 148 StringRef CPU, StringRef FS, const TargetOptions &Options, 149 Reloc::Model RM, CodeModel::Model CM, 150 CodeGenOpt::Level OL) 151 : AArch64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 152 153 namespace { 154 /// AArch64 Code Generator Pass Configuration Options. 155 class AArch64PassConfig : public TargetPassConfig { 156 public: 157 AArch64PassConfig(AArch64TargetMachine *TM, PassManagerBase &PM) 158 : TargetPassConfig(TM, PM) { 159 if (TM->getOptLevel() != CodeGenOpt::None) 160 substitutePass(&PostRASchedulerID, &PostMachineSchedulerID); 161 } 162 163 AArch64TargetMachine &getAArch64TargetMachine() const { 164 return getTM<AArch64TargetMachine>(); 165 } 166 167 void addIRPasses() override; 168 bool addPreISel() override; 169 bool addInstSelector() override; 170 bool addILPOpts() override; 171 bool addPreRegAlloc() override; 172 bool addPostRegAlloc() override; 173 bool addPreSched2() override; 174 bool addPreEmitPass() override; 175 }; 176 } // namespace 177 178 void AArch64TargetMachine::addAnalysisPasses(PassManagerBase &PM) { 179 // Add first the target-independent BasicTTI pass, then our AArch64 pass. This 180 // allows the AArch64 pass to delegate to the target independent layer when 181 // appropriate. 182 PM.add(createBasicTargetTransformInfoPass(this)); 183 PM.add(createAArch64TargetTransformInfoPass(this)); 184 } 185 186 TargetPassConfig *AArch64TargetMachine::createPassConfig(PassManagerBase &PM) { 187 return new AArch64PassConfig(this, PM); 188 } 189 190 void AArch64PassConfig::addIRPasses() { 191 // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg 192 // ourselves. 193 addPass(createAtomicExpandPass(TM)); 194 195 // Cmpxchg instructions are often used with a subsequent comparison to 196 // determine whether it succeeded. We can exploit existing control-flow in 197 // ldrex/strex loops to simplify this, but it needs tidying up. 198 if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) 199 addPass(createCFGSimplificationPass()); 200 201 TargetPassConfig::addIRPasses(); 202 } 203 204 // Pass Pipeline Configuration 205 bool AArch64PassConfig::addPreISel() { 206 // Run promote constant before global merge, so that the promoted constants 207 // get a chance to be merged 208 if (TM->getOptLevel() != CodeGenOpt::None && EnablePromoteConstant) 209 addPass(createAArch64PromoteConstantPass()); 210 if (TM->getOptLevel() != CodeGenOpt::None) 211 addPass(createGlobalMergePass(TM)); 212 if (TM->getOptLevel() != CodeGenOpt::None) 213 addPass(createAArch64AddressTypePromotionPass()); 214 215 return false; 216 } 217 218 bool AArch64PassConfig::addInstSelector() { 219 addPass(createAArch64ISelDag(getAArch64TargetMachine(), getOptLevel())); 220 221 // For ELF, cleanup any local-dynamic TLS accesses (i.e. combine as many 222 // references to _TLS_MODULE_BASE_ as possible. 223 if (TM->getSubtarget<AArch64Subtarget>().isTargetELF() && 224 getOptLevel() != CodeGenOpt::None) 225 addPass(createAArch64CleanupLocalDynamicTLSPass()); 226 227 return false; 228 } 229 230 bool AArch64PassConfig::addILPOpts() { 231 if (EnableCondOpt) 232 addPass(createAArch64ConditionOptimizerPass()); 233 if (EnableCCMP) 234 addPass(createAArch64ConditionalCompares()); 235 if (EnableMCR) 236 addPass(&MachineCombinerID); 237 if (EnableEarlyIfConversion) 238 addPass(&EarlyIfConverterID); 239 if (EnableStPairSuppress) 240 addPass(createAArch64StorePairSuppressPass()); 241 return true; 242 } 243 244 bool AArch64PassConfig::addPreRegAlloc() { 245 // Use AdvSIMD scalar instructions whenever profitable. 246 if (TM->getOptLevel() != CodeGenOpt::None && EnableAdvSIMDScalar) { 247 addPass(createAArch64AdvSIMDScalar()); 248 // The AdvSIMD pass may produce copies that can be rewritten to 249 // be register coaleascer friendly. 250 addPass(&PeepholeOptimizerID); 251 } 252 return true; 253 } 254 255 bool AArch64PassConfig::addPostRegAlloc() { 256 // Change dead register definitions to refer to the zero register. 257 if (TM->getOptLevel() != CodeGenOpt::None && EnableDeadRegisterElimination) 258 addPass(createAArch64DeadRegisterDefinitions()); 259 if (TM->getOptLevel() != CodeGenOpt::None && 260 TM->getSubtarget<AArch64Subtarget>().isCortexA57() && 261 !static_cast<const AArch64TargetMachine *>(TM)->isPBQPUsed()) 262 // Improve performance for some FP/SIMD code for A57. 263 addPass(createAArch64A57FPLoadBalancing()); 264 return true; 265 } 266 267 bool AArch64PassConfig::addPreSched2() { 268 // Expand some pseudo instructions to allow proper scheduling. 269 addPass(createAArch64ExpandPseudoPass()); 270 // Use load/store pair instructions when possible. 271 if (TM->getOptLevel() != CodeGenOpt::None && EnableLoadStoreOpt) 272 addPass(createAArch64LoadStoreOptimizationPass()); 273 return true; 274 } 275 276 bool AArch64PassConfig::addPreEmitPass() { 277 // Relax conditional branch instructions if they're otherwise out of 278 // range of their destination. 279 addPass(createAArch64BranchRelaxation()); 280 if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH && 281 TM->getSubtarget<AArch64Subtarget>().isTargetMachO()) 282 addPass(createAArch64CollectLOHPass()); 283 return true; 284 } 285