AMDGPU/SI: Add SI Machine Scheduler
[oota-llvm.git] / lib / Target / AMDGPU / AMDGPUTargetMachine.cpp
1 //===-- AMDGPUTargetMachine.cpp - TargetMachine for hw codegen targets-----===//
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 /// \file
11 /// \brief The AMDGPU target machine contains all of the hardware specific
12 /// information  needed to emit code for R600 and SI GPUs.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #include "AMDGPUTargetMachine.h"
17 #include "AMDGPUTargetObjectFile.h"
18 #include "AMDGPU.h"
19 #include "AMDGPUTargetTransformInfo.h"
20 #include "R600ISelLowering.h"
21 #include "R600InstrInfo.h"
22 #include "R600MachineScheduler.h"
23 #include "SIISelLowering.h"
24 #include "SIInstrInfo.h"
25 #include "llvm/Analysis/Passes.h"
26 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
27 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
28 #include "llvm/CodeGen/MachineModuleInfo.h"
29 #include "llvm/CodeGen/Passes.h"
30 #include "llvm/IR/Verifier.h"
31 #include "llvm/MC/MCAsmInfo.h"
32 #include "llvm/IR/LegacyPassManager.h"
33 #include "llvm/Support/TargetRegistry.h"
34 #include "llvm/Support/raw_os_ostream.h"
35 #include "llvm/Transforms/IPO.h"
36 #include "llvm/Transforms/Scalar.h"
37 #include <llvm/CodeGen/Passes.h>
38
39 using namespace llvm;
40
41 extern "C" void LLVMInitializeAMDGPUTarget() {
42   // Register the target
43   RegisterTargetMachine<R600TargetMachine> X(TheAMDGPUTarget);
44   RegisterTargetMachine<GCNTargetMachine> Y(TheGCNTarget);
45
46   PassRegistry *PR = PassRegistry::getPassRegistry();
47   initializeSILowerI1CopiesPass(*PR);
48   initializeSIFixSGPRCopiesPass(*PR);
49   initializeSIFoldOperandsPass(*PR);
50   initializeSIFixSGPRLiveRangesPass(*PR);
51   initializeSIFixControlFlowLiveIntervalsPass(*PR);
52   initializeSILoadStoreOptimizerPass(*PR);
53   initializeAMDGPUAnnotateKernelFeaturesPass(*PR);
54   initializeAMDGPUAnnotateUniformValuesPass(*PR);
55 }
56
57 static std::unique_ptr<TargetLoweringObjectFile> createTLOF(const Triple &TT) {
58   if (TT.getOS() == Triple::AMDHSA)
59     return make_unique<AMDGPUHSATargetObjectFile>();
60
61   return make_unique<AMDGPUTargetObjectFile>();
62 }
63
64 static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
65   return new ScheduleDAGMILive(C, make_unique<R600SchedStrategy>());
66 }
67
68 static MachineSchedRegistry
69 R600SchedRegistry("r600", "Run R600's custom scheduler",
70                    createR600MachineScheduler);
71
72 static MachineSchedRegistry
73 SISchedRegistry("si", "Run SI's custom scheduler",
74                 createSIMachineScheduler);
75
76 static std::string computeDataLayout(const Triple &TT) {
77   std::string Ret = "e-p:32:32";
78
79   if (TT.getArch() == Triple::amdgcn) {
80     // 32-bit private, local, and region pointers. 64-bit global and constant.
81     Ret += "-p1:64:64-p2:64:64-p3:32:32-p4:64:64-p5:32:32-p24:64:64";
82   }
83
84   Ret += "-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256"
85          "-v512:512-v1024:1024-v2048:2048-n32:64";
86
87   return Ret;
88 }
89
90 AMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, const Triple &TT,
91                                          StringRef CPU, StringRef FS,
92                                          TargetOptions Options, Reloc::Model RM,
93                                          CodeModel::Model CM,
94                                          CodeGenOpt::Level OptLevel)
95     : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, RM, CM,
96                         OptLevel),
97       TLOF(createTLOF(getTargetTriple())), Subtarget(TT, CPU, FS, *this),
98       IntrinsicInfo() {
99   setRequiresStructuredCFG(true);
100   initAsmInfo();
101 }
102
103 AMDGPUTargetMachine::~AMDGPUTargetMachine() { }
104
105 //===----------------------------------------------------------------------===//
106 // R600 Target Machine (R600 -> Cayman)
107 //===----------------------------------------------------------------------===//
108
109 R600TargetMachine::R600TargetMachine(const Target &T, const Triple &TT,
110                                      StringRef FS, StringRef CPU,
111                                      TargetOptions Options, Reloc::Model RM,
112                                      CodeModel::Model CM, CodeGenOpt::Level OL)
113     : AMDGPUTargetMachine(T, TT, FS, CPU, Options, RM, CM, OL) {}
114
115 //===----------------------------------------------------------------------===//
116 // GCN Target Machine (SI+)
117 //===----------------------------------------------------------------------===//
118
119 GCNTargetMachine::GCNTargetMachine(const Target &T, const Triple &TT,
120                                    StringRef FS, StringRef CPU,
121                                    TargetOptions Options, Reloc::Model RM,
122                                    CodeModel::Model CM, CodeGenOpt::Level OL)
123     : AMDGPUTargetMachine(T, TT, FS, CPU, Options, RM, CM, OL) {}
124
125 //===----------------------------------------------------------------------===//
126 // AMDGPU Pass Setup
127 //===----------------------------------------------------------------------===//
128
129 namespace {
130 class AMDGPUPassConfig : public TargetPassConfig {
131 public:
132   AMDGPUPassConfig(TargetMachine *TM, PassManagerBase &PM)
133     : TargetPassConfig(TM, PM) {
134
135     // Exceptions and StackMaps are not supported, so these passes will never do
136     // anything.
137     disablePass(&StackMapLivenessID);
138     disablePass(&FuncletLayoutID);
139   }
140
141   AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
142     return getTM<AMDGPUTargetMachine>();
143   }
144
145   ScheduleDAGInstrs *
146   createMachineScheduler(MachineSchedContext *C) const override {
147     const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl();
148     if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
149       return createR600MachineScheduler(C);
150     return nullptr;
151   }
152
153   void addIRPasses() override;
154   void addCodeGenPrepare() override;
155   bool addPreISel() override;
156   bool addInstSelector() override;
157   bool addGCPasses() override;
158 };
159
160 class R600PassConfig : public AMDGPUPassConfig {
161 public:
162   R600PassConfig(TargetMachine *TM, PassManagerBase &PM)
163     : AMDGPUPassConfig(TM, PM) { }
164
165   bool addPreISel() override;
166   void addPreRegAlloc() override;
167   void addPreSched2() override;
168   void addPreEmitPass() override;
169 };
170
171 class GCNPassConfig : public AMDGPUPassConfig {
172 public:
173   GCNPassConfig(TargetMachine *TM, PassManagerBase &PM)
174     : AMDGPUPassConfig(TM, PM) { }
175   bool addPreISel() override;
176   bool addInstSelector() override;
177   void addFastRegAlloc(FunctionPass *RegAllocPass) override;
178   void addOptimizedRegAlloc(FunctionPass *RegAllocPass) override;
179   void addPreRegAlloc() override;
180   void addPostRegAlloc() override;
181   void addPreSched2() override;
182   void addPreEmitPass() override;
183 };
184
185 } // End of anonymous namespace
186
187 TargetIRAnalysis AMDGPUTargetMachine::getTargetIRAnalysis() {
188   return TargetIRAnalysis([this](const Function &F) {
189     return TargetTransformInfo(
190         AMDGPUTTIImpl(this, F.getParent()->getDataLayout()));
191   });
192 }
193
194 void AMDGPUPassConfig::addIRPasses() {
195   // Function calls are not supported, so make sure we inline everything.
196   addPass(createAMDGPUAlwaysInlinePass());
197   addPass(createAlwaysInlinerPass());
198   // We need to add the barrier noop pass, otherwise adding the function
199   // inlining pass will cause all of the PassConfigs passes to be run
200   // one function at a time, which means if we have a nodule with two
201   // functions, then we will generate code for the first function
202   // without ever running any passes on the second.
203   addPass(createBarrierNoopPass());
204
205   // Handle uses of OpenCL image2d_t, image3d_t and sampler_t arguments.
206   addPass(createAMDGPUOpenCLImageTypeLoweringPass());
207
208   TargetPassConfig::addIRPasses();
209 }
210
211 void AMDGPUPassConfig::addCodeGenPrepare() {
212   const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl();
213   if (ST.isPromoteAllocaEnabled()) {
214     addPass(createAMDGPUPromoteAlloca(ST));
215     addPass(createSROAPass());
216   }
217   TargetPassConfig::addCodeGenPrepare();
218 }
219
220 bool
221 AMDGPUPassConfig::addPreISel() {
222   const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl();
223   addPass(createFlattenCFGPass());
224   if (ST.IsIRStructurizerEnabled())
225     addPass(createStructurizeCFGPass());
226   return false;
227 }
228
229 bool AMDGPUPassConfig::addInstSelector() {
230   addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
231   return false;
232 }
233
234 bool AMDGPUPassConfig::addGCPasses() {
235   // Do nothing. GC is not supported.
236   return false;
237 }
238
239 //===----------------------------------------------------------------------===//
240 // R600 Pass Setup
241 //===----------------------------------------------------------------------===//
242
243 bool R600PassConfig::addPreISel() {
244   AMDGPUPassConfig::addPreISel();
245   addPass(createR600TextureIntrinsicsReplacer());
246   return false;
247 }
248
249 void R600PassConfig::addPreRegAlloc() {
250   addPass(createR600VectorRegMerger(*TM));
251 }
252
253 void R600PassConfig::addPreSched2() {
254   const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl();
255   addPass(createR600EmitClauseMarkers(), false);
256   if (ST.isIfCvtEnabled())
257     addPass(&IfConverterID, false);
258   addPass(createR600ClauseMergePass(*TM), false);
259 }
260
261 void R600PassConfig::addPreEmitPass() {
262   addPass(createAMDGPUCFGStructurizerPass(), false);
263   addPass(createR600ExpandSpecialInstrsPass(*TM), false);
264   addPass(&FinalizeMachineBundlesID, false);
265   addPass(createR600Packetizer(*TM), false);
266   addPass(createR600ControlFlowFinalizer(*TM), false);
267 }
268
269 TargetPassConfig *R600TargetMachine::createPassConfig(PassManagerBase &PM) {
270   return new R600PassConfig(this, PM);
271 }
272
273 //===----------------------------------------------------------------------===//
274 // GCN Pass Setup
275 //===----------------------------------------------------------------------===//
276
277 bool GCNPassConfig::addPreISel() {
278   AMDGPUPassConfig::addPreISel();
279
280   // FIXME: We need to run a pass to propagate the attributes when calls are
281   // supported.
282   addPass(&AMDGPUAnnotateKernelFeaturesID);
283
284   addPass(createSinkingPass());
285   addPass(createSITypeRewriter());
286   addPass(createSIAnnotateControlFlowPass());
287   addPass(createAMDGPUAnnotateUniformValues());
288
289   return false;
290 }
291
292 bool GCNPassConfig::addInstSelector() {
293   AMDGPUPassConfig::addInstSelector();
294   addPass(createSILowerI1CopiesPass());
295   addPass(&SIFixSGPRCopiesID);
296   addPass(createSIFoldOperandsPass());
297   return false;
298 }
299
300 void GCNPassConfig::addPreRegAlloc() {
301   const AMDGPUSubtarget &ST = *getAMDGPUTargetMachine().getSubtargetImpl();
302
303   // This needs to be run directly before register allocation because
304   // earlier passes might recompute live intervals.
305   // TODO: handle CodeGenOpt::None; fast RA ignores spill weights set by the pass
306   if (getOptLevel() > CodeGenOpt::None) {
307     insertPass(&MachineSchedulerID, &SIFixControlFlowLiveIntervalsID);
308   }
309
310   if (getOptLevel() > CodeGenOpt::None && ST.loadStoreOptEnabled()) {
311     // Don't do this with no optimizations since it throws away debug info by
312     // merging nonadjacent loads.
313
314     // This should be run after scheduling, but before register allocation. It
315     // also need extra copies to the address operand to be eliminated.
316     insertPass(&MachineSchedulerID, &SILoadStoreOptimizerID);
317     insertPass(&MachineSchedulerID, &RegisterCoalescerID);
318   }
319   addPass(createSIShrinkInstructionsPass(), false);
320 }
321
322 void GCNPassConfig::addFastRegAlloc(FunctionPass *RegAllocPass) {
323   addPass(&SIFixSGPRLiveRangesID);
324   TargetPassConfig::addFastRegAlloc(RegAllocPass);
325 }
326
327 void GCNPassConfig::addOptimizedRegAlloc(FunctionPass *RegAllocPass) {
328   // We want to run this after LiveVariables is computed to avoid computing them
329   // twice.
330   // FIXME: We shouldn't disable the verifier here. r249087 introduced a failure
331   // that needs to be fixed.
332   insertPass(&LiveVariablesID, &SIFixSGPRLiveRangesID, /*VerifyAfter=*/false);
333   TargetPassConfig::addOptimizedRegAlloc(RegAllocPass);
334 }
335
336 void GCNPassConfig::addPostRegAlloc() {
337   addPass(createSIShrinkInstructionsPass(), false);
338 }
339
340 void GCNPassConfig::addPreSched2() {
341 }
342
343 void GCNPassConfig::addPreEmitPass() {
344   addPass(createSIInsertWaits(*TM), false);
345   addPass(createSILowerControlFlowPass(*TM), false);
346 }
347
348 TargetPassConfig *GCNTargetMachine::createPassConfig(PassManagerBase &PM) {
349   return new GCNPassConfig(this, PM);
350 }