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 "ARMTargetMachine.h" 14 #include "ARM.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 cl::opt<bool> 27 EnableGlobalMerge("global-merge", cl::Hidden, 28 cl::desc("Enable global merge pass"), 29 cl::init(true)); 30 31 static cl::opt<bool> 32 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden, 33 cl::desc("Inhibit optimization of S->D register accesses on A15"), 34 cl::init(false)); 35 36 extern "C" void LLVMInitializeARMTarget() { 37 // Register the target. 38 RegisterTargetMachine<ARMTargetMachine> X(TheARMTarget); 39 RegisterTargetMachine<ThumbTargetMachine> Y(TheThumbTarget); 40 } 41 42 43 /// TargetMachine ctor - Create an ARM architecture model. 44 /// 45 ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT, 46 StringRef CPU, StringRef FS, 47 const TargetOptions &Options, 48 Reloc::Model RM, CodeModel::Model CM, 49 CodeGenOpt::Level OL) 50 : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 51 Subtarget(TT, CPU, FS, Options), 52 JITInfo(), 53 InstrItins(Subtarget.getInstrItineraryData()) { 54 // Default to soft float ABI 55 if (Options.FloatABIType == FloatABI::Default) 56 this->Options.FloatABIType = 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 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, 71 StringRef CPU, StringRef FS, 72 const TargetOptions &Options, 73 Reloc::Model RM, CodeModel::Model CM, 74 CodeGenOpt::Level OL) 75 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 76 InstrInfo(Subtarget), 77 DL(Subtarget.isAPCS_ABI() ? 78 std::string("e-p:32:32-f64:32:64-i64:32:64-" 79 "v128:32:128-v64:32:64-n32-S32") : 80 Subtarget.isAAPCS_ABI() ? 81 std::string("e-p:32:32-f64:64:64-i64:64:64-" 82 "v128:64:128-v64:64:64-n32-S64") : 83 std::string("e-p:32:32-f64:64:64-i64:64:64-" 84 "v128:64:128-v64:64:64-n32-S32")), 85 TLInfo(*this), 86 TSInfo(*this), 87 FrameLowering(Subtarget) { 88 initAsmInfo(); 89 if (!Subtarget.hasARMOps()) 90 report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not " 91 "support ARM mode execution!"); 92 } 93 94 void ThumbTargetMachine::anchor() { } 95 96 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT, 97 StringRef CPU, StringRef FS, 98 const TargetOptions &Options, 99 Reloc::Model RM, CodeModel::Model CM, 100 CodeGenOpt::Level OL) 101 : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), 102 InstrInfo(Subtarget.hasThumb2() 103 ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget)) 104 : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))), 105 DL(Subtarget.isAPCS_ABI() ? 106 std::string("e-p:32:32-f64:32:64-i64:32:64-" 107 "i16:16:32-i8:8:32-i1:8:32-" 108 "v128:32:128-v64:32:64-a:0:32-n32-S32") : 109 Subtarget.isAAPCS_ABI() ? 110 std::string("e-p:32:32-f64:64:64-i64:64:64-" 111 "i16:16:32-i8:8:32-i1:8:32-" 112 "v128:64:128-v64:64:64-a:0:32-n32-S64") : 113 std::string("e-p:32:32-f64:64:64-i64:64:64-" 114 "i16:16:32-i8:8:32-i1:8:32-" 115 "v128:64:128-v64:64:64-a:0:32-n32-S32")), 116 TLInfo(*this), 117 TSInfo(*this), 118 FrameLowering(Subtarget.hasThumb2() 119 ? new ARMFrameLowering(Subtarget) 120 : (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) { 121 initAsmInfo(); 122 } 123 124 namespace { 125 /// ARM Code Generator Pass Configuration Options. 126 class ARMPassConfig : public TargetPassConfig { 127 public: 128 ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM) 129 : TargetPassConfig(TM, PM) {} 130 131 ARMBaseTargetMachine &getARMTargetMachine() const { 132 return getTM<ARMBaseTargetMachine>(); 133 } 134 135 const ARMSubtarget &getARMSubtarget() const { 136 return *getARMTargetMachine().getSubtargetImpl(); 137 } 138 139 virtual bool addPreISel(); 140 virtual bool addInstSelector(); 141 virtual bool addPreRegAlloc(); 142 virtual bool addPreSched2(); 143 virtual bool addPreEmitPass(); 144 }; 145 } // namespace 146 147 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) { 148 return new ARMPassConfig(this, PM); 149 } 150 151 bool ARMPassConfig::addPreISel() { 152 if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge) 153 addPass(createGlobalMergePass(TM)); 154 155 return false; 156 } 157 158 bool ARMPassConfig::addInstSelector() { 159 addPass(createARMISelDag(getARMTargetMachine(), getOptLevel())); 160 161 const ARMSubtarget *Subtarget = &getARMSubtarget(); 162 if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() && 163 TM->Options.EnableFastISel) 164 addPass(createARMGlobalBaseRegPass()); 165 return false; 166 } 167 168 bool ARMPassConfig::addPreRegAlloc() { 169 // FIXME: temporarily disabling load / store optimization pass for Thumb1. 170 if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only()) 171 addPass(createARMLoadStoreOptimizationPass(true)); 172 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9()) 173 addPass(createMLxExpansionPass()); 174 // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be 175 // enabled when NEON is available. 176 if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() && 177 getARMSubtarget().hasNEON() && !DisableA15SDOptimization) { 178 addPass(createA15SDOptimizerPass()); 179 } 180 return true; 181 } 182 183 bool ARMPassConfig::addPreSched2() { 184 // FIXME: temporarily disabling load / store optimization pass for Thumb1. 185 if (getOptLevel() != CodeGenOpt::None) { 186 if (!getARMSubtarget().isThumb1Only()) { 187 addPass(createARMLoadStoreOptimizationPass()); 188 printAndVerify("After ARM load / store optimizer"); 189 } 190 if (getARMSubtarget().hasNEON()) 191 addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass)); 192 } 193 194 // Expand some pseudo instructions into multiple instructions to allow 195 // proper scheduling. 196 addPass(createARMExpandPseudoPass()); 197 198 if (getOptLevel() != CodeGenOpt::None) { 199 if (!getARMSubtarget().isThumb1Only()) 200 addPass(&IfConverterID); 201 } 202 if (getARMSubtarget().isThumb2()) 203 addPass(createThumb2ITBlockPass()); 204 205 return true; 206 } 207 208 bool ARMPassConfig::addPreEmitPass() { 209 if (getARMSubtarget().isThumb2()) { 210 if (!getARMSubtarget().prefers32BitThumb()) 211 addPass(createThumb2SizeReductionPass()); 212 213 // Constant island pass work on unbundled instructions. 214 addPass(&UnpackMachineBundlesID); 215 } 216 217 addPass(createARMConstantIslandPass()); 218 219 return true; 220 } 221 222 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM, 223 JITCodeEmitter &JCE) { 224 // Machine code emitter pass for ARM. 225 PM.add(createARMJITCodeEmitterPass(*this, JCE)); 226 return false; 227 } 228