[ARM64][fast-isel] Disable target specific optimizations at -O0. Functionally,
[oota-llvm.git] / lib / Target / ARM64 / ARM64TargetMachine.cpp
1 //===-- ARM64TargetMachine.cpp - Define TargetMachine for ARM64 -----------===//
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 "ARM64.h"
14 #include "ARM64TargetMachine.h"
15 #include "llvm/PassManager.h"
16 #include "llvm/CodeGen/Passes.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/TargetRegistry.h"
19 #include "llvm/Target/TargetOptions.h"
20 #include "llvm/Transforms/Scalar.h"
21 using namespace llvm;
22
23 static cl::opt<bool>
24 EnableCCMP("arm64-ccmp", cl::desc("Enable the CCMP formation pass"),
25            cl::init(true), cl::Hidden);
26
27 static cl::opt<bool>
28 EnableEarlyIfConvert("arm64-early-ifcvt", cl::desc("Enable the early if "
29                      "converter pass"), cl::init(true), cl::Hidden);
30
31 static cl::opt<bool>
32 EnableStPairSuppress("arm64-stp-suppress", cl::desc("Suppress STP for ARM64"),
33                      cl::init(true), cl::Hidden);
34
35 static cl::opt<bool>
36 EnableAdvSIMDScalar("arm64-simd-scalar", cl::desc("Enable use of AdvSIMD scalar"
37                     " integer instructions"), cl::init(false), cl::Hidden);
38
39 static cl::opt<bool>
40 EnablePromoteConstant("arm64-promote-const", cl::desc("Enable the promote "
41                       "constant pass"), cl::init(true), cl::Hidden);
42
43 static cl::opt<bool>
44 EnableCollectLOH("arm64-collect-loh", cl::desc("Enable the pass that emits the"
45                  " linker optimization hints (LOH)"), cl::init(true),
46                  cl::Hidden);
47
48 static cl::opt<bool>
49 EnableDeadRegisterElimination("arm64-dead-def-elimination", cl::Hidden,
50                               cl::desc("Enable the pass that removes dead"
51                                        " definitons and replaces stores to"
52                                        " them with stores to the zero"
53                                        " register"),
54                               cl::init(true));
55
56 static cl::opt<bool>
57 EnableLoadStoreOpt("arm64-load-store-opt", cl::desc("Enable the load/store pair"
58                    " optimization pass"), cl::init(true), cl::Hidden);
59
60 extern "C" void LLVMInitializeARM64Target() {
61   // Register the target.
62   RegisterTargetMachine<ARM64leTargetMachine> X(TheARM64leTarget);
63   RegisterTargetMachine<ARM64beTargetMachine> Y(TheARM64beTarget);
64 }
65
66 /// TargetMachine ctor - Create an ARM64 architecture model.
67 ///
68 ARM64TargetMachine::ARM64TargetMachine(const Target &T, StringRef TT,
69                                        StringRef CPU, StringRef FS,
70                                        const TargetOptions &Options,
71                                        Reloc::Model RM, CodeModel::Model CM,
72                                        CodeGenOpt::Level OL,
73                                        bool LittleEndian)
74     : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
75       Subtarget(TT, CPU, FS, LittleEndian),
76       // This nested ternary is horrible, but DL needs to be properly initialized
77       // before TLInfo is constructed.
78       DL(Subtarget.isTargetMachO() ?
79          "e-m:o-i64:64-i128:128-n32:64-S128" :
80          (LittleEndian ?
81           "e-m:e-i64:64-i128:128-n32:64-S128" :
82           "E-m:e-i64:64-i128:128-n32:64-S128")),
83       InstrInfo(Subtarget), TLInfo(*this), FrameLowering(*this, Subtarget),
84       TSInfo(*this) {
85   initAsmInfo();
86 }
87
88 void ARM64leTargetMachine::anchor() { }
89
90 ARM64leTargetMachine::
91 ARM64leTargetMachine(const Target &T, StringRef TT,
92                        StringRef CPU, StringRef FS, const TargetOptions &Options,
93                        Reloc::Model RM, CodeModel::Model CM,
94                        CodeGenOpt::Level OL)
95   : ARM64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
96
97 void ARM64beTargetMachine::anchor() { }
98
99 ARM64beTargetMachine::
100 ARM64beTargetMachine(const Target &T, StringRef TT,
101                        StringRef CPU, StringRef FS, const TargetOptions &Options,
102                        Reloc::Model RM, CodeModel::Model CM,
103                        CodeGenOpt::Level OL)
104   : ARM64TargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
105
106 namespace {
107 /// ARM64 Code Generator Pass Configuration Options.
108 class ARM64PassConfig : public TargetPassConfig {
109 public:
110   ARM64PassConfig(ARM64TargetMachine *TM, PassManagerBase &PM)
111       : TargetPassConfig(TM, PM) {}
112
113   ARM64TargetMachine &getARM64TargetMachine() const {
114     return getTM<ARM64TargetMachine>();
115   }
116
117   bool addPreISel() override;
118   bool addInstSelector() override;
119   bool addILPOpts() override;
120   bool addPreRegAlloc() override;
121   bool addPostRegAlloc() override;
122   bool addPreSched2() override;
123   bool addPreEmitPass() override;
124 };
125 } // namespace
126
127 void ARM64TargetMachine::addAnalysisPasses(PassManagerBase &PM) {
128   // Add first the target-independent BasicTTI pass, then our ARM64 pass. This
129   // allows the ARM64 pass to delegate to the target independent layer when
130   // appropriate.
131   PM.add(createBasicTargetTransformInfoPass(this));
132   PM.add(createARM64TargetTransformInfoPass(this));
133 }
134
135 TargetPassConfig *ARM64TargetMachine::createPassConfig(PassManagerBase &PM) {
136   return new ARM64PassConfig(this, PM);
137 }
138
139 // Pass Pipeline Configuration
140 bool ARM64PassConfig::addPreISel() {
141   // Run promote constant before global merge, so that the promoted constants
142   // get a chance to be merged
143   if (TM->getOptLevel() != CodeGenOpt::None && EnablePromoteConstant)
144     addPass(createARM64PromoteConstantPass());
145   if (TM->getOptLevel() != CodeGenOpt::None)
146     addPass(createGlobalMergePass(TM));
147   if (TM->getOptLevel() != CodeGenOpt::None)
148     addPass(createARM64AddressTypePromotionPass());
149
150   // Always expand atomic operations, we don't deal with atomicrmw or cmpxchg
151   // ourselves.
152   addPass(createAtomicExpandLoadLinkedPass(TM));
153
154   return false;
155 }
156
157 bool ARM64PassConfig::addInstSelector() {
158   addPass(createARM64ISelDag(getARM64TargetMachine(), getOptLevel()));
159
160   // For ELF, cleanup any local-dynamic TLS accesses (i.e. combine as many
161   // references to _TLS_MODULE_BASE_ as possible.
162   if (TM->getSubtarget<ARM64Subtarget>().isTargetELF() &&
163       getOptLevel() != CodeGenOpt::None)
164     addPass(createARM64CleanupLocalDynamicTLSPass());
165
166   return false;
167 }
168
169 bool ARM64PassConfig::addILPOpts() {
170   if (EnableCCMP)
171     addPass(createARM64ConditionalCompares());
172   if (EnableEarlyIfConvert)
173     addPass(&EarlyIfConverterID);
174   if (EnableStPairSuppress)
175     addPass(createARM64StorePairSuppressPass());
176   return true;
177 }
178
179 bool ARM64PassConfig::addPreRegAlloc() {
180   // Use AdvSIMD scalar instructions whenever profitable.
181   if (TM->getOptLevel() != CodeGenOpt::None && EnableAdvSIMDScalar)
182     addPass(createARM64AdvSIMDScalar());
183   return true;
184 }
185
186 bool ARM64PassConfig::addPostRegAlloc() {
187   // Change dead register definitions to refer to the zero register.
188   if (TM->getOptLevel() != CodeGenOpt::None && EnableDeadRegisterElimination)
189     addPass(createARM64DeadRegisterDefinitions());
190   return true;
191 }
192
193 bool ARM64PassConfig::addPreSched2() {
194   // Expand some pseudo instructions to allow proper scheduling.
195   addPass(createARM64ExpandPseudoPass());
196   // Use load/store pair instructions when possible.
197   if (TM->getOptLevel() != CodeGenOpt::None && EnableLoadStoreOpt)
198     addPass(createARM64LoadStoreOptimizationPass());
199   return true;
200 }
201
202 bool ARM64PassConfig::addPreEmitPass() {
203   // Relax conditional branch instructions if they're otherwise out of
204   // range of their destination.
205   addPass(createARM64BranchRelaxation());
206   if (TM->getOptLevel() != CodeGenOpt::None && EnableCollectLOH &&
207       TM->getSubtarget<ARM64Subtarget>().isTargetMachO())
208     addPass(createARM64CollectLOHPass());
209   return true;
210 }