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 addPass(createAtomicExpandLoadLinkedPass(TM)); 162 163 // Cmpxchg instructions are often used with a subsequent comparison to 164 // determine whether it succeeded. We can exploit existing control-flow in 165 // ldrex/strex loops to simplify this, but it needs tidying up. 166 const ARMSubtarget *Subtarget = &getARMSubtarget(); 167 if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only()) 168 if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy) 169 addPass(createCFGSimplificationPass()); 170 171 TargetPassConfig::addIRPasses(); 172 } 173 174 bool ARMPassConfig::addPreISel() { 175 if (TM->getOptLevel() != CodeGenOpt::None) 176 addPass(createGlobalMergePass(TM)); 177 178 return false; 179 } 180 181 bool ARMPassConfig::addInstSelector() { 182 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 183 184 const ARMSubtarget *Subtarget = &getARMSubtarget(); 185 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 186 TM->Options.EnableFastISel) 187 addPass(createARMGlobalBaseRegPass()); 188 return false; 189 } 190 191 bool ARMPassConfig::addPreRegAlloc() { 192 if (getOptLevel() != CodeGenOpt::None) 193 addPass(createARMLoadStoreOptimizationPass(true)); 194 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 195 addPass(createMLxExpansionPass()); 196 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 197 // enabled when NEON is available. 198 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 199 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 200 addPass(createA15SDOptimizerPass()); 201 } 202 return true; 203 } 204 205 bool ARMPassConfig::addPreSched2() { 206 if (getOptLevel() != CodeGenOpt::None) { 207 addPass(createARMLoadStoreOptimizationPass()); 208 printAndVerify("After ARM load / store optimizer"); 209 210 if (getARMSubtarget().hasNEON()) 211 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 212 } 213 214 // Expand some pseudo instructions into multiple instructions to allow 215 // proper scheduling. 216 addPass(createARMExpandPseudoPass()); 217 218 if (getOptLevel() != CodeGenOpt::None) { 219 if (!getARMSubtarget().isThumb1Only()) { 220 // in v8, IfConversion depends on Thumb instruction widths 221 if (getARMSubtarget().restrictIT() && 222 !getARMSubtarget().prefers32BitThumb()) 223 addPass(createThumb2SizeReductionPass()); 224 addPass(&IfConverterID); 225 } 226 } 227 if (getARMSubtarget().isThumb2()) 228 addPass(createThumb2ITBlockPass()); 229 230 return true; 231 } 232 233 bool ARMPassConfig::addPreEmitPass() { 234 if (getARMSubtarget().isThumb2()) { 235 if (!getARMSubtarget().prefers32BitThumb()) 236 addPass(createThumb2SizeReductionPass()); 237 238 // Constant island pass work on unbundled instructions. 239 addPass(&UnpackMachineBundlesID); 240 } 241 242 addPass(createARMOptimizeBarriersPass()); 243 addPass(createARMConstantIslandPass()); 244 245 return true; 246 } 247 248 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, 249 JITCodeEmitter &JCE) { 250 // Machine code emitter pass for ARM. 251 PM.add(createARMJITCodeEmitterPass(*this, JCE)); 252 return false; 253 } 254