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 extern "C" void LLVMInitializeARMTarget() { 32 // Register the target. 33 RegisterTargetMachine<ARMLETargetMachine> X(TheARMLETarget); 34 RegisterTargetMachine<ARMBETargetMachine> Y(TheARMBETarget); 35 RegisterTargetMachine<ThumbLETargetMachine> A(TheThumbLETarget); 36 RegisterTargetMachine<ThumbBETargetMachine> B(TheThumbBETarget); 37 } 38 39 40 /// TargetMachine ctor - Create an ARM architecture model. 41 /// 42 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT, 43 StringRef CPU, StringRef FS, 44 const TargetOptions &Options, 45 Reloc::Model RM, CodeModel::Model CM, 46 CodeGenOpt::Level OL, 47 bool isLittle) 48 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 49 Subtarget(TT, CPU, FS, isLittle, Options), 50 JITInfo(), 51 InstrItins(Subtarget.getInstrItineraryData()) { 52 53 // Default to triple-appropriate float ABI 54 if (Options.FloatABIType == FloatABI::Default) 55 this->Options.FloatABIType = 56 Subtarget.isTargetHardFloat() ? FloatABI::Hard : FloatABI::Soft; 57 } 58 59 void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) { 60 // Add first the target-independent BasicTTI pass, then our ARM pass. This 61 // allows the ARM pass to delegate to the target independent layer when 62 // appropriate. 63 PM.add(createBasicTargetTransformInfoPass(this)); 64 PM.add(createARMTargetTransformInfoPass(this)); 65 } 66 67 68 void ARMTargetMachine::anchor() { } 69 70 static std::string computeDataLayout(ARMSubtarget &ST) { 71 std::string Ret = ""; 72 73 if (ST.isLittle()) 74 // Little endian. 75 Ret += "e"; 76 else 77 // Big endian. 78 Ret += "E"; 79 80 Ret += DataLayout::getManglingComponent(ST.getTargetTriple()); 81 82 // Pointers are 32 bits and aligned to 32 bits. 83 Ret += "-p:32:32"; 84 85 // On thumb, i16,i18 and i1 have natural aligment requirements, but we try to 86 // align to 32. 87 if (ST.isThumb()) 88 Ret += "-i1:8:32-i8:8:32-i16:16:32"; 89 90 // ABIs other than APCS have 64 bit integers with natural alignment. 91 if (!ST.isAPCS_ABI()) 92 Ret += "-i64:64"; 93 94 // We have 64 bits floats. The APCS ABI requires them to be aligned to 32 95 // bits, others to 64 bits. We always try to align to 64 bits. 96 if (ST.isAPCS_ABI()) 97 Ret += "-f64:32:64"; 98 99 // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others 100 // to 64. We always ty to give them natural alignment. 101 if (ST.isAPCS_ABI()) 102 Ret += "-v64:32:64-v128:32:128"; 103 else 104 Ret += "-v128:64:128"; 105 106 // On thumb and APCS, only try to align aggregates to 32 bits (the default is 107 // 64 bits). 108 if (ST.isThumb() || ST.isAPCS_ABI()) 109 Ret += "-a:0:32"; 110 111 // Integer registers are 32 bits. 112 Ret += "-n32"; 113 114 // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit 115 // aligned everywhere else. 116 if (ST.isTargetNaCl()) 117 Ret += "-S128"; 118 else if (ST.isAAPCS_ABI()) 119 Ret += "-S64"; 120 else 121 Ret += "-S32"; 122 123 return Ret; 124 } 125 126 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, 127 StringRef CPU, StringRef FS, 128 const TargetOptions &Options, 129 Reloc::Model RM, CodeModel::Model CM, 130 CodeGenOpt::Level OL, 131 bool isLittle) 132 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle), 133 InstrInfo(Subtarget), 134 DL(computeDataLayout(Subtarget)), 135 TLInfo(*this), 136 TSInfo(*this), 137 FrameLowering(Subtarget) { 138 initAsmInfo(); 139 if (!Subtarget.hasARMOps()) 140 report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not " 141 "support ARM mode execution!"); 142 } 143 144 void ARMLETargetMachine::anchor() { } 145 146 ARMLETargetMachine:: 147 ARMLETargetMachine(const Target &T, StringRef TT, 148 StringRef CPU, StringRef FS, const TargetOptions &Options, 149 Reloc::Model RM, CodeModel::Model CM, 150 CodeGenOpt::Level OL) 151 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 152 153 void ARMBETargetMachine::anchor() { } 154 155 ARMBETargetMachine:: 156 ARMBETargetMachine(const Target &T, StringRef TT, 157 StringRef CPU, StringRef FS, const TargetOptions &Options, 158 Reloc::Model RM, CodeModel::Model CM, 159 CodeGenOpt::Level OL) 160 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 161 162 void ThumbTargetMachine::anchor() { } 163 164 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, 165 StringRef CPU, StringRef FS, 166 const TargetOptions &Options, 167 Reloc::Model RM, CodeModel::Model CM, 168 CodeGenOpt::Level OL, 169 bool isLittle) 170 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle), 171 InstrInfo(Subtarget.hasThumb2() 172 ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) 173 : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), 174 DL(computeDataLayout(Subtarget)), 175 TLInfo(*this), 176 TSInfo(*this), 177 FrameLowering(Subtarget.hasThumb2() 178 ? new ARMFrameLowering(Subtarget) 179 : (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) { 180 initAsmInfo(); 181 } 182 183 void ThumbLETargetMachine::anchor() { } 184 185 ThumbLETargetMachine:: 186 ThumbLETargetMachine(const Target &T, StringRef TT, 187 StringRef CPU, StringRef FS, const TargetOptions &Options, 188 Reloc::Model RM, CodeModel::Model CM, 189 CodeGenOpt::Level OL) 190 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 191 192 void ThumbBETargetMachine::anchor() { } 193 194 ThumbBETargetMachine:: 195 ThumbBETargetMachine(const Target &T, StringRef TT, 196 StringRef CPU, StringRef FS, const TargetOptions &Options, 197 Reloc::Model RM, CodeModel::Model CM, 198 CodeGenOpt::Level OL) 199 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 200 201 namespace { 202 /// ARM Code Generator Pass Configuration Options. 203 class ARMPassConfig : public TargetPassConfig { 204 public: 205 ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM) 206 : TargetPassConfig(TM, PM) {} 207 208 ARMBaseTargetMachine &getARMTargetMachine() const { 209 return getTM<ARMBaseTargetMachine>(); 210 } 211 212 const ARMSubtarget &getARMSubtarget() const { 213 return *getARMTargetMachine().getSubtargetImpl(); 214 } 215 216 bool addPreISel() override; 217 bool addInstSelector() override; 218 bool addPreRegAlloc() override; 219 bool addPreSched2() override; 220 bool addPreEmitPass() override; 221 }; 222 } // namespace 223 224 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { 225 return new ARMPassConfig(this, PM); 226 } 227 228 bool ARMPassConfig::addPreISel() { 229 const ARMSubtarget *Subtarget = &getARMSubtarget(); 230 if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) 231 addPass(createAtomicExpandLoadLinkedPass(TM)); 232 233 if (TM->getOptLevel() != CodeGenOpt::None) 234 addPass(createGlobalMergePass(TM)); 235 236 return false; 237 } 238 239 bool ARMPassConfig::addInstSelector() { 240 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 241 242 const ARMSubtarget *Subtarget = &getARMSubtarget(); 243 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 244 TM->Options.EnableFastISel) 245 addPass(createARMGlobalBaseRegPass()); 246 return false; 247 } 248 249 bool ARMPassConfig::addPreRegAlloc() { 250 if (getOptLevel() != CodeGenOpt::None) 251 addPass(createARMLoadStoreOptimizationPass(true)); 252 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 253 addPass(createMLxExpansionPass()); 254 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 255 // enabled when NEON is available. 256 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 257 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 258 addPass(createA15SDOptimizerPass()); 259 } 260 return true; 261 } 262 263 bool ARMPassConfig::addPreSched2() { 264 if (getOptLevel() != CodeGenOpt::None) { 265 addPass(createARMLoadStoreOptimizationPass()); 266 printAndVerify("After ARM load / store optimizer"); 267 268 if (getARMSubtarget().hasNEON()) 269 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 270 } 271 272 // Expand some pseudo instructions into multiple instructions to allow 273 // proper scheduling. 274 addPass(createARMExpandPseudoPass()); 275 276 if (getOptLevel() != CodeGenOpt::None) { 277 if (!getARMSubtarget().isThumb1Only()) { 278 // in v8, IfConversion depends on Thumb instruction widths 279 if (getARMSubtarget().restrictIT() && 280 !getARMSubtarget().prefers32BitThumb()) 281 addPass(createThumb2SizeReductionPass()); 282 addPass(&IfConverterID); 283 } 284 } 285 if (getARMSubtarget().isThumb2()) 286 addPass(createThumb2ITBlockPass()); 287 288 return true; 289 } 290 291 bool ARMPassConfig::addPreEmitPass() { 292 if (getARMSubtarget().isThumb2()) { 293 if (!getARMSubtarget().prefers32BitThumb()) 294 addPass(createThumb2SizeReductionPass()); 295 296 // Constant island pass work on unbundled instructions. 297 addPass(&UnpackMachineBundlesID); 298 } 299 300 addPass(createARMOptimizeBarriersPass()); 301 addPass(createARMConstantIslandPass()); 302 303 return true; 304 } 305 306 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, 307 JITCodeEmitter &JCE) { 308 // Machine code emitter pass for ARM. 309 PM.add(createARMJITCodeEmitterPass(*this, JCE)); 310 return false; 311 } 312