Move the R600 intrinsic support back to the target machine - there's
[oota-llvm.git] / lib / Target / R600 / 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 "AMDGPU.h"
18 #include "R600ISelLowering.h"
19 #include "R600InstrInfo.h"
20 #include "R600MachineScheduler.h"
21 #include "SIISelLowering.h"
22 #include "SIInstrInfo.h"
23 #include "llvm/Analysis/Passes.h"
24 #include "llvm/CodeGen/MachineFunctionAnalysis.h"
25 #include "llvm/CodeGen/MachineModuleInfo.h"
26 #include "llvm/CodeGen/Passes.h"
27 #include "llvm/IR/Verifier.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/PassManager.h"
30 #include "llvm/Support/TargetRegistry.h"
31 #include "llvm/Support/raw_os_ostream.h"
32 #include "llvm/Transforms/IPO.h"
33 #include "llvm/Transforms/Scalar.h"
34 #include <llvm/CodeGen/Passes.h>
35
36 using namespace llvm;
37
38 extern "C" void LLVMInitializeR600Target() {
39   // Register the target
40   RegisterTargetMachine<AMDGPUTargetMachine> X(TheAMDGPUTarget);
41 }
42
43 static ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
44   return new ScheduleDAGMILive(C, make_unique<R600SchedStrategy>());
45 }
46
47 static MachineSchedRegistry
48 SchedCustomRegistry("r600", "Run R600's custom scheduler",
49                     createR600MachineScheduler);
50
51 AMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, StringRef TT,
52                                          StringRef CPU, StringRef FS,
53                                          TargetOptions Options, Reloc::Model RM,
54                                          CodeModel::Model CM,
55                                          CodeGenOpt::Level OptLevel)
56     : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OptLevel),
57       Subtarget(TT, CPU, FS, *this), IntrinsicInfo() {
58   setRequiresStructuredCFG(true);
59   initAsmInfo();
60 }
61
62 AMDGPUTargetMachine::~AMDGPUTargetMachine() {
63 }
64
65 namespace {
66 class AMDGPUPassConfig : public TargetPassConfig {
67 public:
68   AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
69     : TargetPassConfig(TM, PM) {}
70
71   AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
72     return getTM<AMDGPUTargetMachine>();
73   }
74
75   ScheduleDAGInstrs *
76   createMachineScheduler(MachineSchedContext *C) const override {
77     const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
78     if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
79       return createR600MachineScheduler(C);
80     return nullptr;
81   }
82
83   virtual void addCodeGenPrepare();
84   bool addPreISel() override;
85   bool addInstSelector() override;
86   bool addPreRegAlloc() override;
87   bool addPostRegAlloc() override;
88   bool addPreSched2() override;
89   bool addPreEmitPass() override;
90 };
91 } // End of anonymous namespace
92
93 TargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) {
94   return new AMDGPUPassConfig(this, PM);
95 }
96
97 //===----------------------------------------------------------------------===//
98 // AMDGPU Analysis Pass Setup
99 //===----------------------------------------------------------------------===//
100
101 void AMDGPUTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
102   // Add first the target-independent BasicTTI pass, then our AMDGPU pass. This
103   // allows the AMDGPU pass to delegate to the target independent layer when
104   // appropriate.
105   PM.add(createBasicTargetTransformInfoPass(this));
106   PM.add(createAMDGPUTargetTransformInfoPass(this));
107 }
108
109 void AMDGPUPassConfig::addCodeGenPrepare() {
110   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
111   if (ST.isPromoteAllocaEnabled()) {
112     addPass(createAMDGPUPromoteAlloca(ST));
113     addPass(createSROAPass());
114   }
115
116   TargetPassConfig::addCodeGenPrepare();
117 }
118
119 bool
120 AMDGPUPassConfig::addPreISel() {
121   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
122   addPass(createFlattenCFGPass());
123   if (ST.IsIRStructurizerEnabled())
124     addPass(createStructurizeCFGPass());
125   if (ST.getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) {
126     addPass(createSinkingPass());
127     addPass(createSITypeRewriter());
128     addPass(createSIAnnotateControlFlowPass());
129   } else {
130     addPass(createR600TextureIntrinsicsReplacer());
131   }
132   return false;
133 }
134
135 bool AMDGPUPassConfig::addInstSelector() {
136   addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
137   addPass(createSILowerI1CopiesPass());
138   return false;
139 }
140
141 bool AMDGPUPassConfig::addPreRegAlloc() {
142   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
143
144   if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
145     addPass(createR600VectorRegMerger(*TM));
146   } else {
147     addPass(createSIFixSGPRCopiesPass(*TM));
148     // SIFixSGPRCopies can generate a lot of duplicate instructions,
149     // so we need to run MachineCSE afterwards.
150     addPass(&MachineCSEID);
151     addPass(createSIShrinkInstructionsPass());
152     initializeSIFixSGPRLiveRangesPass(*PassRegistry::getPassRegistry());
153     insertPass(&RegisterCoalescerID, &SIFixSGPRLiveRangesID);
154   }
155   return false;
156 }
157
158 bool AMDGPUPassConfig::addPostRegAlloc() {
159   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
160
161   addPass(createSIShrinkInstructionsPass());
162   if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
163     addPass(createSIInsertWaits(*TM));
164   }
165   return false;
166 }
167
168 bool AMDGPUPassConfig::addPreSched2() {
169   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
170
171   if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
172     addPass(createR600EmitClauseMarkers());
173   if (ST.isIfCvtEnabled())
174     addPass(&IfConverterID);
175   if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
176     addPass(createR600ClauseMergePass(*TM));
177   return false;
178 }
179
180 bool AMDGPUPassConfig::addPreEmitPass() {
181   const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
182   if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
183     addPass(createAMDGPUCFGStructurizerPass());
184     addPass(createR600ExpandSpecialInstrsPass(*TM));
185     addPass(&FinalizeMachineBundlesID);
186     addPass(createR600Packetizer(*TM));
187     addPass(createR600ControlFlowFinalizer(*TM));
188   } else {
189     addPass(createSILowerControlFlowPass(*TM));
190   }
191
192   return false;
193 }