ARMTargetMachine.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
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"
24using namespace llvm;
25
26static cl::opt<bool>
27DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
28                   cl::desc("Inhibit optimization of S->D register accesses on A15"),
29                   cl::init(false));
30
31static cl::opt<bool>
32EnableAtomicTidy("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
37extern "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///
48ARMBaseTargetMachine::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
62void 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
71void ARMTargetMachine::anchor() { }
72
73ARMTargetMachine::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
84void ARMLETargetMachine::anchor() { }
85
86ARMLETargetMachine::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
93void ARMBETargetMachine::anchor() { }
94
95ARMBETargetMachine::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
102void ThumbTargetMachine::anchor() { }
103
104ThumbTargetMachine::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
114void ThumbLETargetMachine::anchor() { }
115
116ThumbLETargetMachine::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
123void ThumbBETargetMachine::anchor() { }
124
125ThumbBETargetMachine::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
132namespace {
133/// ARM Code Generator Pass Configuration Options.
134class ARMPassConfig : public TargetPassConfig {
135public:
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
156TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
157  return new ARMPassConfig(this, PM);
158}
159
160void 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
174bool ARMPassConfig::addPreISel() {
175  if (TM->getOptLevel() != CodeGenOpt::None)
176    addPass(createGlobalMergePass(TM));
177
178  return false;
179}
180
181bool 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
191bool 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
205bool 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
233bool 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
248bool 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