ARMTargetMachine.cpp revision ebe69fe11e48d322045d5949c83283927a0d790b
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/IR/LegacyPassManager.h" 21#include "llvm/MC/MCAsmInfo.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" 27using namespace llvm; 28 29static cl::opt<bool> 30DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden, 31 cl::desc("Inhibit optimization of S->D register accesses on A15"), 32 cl::init(false)); 33 34static cl::opt<bool> 35EnableAtomicTidy("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 40extern "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 48static 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 56static ARMBaseTargetMachine::ARMABI 57computeTargetABI(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 108static 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/// 162ARMBaseTargetMachine::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 179ARMBaseTargetMachine::~ARMBaseTargetMachine() {} 180 181const ARMSubtarget * 182ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const { 183 Attribute CPUAttr = F.getFnAttribute("target-cpu"); 184 Attribute FSAttr = F.getFnAttribute("target-features"); 185 186 std::string CPU = !CPUAttr.hasAttribute(Attribute::None) 187 ? CPUAttr.getValueAsString().str() 188 : TargetCPU; 189 std::string FS = !FSAttr.hasAttribute(Attribute::None) 190 ? FSAttr.getValueAsString().str() 191 : TargetFS; 192 193 // FIXME: This is related to the code below to reset the target options, 194 // we need to know whether or not the soft float flag is set on the 195 // function before we can generate a subtarget. We also need to use 196 // it as a key for the subtarget since that can be the only difference 197 // between two functions. 198 Attribute SFAttr = F.getFnAttribute("use-soft-float"); 199 bool SoftFloat = !SFAttr.hasAttribute(Attribute::None) 200 ? SFAttr.getValueAsString() == "true" 201 : Options.UseSoftFloat; 202 203 auto &I = SubtargetMap[CPU + FS + (SoftFloat ? "use-soft-float=true" 204 : "use-soft-float=false")]; 205 if (!I) { 206 // This needs to be done before we create a new subtarget since any 207 // creation will depend on the TM and the code generation flags on the 208 // function that reside in TargetOptions. 209 resetTargetOptions(F); 210 I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle); 211 } 212 return I.get(); 213} 214 215TargetIRAnalysis ARMBaseTargetMachine::getTargetIRAnalysis() { 216 return TargetIRAnalysis( 217 [this](Function &F) { return TargetTransformInfo(ARMTTIImpl(this, F)); }); 218} 219 220 221void ARMTargetMachine::anchor() { } 222 223ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU, 224 StringRef FS, const TargetOptions &Options, 225 Reloc::Model RM, CodeModel::Model CM, 226 CodeGenOpt::Level OL, bool isLittle) 227 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) { 228 initAsmInfo(); 229 if (!Subtarget.hasARMOps()) 230 report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not " 231 "support ARM mode execution!"); 232} 233 234void ARMLETargetMachine::anchor() { } 235 236ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT, 237 StringRef CPU, StringRef FS, 238 const TargetOptions &Options, 239 Reloc::Model RM, CodeModel::Model CM, 240 CodeGenOpt::Level OL) 241 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 242 243void ARMBETargetMachine::anchor() { } 244 245ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT, 246 StringRef CPU, StringRef FS, 247 const TargetOptions &Options, 248 Reloc::Model RM, CodeModel::Model CM, 249 CodeGenOpt::Level OL) 250 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 251 252void ThumbTargetMachine::anchor() { } 253 254ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, 255 StringRef CPU, StringRef FS, 256 const TargetOptions &Options, 257 Reloc::Model RM, CodeModel::Model CM, 258 CodeGenOpt::Level OL, bool isLittle) 259 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, 260 isLittle) { 261 initAsmInfo(); 262} 263 264void ThumbLETargetMachine::anchor() { } 265 266ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT, 267 StringRef CPU, StringRef FS, 268 const TargetOptions &Options, 269 Reloc::Model RM, CodeModel::Model CM, 270 CodeGenOpt::Level OL) 271 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 272 273void ThumbBETargetMachine::anchor() { } 274 275ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT, 276 StringRef CPU, StringRef FS, 277 const TargetOptions &Options, 278 Reloc::Model RM, CodeModel::Model CM, 279 CodeGenOpt::Level OL) 280 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 281 282namespace { 283/// ARM Code Generator Pass Configuration Options. 284class ARMPassConfig : public TargetPassConfig { 285public: 286 ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM) 287 : TargetPassConfig(TM, PM) {} 288 289 ARMBaseTargetMachine &getARMTargetMachine() const { 290 return getTM<ARMBaseTargetMachine>(); 291 } 292 293 const ARMSubtarget &getARMSubtarget() const { 294 return *getARMTargetMachine().getSubtargetImpl(); 295 } 296 297 void addIRPasses() override; 298 bool addPreISel() override; 299 bool addInstSelector() override; 300 void addPreRegAlloc() override; 301 void addPreSched2() override; 302 void addPreEmitPass() override; 303}; 304} // namespace 305 306TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { 307 return new ARMPassConfig(this, PM); 308} 309 310void ARMPassConfig::addIRPasses() { 311 if (TM->Options.ThreadModel == ThreadModel::Single) 312 addPass(createLowerAtomicPass()); 313 else 314 addPass(createAtomicExpandPass(TM)); 315 316 // Cmpxchg instructions are often used with a subsequent comparison to 317 // determine whether it succeeded. We can exploit existing control-flow in 318 // ldrex/strex loops to simplify this, but it needs tidying up. 319 const ARMSubtarget *Subtarget = &getARMSubtarget(); 320 if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) 321 if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) 322 addPass(createCFGSimplificationPass()); 323 324 TargetPassConfig::addIRPasses(); 325} 326 327bool ARMPassConfig::addPreISel() { 328 if (TM->getOptLevel() != CodeGenOpt::None) 329 // FIXME: This is using the thumb1 only constant value for 330 // maximal global offset for merging globals. We may want 331 // to look into using the old value for non-thumb1 code of 332 // 4095 based on the TargetMachine, but this starts to become 333 // tricky when doing code gen per function. 334 addPass(createGlobalMergePass(TM, 127)); 335 336 return false; 337} 338 339bool ARMPassConfig::addInstSelector() { 340 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 341 342 const ARMSubtarget *Subtarget = &getARMSubtarget(); 343 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 344 TM->Options.EnableFastISel) 345 addPass(createARMGlobalBaseRegPass()); 346 return false; 347} 348 349void ARMPassConfig::addPreRegAlloc() { 350 if (getOptLevel() != CodeGenOpt::None) 351 addPass(createARMLoadStoreOptimizationPass(true)); 352 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 353 addPass(createMLxExpansionPass()); 354 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 355 // enabled when NEON is available. 356 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 357 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 358 addPass(createA15SDOptimizerPass()); 359 } 360} 361 362void ARMPassConfig::addPreSched2() { 363 if (getOptLevel() != CodeGenOpt::None) { 364 addPass(createARMLoadStoreOptimizationPass()); 365 366 if (getARMSubtarget().hasNEON()) 367 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 368 } 369 370 // Expand some pseudo instructions into multiple instructions to allow 371 // proper scheduling. 372 addPass(createARMExpandPseudoPass()); 373 374 if (getOptLevel() != CodeGenOpt::None) { 375 if (!getARMSubtarget().isThumb1Only()) { 376 // in v8, IfConversion depends on Thumb instruction widths 377 if (getARMSubtarget().restrictIT() && 378 !getARMSubtarget().prefers32BitThumb()) 379 addPass(createThumb2SizeReductionPass()); 380 addPass(&IfConverterID); 381 } 382 } 383 if (getARMSubtarget().isThumb2()) 384 addPass(createThumb2ITBlockPass()); 385} 386 387void ARMPassConfig::addPreEmitPass() { 388 if (getARMSubtarget().isThumb2()) { 389 if (!getARMSubtarget().prefers32BitThumb()) 390 addPass(createThumb2SizeReductionPass()); 391 392 // Constant island pass work on unbundled instructions. 393 addPass(&UnpackMachineBundlesID); 394 } 395 396 addPass(createARMOptimizeBarriersPass()); 397 addPass(createARMConstantIslandPass()); 398} 399