ARMTargetMachine.cpp revision ebe69fe11e48d322045d5949c83283927a0d790b
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 "ARMFrameLowering.h"
15#include "ARMTargetMachine.h"
16#include "ARMTargetObjectFile.h"
17#include "ARMTargetTransformInfo.h"
18#include "llvm/CodeGen/Passes.h"
19#include "llvm/IR/Function.h"
20#include "llvm/IR/LegacyPassManager.h"
21#include "llvm/MC/MCAsmInfo.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/FormattedStream.h"
24#include "llvm/Support/TargetRegistry.h"
25#include "llvm/Target/TargetOptions.h"
26#include "llvm/Transforms/Scalar.h"
27using namespace llvm;
28
29static cl::opt<bool>
30DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
31                   cl::desc("Inhibit optimization of S->D register accesses on A15"),
32                   cl::init(false));
33
34static cl::opt<bool>
35EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden,
36                 cl::desc("Run SimplifyCFG after expanding atomic operations"
37                          " to make use of cmpxchg flow-based information"),
38                 cl::init(true));
39
40extern "C" void LLVMInitializeARMTarget() {
41  // Register the target.
42  RegisterTargetMachine<ARMLETargetMachine> X(TheARMLETarget);
43  RegisterTargetMachine<ARMBETargetMachine> Y(TheARMBETarget);
44  RegisterTargetMachine<ThumbLETargetMachine> A(TheThumbLETarget);
45  RegisterTargetMachine<ThumbBETargetMachine> B(TheThumbBETarget);
46}
47
48static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
49  if (TT.isOSBinFormatMachO())
50    return make_unique<TargetLoweringObjectFileMachO>();
51  if (TT.isOSWindows())
52    return make_unique<TargetLoweringObjectFileCOFF>();
53  return make_unique<ARMElfTargetObjectFile>();
54}
55
56static ARMBaseTargetMachine::ARMABI
57computeTargetABI(const Triple &TT, StringRef CPU,
58                 const TargetOptions &Options) {
59  if (Options.MCOptions.getABIName().startswith("aapcs"))
60    return ARMBaseTargetMachine::ARM_ABI_AAPCS;
61  else if (Options.MCOptions.getABIName().startswith("apcs"))
62    return ARMBaseTargetMachine::ARM_ABI_APCS;
63
64  assert(Options.MCOptions.getABIName().empty() &&
65         "Unknown target-abi option!");
66
67  ARMBaseTargetMachine::ARMABI TargetABI =
68      ARMBaseTargetMachine::ARM_ABI_UNKNOWN;
69
70  // FIXME: This is duplicated code from the front end and should be unified.
71  if (TT.isOSBinFormatMachO()) {
72    if (TT.getEnvironment() == llvm::Triple::EABI ||
73        (TT.getOS() == llvm::Triple::UnknownOS &&
74         TT.getObjectFormat() == llvm::Triple::MachO) ||
75        CPU.startswith("cortex-m")) {
76      TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
77    } else {
78      TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
79    }
80  } else if (TT.isOSWindows()) {
81    // FIXME: this is invalid for WindowsCE
82    TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
83  } else {
84    // Select the default based on the platform.
85    switch (TT.getEnvironment()) {
86    case llvm::Triple::Android:
87    case llvm::Triple::GNUEABI:
88    case llvm::Triple::GNUEABIHF:
89    case llvm::Triple::EABIHF:
90    case llvm::Triple::EABI:
91      TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
92      break;
93    case llvm::Triple::GNU:
94      TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
95      break;
96    default:
97      if (TT.getOS() == llvm::Triple::NetBSD)
98	TargetABI = ARMBaseTargetMachine::ARM_ABI_APCS;
99      else
100	TargetABI = ARMBaseTargetMachine::ARM_ABI_AAPCS;
101      break;
102    }
103  }
104
105  return TargetABI;
106}
107
108static std::string computeDataLayout(const Triple &TT,
109                                     ARMBaseTargetMachine::ARMABI ABI,
110                                     bool isLittle) {
111  std::string Ret = "";
112
113  if (isLittle)
114    // Little endian.
115    Ret += "e";
116  else
117    // Big endian.
118    Ret += "E";
119
120  Ret += DataLayout::getManglingComponent(TT);
121
122  // Pointers are 32 bits and aligned to 32 bits.
123  Ret += "-p:32:32";
124
125  // ABIs other than APCS have 64 bit integers with natural alignment.
126  if (ABI != ARMBaseTargetMachine::ARM_ABI_APCS)
127    Ret += "-i64:64";
128
129  // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
130  // bits, others to 64 bits. We always try to align to 64 bits.
131  if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
132    Ret += "-f64:32:64";
133
134  // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
135  // to 64. We always ty to give them natural alignment.
136  if (ABI == ARMBaseTargetMachine::ARM_ABI_APCS)
137    Ret += "-v64:32:64-v128:32:128";
138  else
139    Ret += "-v128:64:128";
140
141  // Try to align aggregates to 32 bits (the default is 64 bits, which has no
142  // particular hardware support on 32-bit ARM).
143  Ret += "-a:0:32";
144
145  // Integer registers are 32 bits.
146  Ret += "-n32";
147
148  // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
149  // aligned everywhere else.
150  if (TT.isOSNaCl())
151    Ret += "-S128";
152  else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS)
153    Ret += "-S64";
154  else
155    Ret += "-S32";
156
157  return Ret;
158}
159
160/// TargetMachine ctor - Create an ARM architecture model.
161///
162ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, StringRef TT,
163                                           StringRef CPU, StringRef FS,
164                                           const TargetOptions &Options,
165                                           Reloc::Model RM, CodeModel::Model CM,
166                                           CodeGenOpt::Level OL, bool isLittle)
167    : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
168      TargetABI(computeTargetABI(Triple(TT), CPU, Options)),
169      DL(computeDataLayout(Triple(TT), TargetABI, isLittle)),
170      TLOF(createTLOF(Triple(getTargetTriple()))),
171      Subtarget(TT, CPU, FS, *this, isLittle), isLittle(isLittle) {
172
173  // Default to triple-appropriate float ABI
174  if (Options.FloatABIType == FloatABI::Default)
175    this->Options.FloatABIType =
176        Subtarget.isTargetHardFloat() ? FloatABI::Hard : FloatABI::Soft;
177}
178
179ARMBaseTargetMachine::~ARMBaseTargetMachine() {}
180
181const ARMSubtarget *
182ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
183  Attribute CPUAttr = F.getFnAttribute("target-cpu");
184  Attribute FSAttr = F.getFnAttribute("target-features");
185
186  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
187                        ? CPUAttr.getValueAsString().str()
188                        : TargetCPU;
189  std::string FS = !FSAttr.hasAttribute(Attribute::None)
190                       ? FSAttr.getValueAsString().str()
191                       : TargetFS;
192
193  // FIXME: This is related to the code below to reset the target options,
194  // we need to know whether or not the soft float flag is set on the
195  // function before we can generate a subtarget. We also need to use
196  // it as a key for the subtarget since that can be the only difference
197  // between two functions.
198  Attribute SFAttr = F.getFnAttribute("use-soft-float");
199  bool SoftFloat = !SFAttr.hasAttribute(Attribute::None)
200                       ? SFAttr.getValueAsString() == "true"
201                       : Options.UseSoftFloat;
202
203  auto &I = SubtargetMap[CPU + FS + (SoftFloat ? "use-soft-float=true"
204                                               : "use-soft-float=false")];
205  if (!I) {
206    // This needs to be done before we create a new subtarget since any
207    // creation will depend on the TM and the code generation flags on the
208    // function that reside in TargetOptions.
209    resetTargetOptions(F);
210    I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle);
211  }
212  return I.get();
213}
214
215TargetIRAnalysis ARMBaseTargetMachine::getTargetIRAnalysis() {
216  return TargetIRAnalysis(
217      [this](Function &F) { return TargetTransformInfo(ARMTTIImpl(this, F)); });
218}
219
220
221void ARMTargetMachine::anchor() { }
222
223ARMTargetMachine::ARMTargetMachine(const Target &T, StringRef TT, StringRef CPU,
224                                   StringRef FS, const TargetOptions &Options,
225                                   Reloc::Model RM, CodeModel::Model CM,
226                                   CodeGenOpt::Level OL, bool isLittle)
227    : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
228  initAsmInfo();
229  if (!Subtarget.hasARMOps())
230    report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
231                       "support ARM mode execution!");
232}
233
234void ARMLETargetMachine::anchor() { }
235
236ARMLETargetMachine::ARMLETargetMachine(const Target &T, StringRef TT,
237                                       StringRef CPU, StringRef FS,
238                                       const TargetOptions &Options,
239                                       Reloc::Model RM, CodeModel::Model CM,
240                                       CodeGenOpt::Level OL)
241    : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
242
243void ARMBETargetMachine::anchor() { }
244
245ARMBETargetMachine::ARMBETargetMachine(const Target &T, StringRef TT,
246                                       StringRef CPU, StringRef FS,
247                                       const TargetOptions &Options,
248                                       Reloc::Model RM, CodeModel::Model CM,
249                                       CodeGenOpt::Level OL)
250    : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
251
252void ThumbTargetMachine::anchor() { }
253
254ThumbTargetMachine::ThumbTargetMachine(const Target &T, StringRef TT,
255                                       StringRef CPU, StringRef FS,
256                                       const TargetOptions &Options,
257                                       Reloc::Model RM, CodeModel::Model CM,
258                                       CodeGenOpt::Level OL, bool isLittle)
259    : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL,
260                           isLittle) {
261  initAsmInfo();
262}
263
264void ThumbLETargetMachine::anchor() { }
265
266ThumbLETargetMachine::ThumbLETargetMachine(const Target &T, StringRef TT,
267                                           StringRef CPU, StringRef FS,
268                                           const TargetOptions &Options,
269                                           Reloc::Model RM, CodeModel::Model CM,
270                                           CodeGenOpt::Level OL)
271    : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
272
273void ThumbBETargetMachine::anchor() { }
274
275ThumbBETargetMachine::ThumbBETargetMachine(const Target &T, StringRef TT,
276                                           StringRef CPU, StringRef FS,
277                                           const TargetOptions &Options,
278                                           Reloc::Model RM, CodeModel::Model CM,
279                                           CodeGenOpt::Level OL)
280    : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
281
282namespace {
283/// ARM Code Generator Pass Configuration Options.
284class ARMPassConfig : public TargetPassConfig {
285public:
286  ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
287    : TargetPassConfig(TM, PM) {}
288
289  ARMBaseTargetMachine &getARMTargetMachine() const {
290    return getTM<ARMBaseTargetMachine>();
291  }
292
293  const ARMSubtarget &getARMSubtarget() const {
294    return *getARMTargetMachine().getSubtargetImpl();
295  }
296
297  void addIRPasses() override;
298  bool addPreISel() override;
299  bool addInstSelector() override;
300  void addPreRegAlloc() override;
301  void addPreSched2() override;
302  void addPreEmitPass() override;
303};
304} // namespace
305
306TargetPassConfig *ARMBaseTargetMachine::createPassConfig(PassManagerBase &PM) {
307  return new ARMPassConfig(this, PM);
308}
309
310void ARMPassConfig::addIRPasses() {
311  if (TM->Options.ThreadModel == ThreadModel::Single)
312    addPass(createLowerAtomicPass());
313  else
314    addPass(createAtomicExpandPass(TM));
315
316  // Cmpxchg instructions are often used with a subsequent comparison to
317  // determine whether it succeeded. We can exploit existing control-flow in
318  // ldrex/strex loops to simplify this, but it needs tidying up.
319  const ARMSubtarget *Subtarget = &getARMSubtarget();
320  if (Subtarget->hasAnyDataBarrier() && !Subtarget->isThumb1Only())
321    if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
322      addPass(createCFGSimplificationPass());
323
324  TargetPassConfig::addIRPasses();
325}
326
327bool ARMPassConfig::addPreISel() {
328  if (TM->getOptLevel() != CodeGenOpt::None)
329    // FIXME: This is using the thumb1 only constant value for
330    // maximal global offset for merging globals. We may want
331    // to look into using the old value for non-thumb1 code of
332    // 4095 based on the TargetMachine, but this starts to become
333    // tricky when doing code gen per function.
334    addPass(createGlobalMergePass(TM, 127));
335
336  return false;
337}
338
339bool ARMPassConfig::addInstSelector() {
340  addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
341
342  const ARMSubtarget *Subtarget = &getARMSubtarget();
343  if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
344      TM->Options.EnableFastISel)
345    addPass(createARMGlobalBaseRegPass());
346  return false;
347}
348
349void ARMPassConfig::addPreRegAlloc() {
350  if (getOptLevel() != CodeGenOpt::None)
351    addPass(createARMLoadStoreOptimizationPass(true));
352  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA9())
353    addPass(createMLxExpansionPass());
354  // Since the A15SDOptimizer pass can insert VDUP instructions, it can only be
355  // enabled when NEON is available.
356  if (getOptLevel() != CodeGenOpt::None && getARMSubtarget().isCortexA15() &&
357    getARMSubtarget().hasNEON() && !DisableA15SDOptimization) {
358    addPass(createA15SDOptimizerPass());
359  }
360}
361
362void ARMPassConfig::addPreSched2() {
363  if (getOptLevel() != CodeGenOpt::None) {
364    addPass(createARMLoadStoreOptimizationPass());
365
366    if (getARMSubtarget().hasNEON())
367      addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
368  }
369
370  // Expand some pseudo instructions into multiple instructions to allow
371  // proper scheduling.
372  addPass(createARMExpandPseudoPass());
373
374  if (getOptLevel() != CodeGenOpt::None) {
375    if (!getARMSubtarget().isThumb1Only()) {
376      // in v8, IfConversion depends on Thumb instruction widths
377      if (getARMSubtarget().restrictIT() &&
378          !getARMSubtarget().prefers32BitThumb())
379        addPass(createThumb2SizeReductionPass());
380      addPass(&IfConverterID);
381    }
382  }
383  if (getARMSubtarget().isThumb2())
384    addPass(createThumb2ITBlockPass());
385}
386
387void ARMPassConfig::addPreEmitPass() {
388  if (getARMSubtarget().isThumb2()) {
389    if (!getARMSubtarget().prefers32BitThumb())
390      addPass(createThumb2SizeReductionPass());
391
392    // Constant island pass work on unbundled instructions.
393    addPass(&UnpackMachineBundlesID);
394  }
395
396  addPass(createARMOptimizeBarriersPass());
397  addPass(createARMConstantIslandPass());
398}
399