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
36249259Sdimusing namespace llvm;
37249259Sdim
38249259Sdimextern "C" void LLVMInitializeR600Target() {
39249259Sdim  // Register the target
40249259Sdim  RegisterTargetMachine<AMDGPUTargetMachine> X(TheAMDGPUTarget);
41249259Sdim}
42249259Sdim
43249259Sdimstatic ScheduleDAGInstrs *createR600MachineScheduler(MachineSchedContext *C) {
44249259Sdim  return new ScheduleDAGMI(C, new R600SchedStrategy());
45249259Sdim}
46249259Sdim
47249259Sdimstatic MachineSchedRegistry
48249259SdimSchedCustomRegistry("r600", "Run R600's custom scheduler",
49249259Sdim                    createR600MachineScheduler);
50249259Sdim
51249259SdimAMDGPUTargetMachine::AMDGPUTargetMachine(const Target &T, StringRef TT,
52249259Sdim    StringRef CPU, StringRef FS,
53249259Sdim  TargetOptions Options,
54249259Sdim  Reloc::Model RM, CodeModel::Model CM,
55249259Sdim  CodeGenOpt::Level OptLevel
56249259Sdim)
57249259Sdim:
58249259Sdim  LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OptLevel),
59249259Sdim  Subtarget(TT, CPU, FS),
60249259Sdim  Layout(Subtarget.getDataLayout()),
61249259Sdim  FrameLowering(TargetFrameLowering::StackGrowsUp,
62249259Sdim      Subtarget.device()->getStackAlignment(), 0),
63249259Sdim  IntrinsicInfo(this),
64249259Sdim  InstrItins(&Subtarget.getInstrItineraryData()) {
65249259Sdim  // TLInfo uses InstrInfo so it must be initialized after.
66249259Sdim  if (Subtarget.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) {
67249259Sdim    InstrInfo = new R600InstrInfo(*this);
68249259Sdim    TLInfo = new R600TargetLowering(*this);
69249259Sdim  } else {
70249259Sdim    InstrInfo = new SIInstrInfo(*this);
71249259Sdim    TLInfo = new SITargetLowering(*this);
72249259Sdim  }
73249259Sdim}
74249259Sdim
75249259SdimAMDGPUTargetMachine::~AMDGPUTargetMachine() {
76249259Sdim}
77249259Sdim
78249259Sdimnamespace {
79249259Sdimclass AMDGPUPassConfig : public TargetPassConfig {
80249259Sdimpublic:
81249259Sdim  AMDGPUPassConfig(AMDGPUTargetMachine *TM, PassManagerBase &PM)
82249259Sdim    : TargetPassConfig(TM, PM) {
83249259Sdim    const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
84249259Sdim    if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) {
85249259Sdim      enablePass(&MachineSchedulerID);
86249259Sdim      MachineSchedRegistry::setDefault(createR600MachineScheduler);
87249259Sdim    }
88249259Sdim  }
89249259Sdim
90249259Sdim  AMDGPUTargetMachine &getAMDGPUTargetMachine() const {
91249259Sdim    return getTM<AMDGPUTargetMachine>();
92249259Sdim  }
93249259Sdim
94249259Sdim  virtual bool addPreISel();
95249259Sdim  virtual bool addInstSelector();
96249259Sdim  virtual bool addPreRegAlloc();
97249259Sdim  virtual bool addPostRegAlloc();
98249259Sdim  virtual bool addPreSched2();
99249259Sdim  virtual bool addPreEmitPass();
100249259Sdim};
101249259Sdim} // End of anonymous namespace
102249259Sdim
103249259SdimTargetPassConfig *AMDGPUTargetMachine::createPassConfig(PassManagerBase &PM) {
104249259Sdim  return new AMDGPUPassConfig(this, PM);
105249259Sdim}
106249259Sdim
107249259Sdimbool
108249259SdimAMDGPUPassConfig::addPreISel() {
109249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
110249259Sdim  if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
111249259Sdim    addPass(createAMDGPUStructurizeCFGPass());
112249259Sdim    addPass(createSIAnnotateControlFlowPass());
113249259Sdim  }
114249259Sdim  return false;
115249259Sdim}
116249259Sdim
117249259Sdimbool AMDGPUPassConfig::addInstSelector() {
118249259Sdim  addPass(createAMDGPUISelDag(getAMDGPUTargetMachine()));
119249259Sdim
120249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
121249259Sdim  if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) {
122249259Sdim    // This callbacks this pass uses are not implemented yet on SI.
123249259Sdim    addPass(createAMDGPUIndirectAddressingPass(*TM));
124249259Sdim  }
125249259Sdim  return false;
126249259Sdim}
127249259Sdim
128249259Sdimbool AMDGPUPassConfig::addPreRegAlloc() {
129249259Sdim  addPass(createAMDGPUConvertToISAPass(*TM));
130249259Sdim  return false;
131249259Sdim}
132249259Sdim
133249259Sdimbool AMDGPUPassConfig::addPostRegAlloc() {
134249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
135249259Sdim
136249259Sdim  if (ST.device()->getGeneration() > AMDGPUDeviceInfo::HD6XXX) {
137249259Sdim    addPass(createSIInsertWaits(*TM));
138249259Sdim  }
139249259Sdim  return false;
140249259Sdim}
141249259Sdim
142249259Sdimbool AMDGPUPassConfig::addPreSched2() {
143249259Sdim
144249259Sdim  addPass(&IfConverterID);
145249259Sdim  return false;
146249259Sdim}
147249259Sdim
148249259Sdimbool AMDGPUPassConfig::addPreEmitPass() {
149249259Sdim  const AMDGPUSubtarget &ST = TM->getSubtarget<AMDGPUSubtarget>();
150249259Sdim  if (ST.device()->getGeneration() <= AMDGPUDeviceInfo::HD6XXX) {
151249259Sdim    addPass(createAMDGPUCFGPreparationPass(*TM));
152249259Sdim    addPass(createAMDGPUCFGStructurizerPass(*TM));
153249259Sdim    addPass(createR600EmitClauseMarkers(*TM));
154249259Sdim    addPass(createR600ExpandSpecialInstrsPass(*TM));
155251662Sdim    addPass(&FinalizeMachineBundlesID);
156251662Sdim    addPass(createR600Packetizer(*TM));
157249259Sdim    addPass(createR600ControlFlowFinalizer(*TM));
158249259Sdim  } else {
159249259Sdim    addPass(createSILowerControlFlowPass(*TM));
160249259Sdim  }
161249259Sdim
162249259Sdim  return false;
163249259Sdim}
164249259Sdim
165