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