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, bool isLittle) 53 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 54 Subtarget(TT, CPU, FS, *this, isLittle, Options) { 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 void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) { 63 // Add first the target-independent BasicTTI pass, then our ARM pass. This 64 // allows the ARM pass to delegate to the target independent layer when 65 // appropriate. 66 PM.add(createBasicTargetTransformInfoPass(this)); 67 PM.add(createARMTargetTransformInfoPass(this)); 68 } 69 70 71 void ARMTargetMachine::anchor() { } 72 73 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU, 74 StringRef FS, const TargetOptions &Options, 75 Reloc::Model RM, CodeModel::Model CM, 76 CodeGenOpt::Level OL, bool isLittle) 77 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) { 78 initAsmInfo(); 79 if (!Subtarget.hasARMOps()) 80 report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not " 81 "support ARM mode execution!"); 82 } 83 84 void ARMLETargetMachine::anchor() { } 85 86 ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT, 87 StringRef CPU, StringRef FS, 88 const TargetOptions &Options, 89 Reloc::Model RM, CodeModel::Model CM, 90 CodeGenOpt::Level OL) 91 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 92 93 void ARMBETargetMachine::anchor() { } 94 95 ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT, 96 StringRef CPU, StringRef FS, 97 const TargetOptions &Options, 98 Reloc::Model RM, CodeModel::Model CM, 99 CodeGenOpt::Level OL) 100 : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 101 102 void ThumbTargetMachine::anchor() { } 103 104 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, 105 StringRef CPU, StringRef FS, 106 const TargetOptions &Options, 107 Reloc::Model RM, CodeModel::Model CM, 108 CodeGenOpt::Level OL, bool isLittle) 109 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, 110 isLittle) { 111 initAsmInfo(); 112 } 113 114 void ThumbLETargetMachine::anchor() { } 115 116 ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT, 117 StringRef CPU, StringRef FS, 118 const TargetOptions &Options, 119 Reloc::Model RM, CodeModel::Model CM, 120 CodeGenOpt::Level OL) 121 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} 122 123 void ThumbBETargetMachine::anchor() { } 124 125 ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT, 126 StringRef CPU, StringRef FS, 127 const TargetOptions &Options, 128 Reloc::Model RM, CodeModel::Model CM, 129 CodeGenOpt::Level OL) 130 : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} 131 132 namespace { 133 /// ARM Code Generator Pass Configuration Options. 134 class ARMPassConfig : public TargetPassConfig { 135 public: 136 ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM) 137 : TargetPassConfig(TM, PM) {} 138 139 ARMBaseTargetMachine &getARMTargetMachine() const { 140 return getTM<ARMBaseTargetMachine>(); 141 } 142 143 const ARMSubtarget &getARMSubtarget() const { 144 return *getARMTargetMachine().getSubtargetImpl(); 145 } 146 147 void addIRPasses() override; 148 bool addPreISel() override; 149 bool addInstSelector() override; 150 bool addPreRegAlloc() override; 151 bool addPreSched2() override; 152 bool addPreEmitPass() override; 153 }; 154 } // namespace 155 156 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { 157 return new ARMPassConfig(this, PM); 158 } 159 160 void ARMPassConfig::addIRPasses() { 161 if (TM->Options.ThreadModel == ThreadModel::Single) 162 addPass(createLowerAtomicPass()); 163 else 164 addPass(createAtomicExpandPass(TM)); 165 166 // Cmpxchg instructions are often used with a subsequent comparison to 167 // determine whether it succeeded. We can exploit existing control-flow in 168 // ldrex/strex loops to simplify this, but it needs tidying up. 169 const ARMSubtarget *Subtarget = &getARMSubtarget(); 170 if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) 171 if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) 172 addPass(createCFGSimplificationPass()); 173 174 TargetPassConfig::addIRPasses(); 175 } 176 177 bool ARMPassConfig::addPreISel() { 178 if (TM->getOptLevel() != CodeGenOpt::None) 179 addPass(createGlobalMergePass(TM)); 180 181 return false; 182 } 183 184 bool ARMPassConfig::addInstSelector() { 185 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 186 187 const ARMSubtarget *Subtarget = &getARMSubtarget(); 188 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 189 TM->Options.EnableFastISel) 190 addPass(createARMGlobalBaseRegPass()); 191 return false; 192 } 193 194 bool ARMPassConfig::addPreRegAlloc() { 195 if (getOptLevel() != CodeGenOpt::None) 196 addPass(createARMLoadStoreOptimizationPass(true)); 197 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 198 addPass(createMLxExpansionPass()); 199 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 200 // enabled when NEON is available. 201 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 202 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 203 addPass(createA15SDOptimizerPass()); 204 } 205 return true; 206 } 207 208 bool ARMPassConfig::addPreSched2() { 209 if (getOptLevel() != CodeGenOpt::None) { 210 addPass(createARMLoadStoreOptimizationPass()); 211 printAndVerify("After ARM load / store optimizer"); 212 213 if (getARMSubtarget().hasNEON()) 214 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 215 } 216 217 // Expand some pseudo instructions into multiple instructions to allow 218 // proper scheduling. 219 addPass(createARMExpandPseudoPass()); 220 221 if (getOptLevel() != CodeGenOpt::None) { 222 if (!getARMSubtarget().isThumb1Only()) { 223 // in v8, IfConversion depends on Thumb instruction widths 224 if (getARMSubtarget().restrictIT() && 225 !getARMSubtarget().prefers32BitThumb()) 226 addPass(createThumb2SizeReductionPass()); 227 addPass(&IfConverterID); 228 } 229 } 230 if (getARMSubtarget().isThumb2()) 231 addPass(createThumb2ITBlockPass()); 232 233 return true; 234 } 235 236 bool ARMPassConfig::addPreEmitPass() { 237 if (getARMSubtarget().isThumb2()) { 238 if (!getARMSubtarget().prefers32BitThumb()) 239 addPass(createThumb2SizeReductionPass()); 240 241 // Constant island pass work on unbundled instructions. 242 addPass(&UnpackMachineBundlesID); 243 } 244 245 addPass(createARMOptimizeBarriersPass()); 246 addPass(createARMConstantIslandPass()); 247 248 return true; 249 } 250 251 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, 252 JITCodeEmitter &JCE) { 253 // Machine code emitter pass for ARM. 254 PM.add(createARMJITCodeEmitterPass(*this, JCE)); 255 return false; 256 } 257