Refactor the construction of the DataLayout string on ARM.
[oota-llvm.git] / lib / Target / ARM / ARMTargetMachine.cpp
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 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 static std::string computeDataLayout(ARMSubtarget &ST) {
71   std::string Ret = "e-p:32:32";
72
73   if (ST.isAPCS_ABI())
74     Ret += "-f64:32:64-i64:32:64";
75   else
76     Ret += "-f64:64:64-i64:64:64";
77
78   if (ST.isThumb()) {
79     if (ST.isAPCS_ABI())
80       Ret += "-i16:16:32-i8:8:32-i1:8:32";
81     else
82       Ret += "-i16:16:32-i8:8:32-i1:8:32";
83   }
84
85   if (ST.isAPCS_ABI())
86     Ret += "-v128:32:128-v64:32:64";
87   else
88     Ret += "-v128:64:128-v64:64:64";
89
90   if (ST.isThumb()) {
91     if (ST.isAPCS_ABI())
92       Ret += "-a:0:32";
93     else
94       Ret += "-a:0:32";
95   }
96
97   Ret += "-n32";
98
99   if (ST.isAAPCS_ABI())
100     Ret += "-S64";
101   else
102     Ret += "-S32";
103
104   return Ret;
105 }
106
107 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT,
108                                    StringRef CPU, StringRef FS,
109                                    const TargetOptions &Options,
110                                    Reloc::Model RM, CodeModel::Model CM,
111                                    CodeGenOpt::Level OL)
112   : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
113     InstrInfo(Subtarget),
114     DL(computeDataLayout(Subtarget)),
115     TLInfo(*this),
116     TSInfo(*this),
117     FrameLowering(Subtarget) {
118   initAsmInfo();
119   if (!Subtarget.hasARMOps())
120     report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
121                        "support ARM mode execution!");
122 }
123
124 void ThumbTargetMachine::anchor() { }
125
126 ThumbTargetMachine::ThumbTargetMachine(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   : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
132     InstrInfo(Subtarget.hasThumb2()
133               ? ((ARMBaseInstrInfo*)new Thumb2InstrInfo(Subtarget))
134               : ((ARMBaseInstrInfo*)new Thumb1InstrInfo(Subtarget))),
135     DL(computeDataLayout(Subtarget)),
136     TLInfo(*this),
137     TSInfo(*this),
138     FrameLowering(Subtarget.hasThumb2()
139               ? new ARMFrameLowering(Subtarget)
140               : (ARMFrameLowering*)new Thumb1FrameLowering(Subtarget)) {
141   initAsmInfo();
142 }
143
144 namespace {
145 /// ARM Code Generator Pass Configuration Options.
146 class ARMPassConfig : public TargetPassConfig {
147 public:
148   ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
149     : TargetPassConfig(TM, PM) {}
150
151   ARMBaseTargetMachine &getARMTargetMachine() const {
152     return getTM<ARMBaseTargetMachine>();
153   }
154
155   const ARMSubtarget &getARMSubtarget() const {
156     return *getARMTargetMachine().getSubtargetImpl();
157   }
158
159   virtual bool addPreISel();
160   virtual bool addInstSelector();
161   virtual bool addPreRegAlloc();
162   virtual bool addPreSched2();
163   virtual bool addPreEmitPass();
164 };
165 } // namespace
166
167 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
168   return new ARMPassConfig(this, PM);
169 }
170
171 bool ARMPassConfig::addPreISel() {
172   if (TM->getOptLevel() != CodeGenOpt::None && EnableGlobalMerge)
173     addPass(createGlobalMergePass(TM));
174
175   return false;
176 }
177
178 bool ARMPassConfig::addInstSelector() {
179   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
180
181   const ARMSubtarget *Subtarget = &getARMSubtarget();
182   if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
183       TM->Options.EnableFastISel)
184     addPass(createARMGlobalBaseRegPass());
185   return false;
186 }
187
188 bool ARMPassConfig::addPreRegAlloc() {
189   // FIXME: temporarily disabling load / store optimization pass for Thumb1.
190   if (getOptLevel() != CodeGenOpt::None && !getARMSubtarget().isThumb1Only())
191     addPass(createARMLoadStoreOptimizationPass(true));
192   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
193     addPass(createMLxExpansionPass());
194   // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
195   // enabled when NEON is available.
196   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
197     getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
198     addPass(createA15SDOptimizerPass());
199   }
200   return true;
201 }
202
203 bool ARMPassConfig::addPreSched2() {
204   // FIXME: temporarily disabling load / store optimization pass for Thumb1.
205   if (getOptLevel() != CodeGenOpt::None) {
206     if (!getARMSubtarget().isThumb1Only()) {
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(createARMConstantIslandPass());
243
244   return true;
245 }
246
247 bool ARMBaseTargetMachine::addCodeEmitter(PassManagerBase &PM,
248                                           JITCodeEmitter &JCE) {
249   // Machine code emitter pass for ARM.
250   PM.add(createARMJITCodeEmitterPass(*this, JCE));
251   return false;
252 }