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