1185377Ssam//===-- AMDGPUTargetMachine.cpp - TargetMachine for hw codegen targets-----===//
2185377Ssam//
3185377Ssam//                     The LLVM Compiler Infrastructure
4185377Ssam//
5185377Ssam// This file is distributed under the University of Illinois Open Source
6185377Ssam// License. See LICENSE.TXT for details.
7185377Ssam//
8185377Ssam//===----------------------------------------------------------------------===//
9185377Ssam//
10185377Ssam/// \file
11185377Ssam/// \brief The AMDGPU target machine contains all of the hardware specific
12185377Ssam/// information  needed to emit code for R600 and SI GPUs.
13185377Ssam//
14185377Ssam//===----------------------------------------------------------------------===//
15185377Ssam
16185377Ssam#include "AMDGPUTargetMachine.h"
17185377Ssam#include "AMDGPU.h"
18185377Ssam#include "R600ISelLowering.h"
19185377Ssam#include "R600InstrInfo.h"
20185377Ssam#include "R600MachineScheduler.h"
21185377Ssam#include "SIISelLowering.h"
22185377Ssam#include "SIInstrInfo.h"
23185377Ssam#include "llvm/Analysis/Passes.h"
24185377Ssam#include "llvm/Analysis/Verifier.h"
25185377Ssam#include "llvm/CodeGen/MachineFunctionAnalysis.h"
26185377Ssam#include "llvm/CodeGen/MachineModuleInfo.h"
27185377Ssam#include "llvm/CodeGen/Passes.h"
28185377Ssam#include "llvm/MC/MCAsmInfo.h"
29185377Ssam#include "llvm/PassManager.h"
30185377Ssam#include "llvm/Support/TargetRegistry.h"
31185377Ssam#include "llvm/Support/raw_os_ostream.h"
32185377Ssam#include "llvm/Transforms/IPO.h"
33185377Ssam#include "llvm/Transforms/Scalar.h"
34185377Ssam#include <llvm/CodeGen/Passes.h>
35185377Ssam
36185377Ssam
37185377Ssamusing namespace llvm;
38185377Ssam
39185377Ssamextern "C" void LLVMInitializeR600Target() {
40185377Ssam  // Register the target
41185377Ssam  RegisterTargetMachine<AMDGPUTargetMachine> X(TheAMDGPUTarget);
42185377Ssam}
43185377Ssam
44185377Ssamstatic ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
45185377Ssam  return new ScheduleDAGMI(C, new R600SchedStrategy());
46185377Ssam}
47185377Ssam
48185377Ssamstatic MachineSchedRegistry
49185377SsamSchedCustomRegistry("r600", "Run R600's custom scheduler",
50185377Ssam                    createR600MachineScheduler);
51185377Ssam
52185377SsamAMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, StringRef TT,
53185377Ssam    StringRef CPU, StringRef FS,
54185377Ssam  TargetOptions Options,
55185377Ssam  Reloc::Model RM, CodeModel::Model CM,
56185377Ssam  CodeGenOpt::Level OptLevel
57185377Ssam)
58185377Ssam:
59185377Ssam  LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OptLevel),
60185377Ssam  Subtarget(TT, CPU, FS),
61185377Ssam  Layout(Subtarget.getDataLayout()),
62185377Ssam  FrameLowering(TargetFrameLowering::StackGrowsUp,
63185377Ssam                64 * 16 // Maximum stack alignment (long16)
64185377Ssam               , 0),
65185377Ssam  IntrinsicInfo(this),
66185377Ssam  InstrItins(&Subtarget.getInstrItineraryData()) {
67185377Ssam  // TLInfo uses InstrInfo so it must be initialized after.
68185377Ssam  if (Subtarget.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
69185377Ssam    InstrInfo.reset(new R600InstrInfo(*this));
70185377Ssam    TLInfo.reset(new R600TargetLowering(*this));
71185377Ssam  } else {
72185377Ssam    InstrInfo.reset(new SIInstrInfo(*this));
73185377Ssam    TLInfo.reset(new SITargetLowering(*this));
74185377Ssam  }
75185377Ssam  initAsmInfo();
76185377Ssam}
77185377Ssam
78185377SsamAMDGPUTargetMachine::~AMDGPUTargetMachine() {
79185377Ssam}
80185377Ssam
81185377Ssamnamespace {
82185377Ssamclass AMDGPUPassConfig : public TargetPassConfig {
83185377Ssampublic:
84185377Ssam  AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
85185377Ssam    : TargetPassConfig(TM, PM) {}
86185377Ssam
87185377Ssam  AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
88185377Ssam    return getTM<AMDGPUTargetMachine>();
89185377Ssam  }
90185377Ssam
91185377Ssam  virtual ScheduleDAGInstrs *
92185377Ssam  createMachineScheduler(MachineSchedContext *C) const {
93185377Ssam    const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
94185377Ssam    if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
95185377Ssam      return createR600MachineScheduler(C);
96185377Ssam    return 0;
97185377Ssam  }
98185377Ssam
99185377Ssam  virtual bool addPreISel();
100185377Ssam  virtual bool addInstSelector();
101185377Ssam  virtual bool addPreRegAlloc();
102185377Ssam  virtual bool addPostRegAlloc();
103185377Ssam  virtual bool addPreSched2();
104185377Ssam  virtual bool addPreEmitPass();
105185377Ssam};
106185377Ssam} // End of anonymous namespace
107185377Ssam
108185377SsamTargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) {
109185377Ssam  return new AMDGPUPassConfig(this, PM);
110185377Ssam}
111185377Ssam
112185377Ssam//===----------------------------------------------------------------------===//
113185377Ssam// AMDGPU Analysis Pass Setup
114185377Ssam//===----------------------------------------------------------------------===//
115185377Ssam
116185377Ssamvoid AMDGPUTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
117185377Ssam  // Add first the target-independent BasicTTI pass, then our AMDGPU pass. This
118185377Ssam  // allows the AMDGPU pass to delegate to the target independent layer when
119185377Ssam  // appropriate.
120185377Ssam  PM.add(createBasicTargetTransformInfoPass(this));
121185377Ssam  PM.add(createAMDGPUTargetTransformInfoPass(this));
122185377Ssam}
123185377Ssam
124185377Ssambool
125185377SsamAMDGPUPassConfig::addPreISel() {
126185377Ssam  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
127185377Ssam  addPass(createFlattenCFGPass());
128185377Ssam  if (ST.IsIRStructurizerEnabled())
129185377Ssam    addPass(createStructurizeCFGPass());
130185377Ssam  if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
131185377Ssam    addPass(createSinkingPass());
132185377Ssam    addPass(createSITypeRewriter());
133185377Ssam    addPass(createSIAnnotateControlFlowPass());
134185377Ssam  } else {
135185377Ssam    addPass(createR600TextureIntrinsicsReplacer());
136185377Ssam  }
137185377Ssam  return false;
138185377Ssam}
139185377Ssam
140185377Ssambool AMDGPUPassConfig::addInstSelector() {
141185377Ssam  addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
142185377Ssam  return false;
143185377Ssam}
144185377Ssam
145185377Ssambool AMDGPUPassConfig::addPreRegAlloc() {
146185377Ssam  addPass(createAMDGPUConvertToISAPass(*TM));
147185377Ssam  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
148185377Ssam
149185377Ssam  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
150185377Ssam    addPass(createR600VectorRegMerger(*TM));
151185377Ssam  } else {
152185377Ssam    addPass(createSIFixSGPRCopiesPass(*TM));
153185377Ssam  }
154185377Ssam  return false;
155185377Ssam}
156185377Ssam
157185377Ssambool AMDGPUPassConfig::addPostRegAlloc() {
158185377Ssam  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
159185377Ssam
160185377Ssam  if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
161185377Ssam    addPass(createSIInsertWaits(*TM));
162185377Ssam  }
163185377Ssam  return false;
164185377Ssam}
165185377Ssam
166185377Ssambool AMDGPUPassConfig::addPreSched2() {
167185377Ssam  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
168185377Ssam
169185377Ssam  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
170185377Ssam    addPass(createR600EmitClauseMarkers(*TM));
171185377Ssam  if (ST.isIfCvtEnabled())
172185377Ssam    addPass(&IfConverterID);
173185377Ssam  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
174185377Ssam    addPass(createR600ClauseMergePass(*TM));
175185377Ssam  return false;
176185377Ssam}
177185377Ssam
178185377Ssambool AMDGPUPassConfig::addPreEmitPass() {
179185377Ssam  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
180185377Ssam  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
181185377Ssam    addPass(createAMDGPUCFGStructurizerPass(*TM));
182185377Ssam    addPass(createR600ExpandSpecialInstrsPass(*TM));
183185377Ssam    addPass(&FinalizeMachineBundlesID);
184185377Ssam    addPass(createR600Packetizer(*TM));
185185377Ssam    addPass(createR600ControlFlowFinalizer(*TM));
186185377Ssam  } else {
187185377Ssam    addPass(createSILowerControlFlowPass(*TM));
188185377Ssam  }
189185377Ssam
190185377Ssam  return false;
191185377Ssam}
192185377Ssam