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/IR/Function.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/PassManager.h"
20 #include "llvm/Support/CommandLine.h"
21 #include "llvm/Support/FormattedStream.h"
22 #include "llvm/Support/TargetRegistry.h"
23 #include "llvm/Target/TargetOptions.h"
24 #include "llvm/Transforms/Scalar.h"
25 using namespace llvm;
26 
27 static cl::opt<bool>
28 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
29                    cl::desc("Inhibit optimization of S->D register accesses on A15"),
30                    cl::init(false));
31 
32 static cl::opt<bool>
33 EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
34                  cl::desc("Run SimplifyCFG after expanding atomic operations"
35                           " to make use of cmpxchg flow-based information"),
36                  cl::init(true));
37 
38 extern "C" void LLVMInitializeARMTarget() {
39   // Register the target.
40   RegisterTargetMachine<ARMLETargetMachine> X(TheARMLETarget);
41   RegisterTargetMachine<ARMBETargetMachine> Y(TheARMBETarget);
42   RegisterTargetMachine<ThumbLETargetMachine> A(TheThumbLETarget);
43   RegisterTargetMachine<ThumbBETargetMachine> B(TheThumbBETarget);
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), isLittle(isLittle) {
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 const ARMSubtarget *
63 ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
64   AttributeSet FnAttrs = F.getAttributes();
65   Attribute CPUAttr =
66       FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu");
67   Attribute FSAttr =
68       FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features");
69 
70   std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
71                         ? CPUAttr.getValueAsString().str()
72                         : TargetCPU;
73   std::string FS = !FSAttr.hasAttribute(Attribute::None)
74                        ? FSAttr.getValueAsString().str()
75                        : TargetFS;
76 
77   // FIXME: This is related to the code below to reset the target options,
78   // we need to know whether or not the soft float flag is set on the
79   // function before we can generate a subtarget. We also need to use
80   // it as a key for the subtarget since that can be the only difference
81   // between two functions.
82   Attribute SFAttr =
83       FnAttrs.getAttribute(AttributeSet::FunctionIndex, "use-soft-float");
84   bool SoftFloat = !SFAttr.hasAttribute(Attribute::None)
85                        ? SFAttr.getValueAsString() == "true"
86                        : Options.UseSoftFloat;
87 
88   auto &I = SubtargetMap[CPU + FS + (SoftFloat ? "use-soft-float=true"
89                                                : "use-soft-float=false")];
90   if (!I) {
91     // This needs to be done before we create a new subtarget since any
92     // creation will depend on the TM and the code generation flags on the
93     // function that reside in TargetOptions.
94     resetTargetOptions(F);
95     I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle);
96   }
97   return I.get();
98 }
99 
100 void ARMBaseTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
101   // Add first the target-independent BasicTTI pass, then our ARM pass. This
102   // allows the ARM pass to delegate to the target independent layer when
103   // appropriate.
104   PM.add(createBasicTargetTransformInfoPass(this));
105   PM.add(createARMTargetTransformInfoPass(this));
106 }
107 
108 
109 void ARMTargetMachine::anchor() { }
110 
111 ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU,
112                                    StringRef FS, const TargetOptions &Options,
113                                    Reloc::Model RM, CodeModel::Model CM,
114                                    CodeGenOpt::Level OL, bool isLittle)
115     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
116   initAsmInfo();
117   if (!Subtarget.hasARMOps())
118     report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
119                        "support ARM mode execution!");
120 }
121 
122 void ARMLETargetMachine::anchor() { }
123 
124 ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT,
125                                        StringRef CPU, StringRef FS,
126                                        const TargetOptions &Options,
127                                        Reloc::Model RM, CodeModel::Model CM,
128                                        CodeGenOpt::Level OL)
129     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
130 
131 void ARMBETargetMachine::anchor() { }
132 
133 ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT,
134                                        StringRef CPU, StringRef FS,
135                                        const TargetOptions &Options,
136                                        Reloc::Model RM, CodeModel::Model CM,
137                                        CodeGenOpt::Level OL)
138     : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
139 
140 void ThumbTargetMachine::anchor() { }
141 
142 ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
143                                        StringRef CPU, StringRef FS,
144                                        const TargetOptions &Options,
145                                        Reloc::Model RM, CodeModel::Model CM,
146                                        CodeGenOpt::Level OL, bool isLittle)
147     : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL,
148                            isLittle) {
149   initAsmInfo();
150 }
151 
152 void ThumbLETargetMachine::anchor() { }
153 
154 ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT,
155                                            StringRef CPU, StringRef FS,
156                                            const TargetOptions &Options,
157                                            Reloc::Model RM, CodeModel::Model CM,
158                                            CodeGenOpt::Level OL)
159     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
160 
161 void ThumbBETargetMachine::anchor() { }
162 
163 ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT,
164                                            StringRef CPU, StringRef FS,
165                                            const TargetOptions &Options,
166                                            Reloc::Model RM, CodeModel::Model CM,
167                                            CodeGenOpt::Level OL)
168     : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
169 
170 namespace {
171 /// ARM Code Generator Pass Configuration Options.
172 class ARMPassConfig : public TargetPassConfig {
173 public:
174   ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
175     : TargetPassConfig(TM, PM) {}
176 
177   ARMBaseTargetMachine &getARMTargetMachine() const {
178     return getTM<ARMBaseTargetMachine>();
179   }
180 
181   const ARMSubtarget &getARMSubtarget() const {
182     return *getARMTargetMachine().getSubtargetImpl();
183   }
184 
185   void addIRPasses() override;
186   bool addPreISel() override;
187   bool addInstSelector() override;
188   bool addPreRegAlloc() override;
189   bool addPreSched2() override;
190   bool addPreEmitPass() override;
191 };
192 } // namespace
193 
194 TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
195   return new ARMPassConfig(this, PM);
196 }
197 
198 void ARMPassConfig::addIRPasses() {
199   if (TM->Options.ThreadModel == ThreadModel::Single)
200     addPass(createLowerAtomicPass());
201   else
202     addPass(createAtomicExpandPass(TM));
203 
204   // Cmpxchg instructions are often used with a subsequent comparison to
205   // determine whether it succeeded. We can exploit existing control-flow in
206   // ldrex/strex loops to simplify this, but it needs tidying up.
207   const ARMSubtarget *Subtarget = &getARMSubtarget();
208   if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only())
209     if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
210       addPass(createCFGSimplificationPass());
211 
212   TargetPassConfig::addIRPasses();
213 }
214 
215 bool ARMPassConfig::addPreISel() {
216   if (TM->getOptLevel() != CodeGenOpt::None)
217     addPass(createGlobalMergePass(TM));
218 
219   return false;
220 }
221 
222 bool ARMPassConfig::addInstSelector() {
223   addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
224 
225   const ARMSubtarget *Subtarget = &getARMSubtarget();
226   if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
227       TM->Options.EnableFastISel)
228     addPass(createARMGlobalBaseRegPass());
229   return false;
230 }
231 
232 bool ARMPassConfig::addPreRegAlloc() {
233   if (getOptLevel() != CodeGenOpt::None)
234     addPass(createARMLoadStoreOptimizationPass(true));
235   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
236     addPass(createMLxExpansionPass());
237   // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
238   // enabled when NEON is available.
239   if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
240     getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
241     addPass(createA15SDOptimizerPass());
242   }
243   return true;
244 }
245 
246 bool ARMPassConfig::addPreSched2() {
247   if (getOptLevel() != CodeGenOpt::None) {
248     addPass(createARMLoadStoreOptimizationPass());
249     printAndVerify("After ARM load / store optimizer");
250 
251     if (getARMSubtarget().hasNEON())
252       addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
253   }
254 
255   // Expand some pseudo instructions into multiple instructions to allow
256   // proper scheduling.
257   addPass(createARMExpandPseudoPass());
258 
259   if (getOptLevel() != CodeGenOpt::None) {
260     if (!getARMSubtarget().isThumb1Only()) {
261       // in v8, IfConversion depends on Thumb instruction widths
262       if (getARMSubtarget().restrictIT() &&
263           !getARMSubtarget().prefers32BitThumb())
264         addPass(createThumb2SizeReductionPass());
265       addPass(&IfConverterID);
266     }
267   }
268   if (getARMSubtarget().isThumb2())
269     addPass(createThumb2ITBlockPass());
270 
271   return true;
272 }
273 
274 bool ARMPassConfig::addPreEmitPass() {
275   if (getARMSubtarget().isThumb2()) {
276     if (!getARMSubtarget().prefers32BitThumb())
277       addPass(createThumb2SizeReductionPass());
278 
279     // Constant island pass work on unbundled instructions.
280     addPass(&UnpackMachineBundlesID);
281   }
282 
283   addPass(createARMOptimizeBarriersPass());
284   addPass(createARMConstantIslandPass());
285 
286   return true;
287 }
288