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