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