1249259Sdim//===-- AMDGPUTargetMachine.cpp - TargetMachine for hw codegen targets-----===//
2249259Sdim//
3249259Sdim//                     The LLVM Compiler Infrastructure
4249259Sdim//
5249259Sdim// This file is distributed under the University of Illinois Open Source
6249259Sdim// License. See LICENSE.TXT for details.
7249259Sdim//
8249259Sdim//===----------------------------------------------------------------------===//
9249259Sdim//
10249259Sdim/// \file
11249259Sdim/// \brief The AMDGPU target machine contains all of the hardware specific
12249259Sdim/// information  needed to emit code for R600 and SI GPUs.
13249259Sdim//
14249259Sdim//===----------------------------------------------------------------------===//
15249259Sdim
16249259Sdim#include "AMDGPUTargetMachine.h"
17249259Sdim#include "AMDGPU.h"
18249259Sdim#include "R600ISelLowering.h"
19249259Sdim#include "R600InstrInfo.h"
20249259Sdim#include "R600MachineScheduler.h"
21249259Sdim#include "SIISelLowering.h"
22249259Sdim#include "SIInstrInfo.h"
23249259Sdim#include "llvm/Analysis/Passes.h"
24249259Sdim#include "llvm/Analysis/Verifier.h"
25249259Sdim#include "llvm/CodeGen/MachineFunctionAnalysis.h"
26249259Sdim#include "llvm/CodeGen/MachineModuleInfo.h"
27249259Sdim#include "llvm/CodeGen/Passes.h"
28249259Sdim#include "llvm/MC/MCAsmInfo.h"
29249259Sdim#include "llvm/PassManager.h"
30249259Sdim#include "llvm/Support/TargetRegistry.h"
31249259Sdim#include "llvm/Support/raw_os_ostream.h"
32249259Sdim#include "llvm/Transforms/IPO.h"
33249259Sdim#include "llvm/Transforms/Scalar.h"
34249259Sdim#include <llvm/CodeGen/Passes.h>
35249259Sdim
36263508Sdim
37249259Sdimusing namespace llvm;
38249259Sdim
39249259Sdimextern "C" void LLVMInitializeR600Target() {
40249259Sdim  // Register the target
41249259Sdim  RegisterTargetMachine<AMDGPUTargetMachine> X(TheAMDGPUTarget);
42249259Sdim}
43249259Sdim
44249259Sdimstatic ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
45249259Sdim  return new ScheduleDAGMI(C, new R600SchedStrategy());
46249259Sdim}
47249259Sdim
48249259Sdimstatic MachineSchedRegistry
49249259SdimSchedCustomRegistry("r600", "Run R600's custom scheduler",
50249259Sdim                    createR600MachineScheduler);
51249259Sdim
52249259SdimAMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, StringRef TT,
53249259Sdim    StringRef CPU, StringRef FS,
54249259Sdim  TargetOptions Options,
55249259Sdim  Reloc::Model RM, CodeModel::Model CM,
56249259Sdim  CodeGenOpt::Level OptLevel
57249259Sdim)
58249259Sdim:
59249259Sdim  LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OptLevel),
60249259Sdim  Subtarget(TT, CPU, FS),
61249259Sdim  Layout(Subtarget.getDataLayout()),
62249259Sdim  FrameLowering(TargetFrameLowering::StackGrowsUp,
63263508Sdim                64 * 16 // Maximum stack alignment (long16)
64263508Sdim               , 0),
65249259Sdim  IntrinsicInfo(this),
66249259Sdim  InstrItins(&Subtarget.getInstrItineraryData()) {
67249259Sdim  // TLInfo uses InstrInfo so it must be initialized after.
68263508Sdim  if (Subtarget.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
69263508Sdim    InstrInfo.reset(new R600InstrInfo(*this));
70263508Sdim    TLInfo.reset(new R600TargetLowering(*this));
71249259Sdim  } else {
72263508Sdim    InstrInfo.reset(new SIInstrInfo(*this));
73263508Sdim    TLInfo.reset(new SITargetLowering(*this));
74249259Sdim  }
75263508Sdim  initAsmInfo();
76249259Sdim}
77249259Sdim
78249259SdimAMDGPUTargetMachine::~AMDGPUTargetMachine() {
79249259Sdim}
80249259Sdim
81249259Sdimnamespace {
82249259Sdimclass AMDGPUPassConfig : public TargetPassConfig {
83249259Sdimpublic:
84249259Sdim  AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
85263508Sdim    : TargetPassConfig(TM, PM) {}
86249259Sdim
87249259Sdim  AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
88249259Sdim    return getTM<AMDGPUTargetMachine>();
89249259Sdim  }
90249259Sdim
91263508Sdim  virtual ScheduleDAGInstrs *
92263508Sdim  createMachineScheduler(MachineSchedContext *C) const {
93263508Sdim    const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
94263508Sdim    if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
95263508Sdim      return createR600MachineScheduler(C);
96263508Sdim    return 0;
97263508Sdim  }
98263508Sdim
99249259Sdim  virtual bool addPreISel();
100249259Sdim  virtual bool addInstSelector();
101249259Sdim  virtual bool addPreRegAlloc();
102249259Sdim  virtual bool addPostRegAlloc();
103249259Sdim  virtual bool addPreSched2();
104249259Sdim  virtual bool addPreEmitPass();
105249259Sdim};
106249259Sdim} // End of anonymous namespace
107249259Sdim
108249259SdimTargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) {
109249259Sdim  return new AMDGPUPassConfig(this, PM);
110249259Sdim}
111249259Sdim
112263508Sdim//===----------------------------------------------------------------------===//
113263508Sdim// AMDGPU Analysis Pass Setup
114263508Sdim//===----------------------------------------------------------------------===//
115263508Sdim
116263508Sdimvoid AMDGPUTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
117263508Sdim  // Add first the target-independent BasicTTI pass, then our AMDGPU pass. This
118263508Sdim  // allows the AMDGPU pass to delegate to the target independent layer when
119263508Sdim  // appropriate.
120263508Sdim  PM.add(createBasicTargetTransformInfoPass(this));
121263508Sdim  PM.add(createAMDGPUTargetTransformInfoPass(this));
122263508Sdim}
123263508Sdim
124249259Sdimbool
125249259SdimAMDGPUPassConfig::addPreISel() {
126249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
127263508Sdim  addPass(createFlattenCFGPass());
128263508Sdim  if (ST.IsIRStructurizerEnabled())
129263508Sdim    addPass(createStructurizeCFGPass());
130263508Sdim  if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
131263508Sdim    addPass(createSinkingPass());
132263508Sdim    addPass(createSITypeRewriter());
133249259Sdim    addPass(createSIAnnotateControlFlowPass());
134263508Sdim  } else {
135263508Sdim    addPass(createR600TextureIntrinsicsReplacer());
136249259Sdim  }
137249259Sdim  return false;
138249259Sdim}
139249259Sdim
140249259Sdimbool AMDGPUPassConfig::addInstSelector() {
141249259Sdim  addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
142249259Sdim  return false;
143249259Sdim}
144249259Sdim
145249259Sdimbool AMDGPUPassConfig::addPreRegAlloc() {
146249259Sdim  addPass(createAMDGPUConvertToISAPass(*TM));
147263508Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
148263508Sdim
149263508Sdim  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
150263508Sdim    addPass(createR600VectorRegMerger(*TM));
151263508Sdim  } else {
152263508Sdim    addPass(createSIFixSGPRCopiesPass(*TM));
153263508Sdim  }
154249259Sdim  return false;
155249259Sdim}
156249259Sdim
157249259Sdimbool AMDGPUPassConfig::addPostRegAlloc() {
158249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
159249259Sdim
160263508Sdim  if (ST.getGeneration() > AMDGPUSubtarget::NORTHERN_ISLANDS) {
161249259Sdim    addPass(createSIInsertWaits(*TM));
162249259Sdim  }
163249259Sdim  return false;
164249259Sdim}
165249259Sdim
166249259Sdimbool AMDGPUPassConfig::addPreSched2() {
167263508Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
168249259Sdim
169263508Sdim  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
170263508Sdim    addPass(createR600EmitClauseMarkers(*TM));
171263508Sdim  if (ST.isIfCvtEnabled())
172263508Sdim    addPass(&IfConverterID);
173263508Sdim  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS)
174263508Sdim    addPass(createR600ClauseMergePass(*TM));
175249259Sdim  return false;
176249259Sdim}
177249259Sdim
178249259Sdimbool AMDGPUPassConfig::addPreEmitPass() {
179249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
180263508Sdim  if (ST.getGeneration() <= AMDGPUSubtarget::NORTHERN_ISLANDS) {
181249259Sdim    addPass(createAMDGPUCFGStructurizerPass(*TM));
182249259Sdim    addPass(createR600ExpandSpecialInstrsPass(*TM));
183251662Sdim    addPass(&FinalizeMachineBundlesID);
184251662Sdim    addPass(createR600Packetizer(*TM));
185249259Sdim    addPass(createR600ControlFlowFinalizer(*TM));
186249259Sdim  } else {
187249259Sdim    addPass(createSILowerControlFlowPass(*TM));
188249259Sdim  }
189249259Sdim
190249259Sdim  return false;
191249259Sdim}
192