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 "ARMFrameLowering.h" 15 #include "ARMTargetMachine.h" 16 #include "ARMTargetObjectFile.h" 17 #include "ARMTargetTransformInfo.h" 18 #include "llvm/CodeGen/Passes.h" 19 #include "llvm/IR/Function.h" 20 #include "llvm/MC/MCAsmInfo.h" 21 #include "llvm/PassManager.h" 22 #include "llvm/Support/CommandLine.h" 23 #include "llvm/Support/FormattedStream.h" 24 #include "llvm/Support/TargetRegistry.h" 25 #include "llvm/Target/TargetOptions.h" 26 #include "llvm/Transforms/Scalar.h" 27 using namespace llvm; 28 29 static cl::opt<bool> 30 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden, 31 cl::desc("Inhibit optimization of S->D register accesses on A15"), 32 cl::init(false)); 33 34 static cl::opt<bool> 35 EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden, 36 cl::desc("Run SimplifyCFG after expanding atomic operations" 37 " to make use of cmpxchg flow-based information"), 38 cl::init(true)); 39 40 extern "C" void LLVMInitializeARMTarget() { 41 // Register the target. 42 RegisterTargetMachine<ARMLETargetMachine> X(TheARMLETarget); 43 RegisterTargetMachine<ARMBETargetMachine> Y(TheARMBETarget); 44 RegisterTargetMachine<ThumbLETargetMachine> A(TheThumbLETarget); 45 RegisterTargetMachine<ThumbBETargetMachine> B(TheThumbBETarget); 46 } 47 48 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) { 49 if (TT.isOSBinFormatMachO()) 50 return make_unique<TargetLoweringObjectFileMachO>(); 51 if (TT.isOSWindows()) 52 return make_unique<TargetLoweringObjectFileCOFF>(); 53 return make_unique<ARMElfTargetObjectFile>(); 54 } 55 56 static ARMBaseTargetMachine::ARMABI 57 computeTargetABI(const Triple &TT, StringRef CPU, 58 const TargetOptions &Options) { 59 if (Options.MCOptions.getABIName().startswith("aapcs")) 60 return ARMBaseTargetMachine::ARM_ABI_AAPCS; 61 else if (Options.MCOptions.getABIName().startswith("apcs")) 62 return ARMBaseTargetMachine::ARM_ABI_APCS; 63 64 assert(Options.MCOptions.getABIName().empty() && 65 "Unknown target-abi option!"); 66 67 ARMBaseTargetMachine::ARMABI TargetABI = 68 ARMBaseTargetMachine::ARM_ABI_UNKNOWN; 69 70 // FIXME: This is duplicated code from the front end and should be unified. 71 if (TT.isOSBinFormatMachO()) { 72 if (TT.getEnvironment() == llvm::Triple::EABI || 73 (TT.getOS() == llvm::Triple::UnknownOS && 74 TT.getObjectFormat() == llvm::Triple::MachO) || 75 CPU.startswith("cortex-m")) { 76 TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS; 77 } else { 78 TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS; 79 } 80 } else if (TT.isOSWindows()) { 81 // FIXME: this is invalid for WindowsCE 82 TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS; 83 } else { 84 // Select the default based on the platform. 85 switch (TT.getEnvironment()) { 86 case llvm::Triple::Android: 87 case llvm::Triple::GNUEABI: 88 case llvm::Triple::GNUEABIHF: 89 case llvm::Triple::EABIHF: 90 case llvm::Triple::EABI: 91 TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS; 92 break; 93 case llvm::Triple::GNU: 94 TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS; 95 break; 96 default: 97 if (TT.getOS() == llvm::Triple::NetBSD) 98 TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS; 99 else 100 TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS; 101 break; 102 } 103 } 104 105 return TargetABI; 106 } 107 108 static std::string computeDataLayout(const Triple &TT, 109 ARMBaseTargetMachine::ARMABI ABI, 110 bool isLittle) { 111 std::string Ret = ""; 112 113 if (isLittle) 114 // Little endian. 115 Ret += "e"; 116 else 117 // Big endian. 118 Ret += "E"; 119 120 Ret += DataLayout::getManglingComponent(TT); 121 122 // Pointers are 32 bits and aligned to 32 bits. 123 Ret += "-p:32:32"; 124 125 // ABIs other than APCS have 64 bit integers with natural alignment. 126 if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS) 127 Ret += "-i64:64"; 128 129 // We have 64 bits floats. The APCS ABI requires them to be aligned to 32 130 // bits, others to 64 bits. We always try to align to 64 bits. 131 if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS) 132 Ret += "-f64:32:64"; 133 134 // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others 135 // to 64. We always ty to give them natural alignment. 136 if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS) 137 Ret += "-v64:32:64-v128:32:128"; 138 else 139 Ret += "-v128:64:128"; 140 141 // Try to align aggregates to 32 bits (the default is 64 bits, which has no 142 // particular hardware support on 32-bit ARM). 143 Ret += "-a:0:32"; 144 145 // Integer registers are 32 bits. 146 Ret += "-n32"; 147 148 // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit 149 // aligned everywhere else. 150 if (TT.isOSNaCl()) 151 Ret += "-S128"; 152 else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS) 153 Ret += "-S64"; 154 else 155 Ret += "-S32"; 156 157 return Ret; 158 } 159 160 /// TargetMachine ctor - Create an ARM architecture model. 161 /// 162 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT, 163 StringRef CPU, StringRef FS, 164 const TargetOptions &Options, 165 Reloc::Model RM, CodeModel::Model CM, 166 CodeGenOpt::Level OL, bool isLittle) 167 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 168 TargetABI(computeTargetABI(Triple(TT), CPU, Options)), 169 DL(computeDataLayout(Triple(TT), TargetABI, isLittle)), 170 TLOF(createTLOF(Triple(getTargetTriple()))), 171 Subtarget(TT, CPU, FS, *this, isLittle), isLittle(isLittle) { 172 173 // Default to triple-appropriate float ABI 174 if (Options.FloatABIType == FloatABI::Default) 175 this->Options.FloatABIType = 176 Subtarget.isTargetHardFloat() ? FloatABI::Hard : FloatABI::Soft; 177 } 178 179 ARMBaseTargetMachine::~ARMBaseTargetMachine() {} 180 181 const ARMSubtarget * 182 ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const { 183 AttributeSet FnAttrs = F.getAttributes(); 184 Attribute CPUAttr = 185 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu"); 186 Attribute FSAttr = 187 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features"); 188 189 std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 190 ? CPUAttr.getValueAsString().str() 191 : TargetCPU; 192 std::string FS = !FSAttr.hasAttribute(Attribute::None) 193 ? FSAttr.getValueAsString().str() 194 : TargetFS; 195 196 // FIXME: This is related to the code below to reset the target options, 197 // we need to know whether or not the soft float flag is set on the 198 // function before we can generate a subtarget. We also need to use 199 // it as a key for the subtarget since that can be the only difference 200 // between two functions. 201 Attribute SFAttr = 202 FnAttrs.getAttribute(AttributeSet::FunctionIndex, "use-soft-float"); 203 bool SoftFloat = !SFAttr.hasAttribute(Attribute::None) 204 ? SFAttr.getValueAsString() == "true" 205 : Options.UseSoftFloat; 206 207 auto &I = SubtargetMap[CPU + FS + (SoftFloat ? "use-soft-float=true" 208 : "use-soft-float=false")]; 209 if (!I) { 210 // This needs to be done before we create a new subtarget since any 211 // creation will depend on the TM and the code generation flags on the 212 // function that reside in TargetOptions. 213 resetTargetOptions(F); 214 I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle); 215 } 216 return I.get(); 217 } 218 219 TargetIRAnalysis ARMBaseTargetMachine::getTargetIRAnalysis() { 220 return TargetIRAnalysis( 221 [this](Function &F) { return TargetTransformInfo(ARMTTIImpl(this, F)); }); 222 } 223 224 225 void ARMTargetMachine::anchor() { } 226 227 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU, 228 StringRef FS, const TargetOptions &Options, 229 Reloc::Model RM, CodeModel::Model CM, 230 CodeGenOpt::Level OL, bool isLittle) 231 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) { 232 initAsmInfo(); 233 if (!Subtarget.hasARMOps()) 234 report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not " 235 "support ARM mode execution!"); 236 } 237 238 void ARMLETargetMachine::anchor() { } 239 240 ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT, 241 StringRef CPU, StringRef FS, 242 const TargetOptions &Options, 243 Reloc::Model RM, CodeModel::Model CM, 244 CodeGenOpt::Level OL) 245 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 246 247 void ARMBETargetMachine::anchor() { } 248 249 ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT, 250 StringRef CPU, StringRef FS, 251 const TargetOptions &Options, 252 Reloc::Model RM, CodeModel::Model CM, 253 CodeGenOpt::Level OL) 254 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 255 256 void ThumbTargetMachine::anchor() { } 257 258 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, 259 StringRef CPU, StringRef FS, 260 const TargetOptions &Options, 261 Reloc::Model RM, CodeModel::Model CM, 262 CodeGenOpt::Level OL, bool isLittle) 263 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, 264 isLittle) { 265 initAsmInfo(); 266 } 267 268 void ThumbLETargetMachine::anchor() { } 269 270 ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT, 271 StringRef CPU, StringRef FS, 272 const TargetOptions &Options, 273 Reloc::Model RM, CodeModel::Model CM, 274 CodeGenOpt::Level OL) 275 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 276 277 void ThumbBETargetMachine::anchor() { } 278 279 ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT, 280 StringRef CPU, StringRef FS, 281 const TargetOptions &Options, 282 Reloc::Model RM, CodeModel::Model CM, 283 CodeGenOpt::Level OL) 284 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 285 286 namespace { 287 /// ARM Code Generator Pass Configuration Options. 288 class ARMPassConfig : public TargetPassConfig { 289 public: 290 ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM) 291 : TargetPassConfig(TM, PM) {} 292 293 ARMBaseTargetMachine &getARMTargetMachine() const { 294 return getTM<ARMBaseTargetMachine>(); 295 } 296 297 const ARMSubtarget &getARMSubtarget() const { 298 return *getARMTargetMachine().getSubtargetImpl(); 299 } 300 301 void addIRPasses() override; 302 bool addPreISel() override; 303 bool addInstSelector() override; 304 void addPreRegAlloc() override; 305 void addPreSched2() override; 306 void addPreEmitPass() override; 307 }; 308 } // namespace 309 310 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { 311 return new ARMPassConfig(this, PM); 312 } 313 314 void ARMPassConfig::addIRPasses() { 315 if (TM->Options.ThreadModel == ThreadModel::Single) 316 addPass(createLowerAtomicPass()); 317 else 318 addPass(createAtomicExpandPass(TM)); 319 320 // Cmpxchg instructions are often used with a subsequent comparison to 321 // determine whether it succeeded. We can exploit existing control-flow in 322 // ldrex/strex loops to simplify this, but it needs tidying up. 323 const ARMSubtarget *Subtarget = &getARMSubtarget(); 324 if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) 325 if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) 326 addPass(createCFGSimplificationPass()); 327 328 TargetPassConfig::addIRPasses(); 329 } 330 331 bool ARMPassConfig::addPreISel() { 332 if (TM->getOptLevel() != CodeGenOpt::None) 333 addPass(createGlobalMergePass(TM)); 334 335 return false; 336 } 337 338 bool ARMPassConfig::addInstSelector() { 339 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 340 341 const ARMSubtarget *Subtarget = &getARMSubtarget(); 342 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 343 TM->Options.EnableFastISel) 344 addPass(createARMGlobalBaseRegPass()); 345 return false; 346 } 347 348 void ARMPassConfig::addPreRegAlloc() { 349 if (getOptLevel() != CodeGenOpt::None) 350 addPass(createARMLoadStoreOptimizationPass(true)); 351 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 352 addPass(createMLxExpansionPass()); 353 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 354 // enabled when NEON is available. 355 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 356 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 357 addPass(createA15SDOptimizerPass()); 358 } 359 } 360 361 void ARMPassConfig::addPreSched2() { 362 if (getOptLevel() != CodeGenOpt::None) { 363 addPass(createARMLoadStoreOptimizationPass()); 364 365 if (getARMSubtarget().hasNEON()) 366 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 367 } 368 369 // Expand some pseudo instructions into multiple instructions to allow 370 // proper scheduling. 371 addPass(createARMExpandPseudoPass()); 372 373 if (getOptLevel() != CodeGenOpt::None) { 374 if (!getARMSubtarget().isThumb1Only()) { 375 // in v8, IfConversion depends on Thumb instruction widths 376 if (getARMSubtarget().restrictIT() && 377 !getARMSubtarget().prefers32BitThumb()) 378 addPass(createThumb2SizeReductionPass()); 379 addPass(&IfConverterID); 380 } 381 } 382 if (getARMSubtarget().isThumb2()) 383 addPass(createThumb2ITBlockPass()); 384 } 385 386 void ARMPassConfig::addPreEmitPass() { 387 if (getARMSubtarget().isThumb2()) { 388 if (!getARMSubtarget().prefers32BitThumb()) 389 addPass(createThumb2SizeReductionPass()); 390 391 // Constant island pass work on unbundled instructions. 392 addPass(&UnpackMachineBundlesID); 393 } 394 395 addPass(createARMOptimizeBarriersPass()); 396 addPass(createARMConstantIslandPass()); 397 } 398