LLVM  3.7.0
ARMTargetMachine.cpp
Go to the documentation of this file.
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"
21 #include "llvm/MC/MCAsmInfo.h"
26 #include "llvm/Transforms/Scalar.h"
27 using namespace llvm;
28 
29 static cl::opt<bool>
30 DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden,
31  cl::desc("Inhibit optimization of S->D register accesses on A15"),
32  cl::init(false));
33 
34 static cl::opt<bool>
35 EnableAtomicTidy("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 
40 static cl::opt<bool>
41 EnableARMLoadStoreOpt("arm-load-store-opt", cl::Hidden,
42  cl::desc("Enable ARM load/store optimization pass"),
43  cl::init(true));
44 
45 // FIXME: Unify control over GlobalMerge.
47 EnableGlobalMerge("arm-global-merge", cl::Hidden,
48  cl::desc("Enable the global merge pass"));
49 
50 extern "C" void LLVMInitializeARMTarget() {
51  // Register the target.
56 }
57 
58 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
59  if (TT.isOSBinFormatMachO())
60  return make_unique<TargetLoweringObjectFileMachO>();
61  if (TT.isOSWindows())
62  return make_unique<TargetLoweringObjectFileCOFF>();
63  return make_unique<ARMElfTargetObjectFile>();
64 }
65 
68  const TargetOptions &Options) {
69  if (Options.MCOptions.getABIName().startswith("aapcs"))
71  else if (Options.MCOptions.getABIName().startswith("apcs"))
73 
74  assert(Options.MCOptions.getABIName().empty() &&
75  "Unknown target-abi option!");
76 
79 
80  // FIXME: This is duplicated code from the front end and should be unified.
81  if (TT.isOSBinFormatMachO()) {
82  if (TT.getEnvironment() == llvm::Triple::EABI ||
84  CPU.startswith("cortex-m")) {
86  } else {
88  }
89  } else if (TT.isOSWindows()) {
90  // FIXME: this is invalid for WindowsCE
92  } else {
93  // Select the default based on the platform.
94  switch (TT.getEnvironment()) {
99  case llvm::Triple::EABI:
101  break;
102  case llvm::Triple::GNU:
104  break;
105  default:
106  if (TT.isOSNetBSD())
108  else
110  break;
111  }
112  }
113 
114  return TargetABI;
115 }
116 
117 static std::string computeDataLayout(const Triple &TT, StringRef CPU,
118  const TargetOptions &Options,
119  bool isLittle) {
120  auto ABI = computeTargetABI(TT, CPU, Options);
121  std::string Ret = "";
122 
123  if (isLittle)
124  // Little endian.
125  Ret += "e";
126  else
127  // Big endian.
128  Ret += "E";
129 
131 
132  // Pointers are 32 bits and aligned to 32 bits.
133  Ret += "-p:32:32";
134 
135  // ABIs other than APCS have 64 bit integers with natural alignment.
137  Ret += "-i64:64";
138 
139  // We have 64 bits floats. The APCS ABI requires them to be aligned to 32
140  // bits, others to 64 bits. We always try to align to 64 bits.
142  Ret += "-f64:32:64";
143 
144  // We have 128 and 64 bit vectors. The APCS ABI aligns them to 32 bits, others
145  // to 64. We always ty to give them natural alignment.
147  Ret += "-v64:32:64-v128:32:128";
148  else
149  Ret += "-v128:64:128";
150 
151  // Try to align aggregates to 32 bits (the default is 64 bits, which has no
152  // particular hardware support on 32-bit ARM).
153  Ret += "-a:0:32";
154 
155  // Integer registers are 32 bits.
156  Ret += "-n32";
157 
158  // The stack is 128 bit aligned on NaCl, 64 bit aligned on AAPCS and 32 bit
159  // aligned everywhere else.
160  if (TT.isOSNaCl())
161  Ret += "-S128";
162  else if (ABI == ARMBaseTargetMachine::ARM_ABI_AAPCS)
163  Ret += "-S64";
164  else
165  Ret += "-S32";
166 
167  return Ret;
168 }
169 
170 /// TargetMachine ctor - Create an ARM architecture model.
171 ///
173  StringRef CPU, StringRef FS,
174  const TargetOptions &Options,
176  CodeGenOpt::Level OL, bool isLittle)
177  : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
178  CPU, FS, Options, RM, CM, OL),
179  TargetABI(computeTargetABI(TT, CPU, Options)),
180  TLOF(createTLOF(getTargetTriple())),
181  Subtarget(TT, CPU, FS, *this, isLittle), isLittle(isLittle) {
182 
183  // Default to triple-appropriate float ABI
184  if (Options.FloatABIType == FloatABI::Default)
185  this->Options.FloatABIType =
187 }
188 
190 
191 const ARMSubtarget *
193  Attribute CPUAttr = F.getFnAttribute("target-cpu");
194  Attribute FSAttr = F.getFnAttribute("target-features");
195 
196  std::string CPU = !CPUAttr.hasAttribute(Attribute::None)
197  ? CPUAttr.getValueAsString().str()
198  : TargetCPU;
199  std::string FS = !FSAttr.hasAttribute(Attribute::None)
200  ? FSAttr.getValueAsString().str()
201  : TargetFS;
202 
203  // FIXME: This is related to the code below to reset the target options,
204  // we need to know whether or not the soft float flag is set on the
205  // function before we can generate a subtarget. We also need to use
206  // it as a key for the subtarget since that can be the only difference
207  // between two functions.
208  bool SoftFloat =
209  F.hasFnAttribute("use-soft-float") &&
210  F.getFnAttribute("use-soft-float").getValueAsString() == "true";
211  // If the soft float attribute is set on the function turn on the soft float
212  // subtarget feature.
213  if (SoftFloat)
214  FS += FS.empty() ? "+soft-float" : ",+soft-float";
215 
216  auto &I = SubtargetMap[CPU + FS];
217  if (!I) {
218  // This needs to be done before we create a new subtarget since any
219  // creation will depend on the TM and the code generation flags on the
220  // function that reside in TargetOptions.
222  I = llvm::make_unique<ARMSubtarget>(TargetTriple, CPU, FS, *this, isLittle);
223  }
224  return I.get();
225 }
226 
228  return TargetIRAnalysis(
229  [this](Function &F) { return TargetTransformInfo(ARMTTIImpl(this, F)); });
230 }
231 
232 
233 void ARMTargetMachine::anchor() { }
234 
236  StringRef CPU, StringRef FS,
237  const TargetOptions &Options,
239  CodeGenOpt::Level OL, bool isLittle)
240  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
241  initAsmInfo();
242  if (!Subtarget.hasARMOps())
243  report_fatal_error("CPU: '" + Subtarget.getCPUString() + "' does not "
244  "support ARM mode execution!");
245 }
246 
247 void ARMLETargetMachine::anchor() { }
248 
250  StringRef CPU, StringRef FS,
251  const TargetOptions &Options,
254  : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
255 
256 void ARMBETargetMachine::anchor() { }
257 
259  StringRef CPU, StringRef FS,
260  const TargetOptions &Options,
263  : ARMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
264 
265 void ThumbTargetMachine::anchor() { }
266 
268  StringRef CPU, StringRef FS,
269  const TargetOptions &Options,
271  CodeGenOpt::Level OL, bool isLittle)
272  : ARMBaseTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, isLittle) {
273  initAsmInfo();
274 }
275 
276 void ThumbLETargetMachine::anchor() { }
277 
279  StringRef CPU, StringRef FS,
280  const TargetOptions &Options,
283  : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
284 
285 void ThumbBETargetMachine::anchor() { }
286 
288  StringRef CPU, StringRef FS,
289  const TargetOptions &Options,
292  : ThumbTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
293 
294 namespace {
295 /// ARM Code Generator Pass Configuration Options.
296 class ARMPassConfig : public TargetPassConfig {
297 public:
298  ARMPassConfig(ARMBaseTargetMachine *TM, PassManagerBase &PM)
299  : TargetPassConfig(TM, PM) {}
300 
301  ARMBaseTargetMachine &getARMTargetMachine() const {
302  return getTM<ARMBaseTargetMachine>();
303  }
304 
305  void addIRPasses() override;
306  bool addPreISel() override;
307  bool addInstSelector() override;
308  void addPreRegAlloc() override;
309  void addPreSched2() override;
310  void addPreEmitPass() override;
311 };
312 } // namespace
313 
315  return new ARMPassConfig(this, PM);
316 }
317 
318 void ARMPassConfig::addIRPasses() {
319  if (TM->Options.ThreadModel == ThreadModel::Single)
320  addPass(createLowerAtomicPass());
321  else
322  addPass(createAtomicExpandPass(TM));
323 
324  // Cmpxchg instructions are often used with a subsequent comparison to
325  // determine whether it succeeded. We can exploit existing control-flow in
326  // ldrex/strex loops to simplify this, but it needs tidying up.
327  if (TM->getOptLevel() != CodeGenOpt::None && EnableAtomicTidy)
328  addPass(createCFGSimplificationPass(-1, [this](const Function &F) {
329  const auto &ST = this->TM->getSubtarget<ARMSubtarget>(F);
330  return ST.hasAnyDataBarrier() && !ST.isThumb1Only();
331  }));
332 
334 
335  // Match interleaved memory accesses to ldN/stN intrinsics.
336  if (TM->getOptLevel() != CodeGenOpt::None)
338 }
339 
340 bool ARMPassConfig::addPreISel() {
341  if ((TM->getOptLevel() != CodeGenOpt::None &&
343  EnableGlobalMerge == cl::BOU_TRUE) {
344  // FIXME: This is using the thumb1 only constant value for
345  // maximal global offset for merging globals. We may want
346  // to look into using the old value for non-thumb1 code of
347  // 4095 based on the TargetMachine, but this starts to become
348  // tricky when doing code gen per function.
349  bool OnlyOptimizeForSize = (TM->getOptLevel() < CodeGenOpt::Aggressive) &&
350  (EnableGlobalMerge == cl::BOU_UNSET);
351  addPass(createGlobalMergePass(TM, 127, OnlyOptimizeForSize));
352  }
353 
354  return false;
355 }
356 
357 bool ARMPassConfig::addInstSelector() {
358  addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
359 
360  if (TM->getTargetTriple().isOSBinFormatELF() && TM->Options.EnableFastISel)
361  addPass(createARMGlobalBaseRegPass());
362  return false;
363 }
364 
365 void ARMPassConfig::addPreRegAlloc() {
366  if (getOptLevel() != CodeGenOpt::None) {
367  addPass(createMLxExpansionPass());
368 
370  addPass(createARMLoadStoreOptimizationPass(/* pre-register alloc */ true));
371 
373  addPass(createA15SDOptimizerPass());
374  }
375 }
376 
377 void ARMPassConfig::addPreSched2() {
378  if (getOptLevel() != CodeGenOpt::None) {
381 
382  addPass(createExecutionDependencyFixPass(&ARM::DPRRegClass));
383  }
384 
385  // Expand some pseudo instructions into multiple instructions to allow
386  // proper scheduling.
387  addPass(createARMExpandPseudoPass());
388 
389  if (getOptLevel() != CodeGenOpt::None) {
390  // in v8, IfConversion depends on Thumb instruction widths
391  addPass(createThumb2SizeReductionPass([this](const Function &F) {
392  return this->TM->getSubtarget<ARMSubtarget>(F).restrictIT();
393  }));
394 
395  addPass(createIfConverter([this](const Function &F) {
396  return !this->TM->getSubtarget<ARMSubtarget>(F).isThumb1Only();
397  }));
398  }
399  addPass(createThumb2ITBlockPass());
400 }
401 
402 void ARMPassConfig::addPreEmitPass() {
404 
405  // Constant island pass work on unbundled instructions.
406  addPass(createUnpackMachineBundles([this](const Function &F) {
407  return this->TM->getSubtarget<ARMSubtarget>(F).isThumb2();
408  }));
409 
410  // Don't optimize barriers at -O0.
411  if (getOptLevel() != CodeGenOpt::None)
413 
414  addPass(createARMConstantIslandPass());
415 }
OSType getOS() const
getOS - Get the parsed operating system type of this triple.
Definition: Triple.h:251
Target TheThumbLETarget
static ARMBaseTargetMachine::ARMABI computeTargetABI(const Triple &TT, StringRef CPU, const TargetOptions &Options)
ThumbTargetMachine - Thumb target machine.
FunctionPass * createA15SDOptimizerPass()
FunctionPass * createMLxExpansionPass()
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition: Triple.h:489
TargetIRAnalysis getTargetIRAnalysis() override
Get the TargetIRAnalysis for this target.
MCTargetOptions MCOptions
Machine level options.
const std::string & getCPUString() const
Definition: ARMSubtarget.h:426
FunctionPass * createARMGlobalBaseRegPass()
virtual void addIRPasses()
Add common target configurable passes that perform LLVM IR to IR transforms following machine indepen...
Definition: Passes.cpp:377
static cl::opt< bool > EnableARMLoadStoreOpt("arm-load-store-opt", cl::Hidden, cl::desc("Enable ARM load/store optimization pass"), cl::init(true))
Triple TargetTriple
Triple string, CPU name, and target feature strings the TargetMachine instance is created with...
FunctionPass * createARMExpandPseudoPass()
createARMExpandPseudoPass - returns an instance of the pseudo instruction expansion pass...
Analysis pass providing the TargetTransformInfo.
FunctionPass * createInterleavedAccessPass(const TargetMachine *TM)
InterleavedAccess Pass - This pass identifies and matches interleaved memory accesses to target speci...
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:188
FunctionPass * createARMOptimizeBarriersPass()
createARMOptimizeBarriersPass - Returns an instance of the remove double barriers pass...
Attribute getFnAttribute(Attribute::AttrKind Kind) const
Return the attribute for the given attribute kind.
Definition: Function.h:225
F(f)
static std::unique_ptr< TargetLoweringObjectFile > createTLOF(const Triple &TT)
bool hasAttribute(AttrKind Val) const
Return true if the attribute is present.
Definition: Attributes.cpp:147
static const char * getManglingComponent(const Triple &T)
Definition: DataLayout.cpp:150
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
bool isOSWindows() const
Tests whether the OS is Windows.
Definition: Triple.h:464
ThumbBETargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL)
FunctionPass * createAtomicExpandPass(const TargetMachine *TM)
No attributes have been set.
Definition: Attributes.h:66
#define false
Definition: ConvertUTF.c:65
Target-Independent Code Generator Pass Configuration Options.
FunctionPass * createARMConstantIslandPass()
createARMConstantIslandPass - returns an instance of the constpool island pass.
This file a TargetTransformInfo::Concept conforming object specific to the ARM target machine...
void LLVMInitializeARMTarget()
bool isOSNaCl() const
Tests whether the OS is NaCl (Native Client)
Definition: Triple.h:469
FunctionPass * createIfConverter(std::function< bool(const Function &)> Ftor)
StringMap< std::unique_ptr< ARMSubtarget > > SubtargetMap
bool hasARMOps() const
Definition: ARMSubtarget.h:312
static std::string computeDataLayout(const Triple &TT, StringRef CPU, const TargetOptions &Options, bool isLittle)
bool isOSNetBSD() const
Definition: Triple.h:408
ARMBaseTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle)
TargetMachine ctor - Create an ARM architecture model.
#define true
Definition: ConvertUTF.c:66
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:325
static cl::opt< bool > DisableA15SDOptimization("disable-a15-sd-optimization", cl::Hidden, cl::desc("Inhibit optimization of S->D register accesses on A15"), cl::init(false))
bool isTargetHardFloat() const
Definition: ARMSubtarget.h:390
const ARMSubtarget * getSubtargetImpl() const
FunctionPass * createCFGSimplificationPass(int Threshold=-1, std::function< bool(const Function &)> Ftor=nullptr)
ARMBETargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL)
FunctionPass * createUnpackMachineBundles(std::function< bool(const Function &)> Ftor)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
This class describes a target machine that is implemented with the LLVM target-independent code gener...
ThumbLETargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL)
static cl::opt< cl::boolOrDefault > EnableGlobalMerge("arm-global-merge", cl::Hidden, cl::desc("Enable the global merge pass"))
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
FunctionPass * createARMLoadStoreOptimizationPass(bool PreAlloc=false)
Returns an instance of the load / store optimization pass.
ARMTargetMachine - ARM target machine.
bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:215
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
FunctionPass * createExecutionDependencyFixPass(const TargetRegisterClass *RC)
createExecutionDependencyFixPass - This pass fixes execution time problems with dependent instruction...
TargetPassConfig * createPassConfig(PassManagerBase &PM) override
Create a pass configuration object to be used by addPassToEmitX methods for generating a pipeline of ...
Pass * createLowerAtomicPass()
ARMTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle)
Target - Wrapper for Target specific information.
ThumbTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle)
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:217
StringRef getABIName() const
getABIName - If this returns a non-empty string this represents the textual name of the ABI that we w...
static cl::opt< bool > EnableAtomicTidy("arm-atomic-cfg-tidy", cl::Hidden, cl::desc("Run SimplifyCFG after expanding atomic operations"" to make use of cmpxchg flow-based information"), cl::init(true))
#define I(x, y, z)
Definition: MD5.cpp:54
Target TheThumbBETarget
void resetTargetOptions(const Function &F) const
Reset the target options based on the function's attributes.
Target TheARMLETarget
Target TheARMBETarget
FunctionPass * createARMISelDag(ARMBaseTargetMachine &TM, CodeGenOpt::Level OptLevel)
createARMISelDag - This pass converts a legalized DAG into a ARM-specific DAG, ready for instruction ...
EnvironmentType getEnvironment() const
getEnvironment - Get the parsed environment type of this triple.
Definition: Triple.h:260
StringRef getValueAsString() const
Return the attribute's value as a string.
Definition: Attributes.cpp:140
RegisterTargetMachine - Helper template for registering a target machine implementation, for use in the target machine initialization function.
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
FunctionPass * createThumb2SizeReductionPass(std::function< bool(const Function &)> Ftor=nullptr)
createThumb2SizeReductionPass - Returns an instance of the Thumb2 size reduction pass.
FunctionPass * createThumb2ITBlockPass()
createThumb2ITBlockPass - Returns an instance of the Thumb2 IT blocks insertion pass.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
ARMLETargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL)
Pass * createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, bool OnlyOptimizeForSize=false)
bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:110
FloatABI::ABIType FloatABIType
FloatABIType - This setting is set by -float-abi=xxx option is specfied on the command line...