1*9880d681SAndroid Build Coastguard Worker //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker /// \file
11*9880d681SAndroid Build Coastguard Worker /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative maneer.
12*9880d681SAndroid Build Coastguard Worker /// This pass is merging consecutive CFAlus where applicable.
13*9880d681SAndroid Build Coastguard Worker /// It needs to be called after IfCvt for best results.
14*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*9880d681SAndroid Build Coastguard Worker
16*9880d681SAndroid Build Coastguard Worker #include "AMDGPU.h"
17*9880d681SAndroid Build Coastguard Worker #include "AMDGPUSubtarget.h"
18*9880d681SAndroid Build Coastguard Worker #include "R600Defines.h"
19*9880d681SAndroid Build Coastguard Worker #include "R600InstrInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "R600MachineFunctionInfo.h"
21*9880d681SAndroid Build Coastguard Worker #include "R600RegisterInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker using namespace llvm;
29*9880d681SAndroid Build Coastguard Worker
30*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "r600mergeclause"
31*9880d681SAndroid Build Coastguard Worker
32*9880d681SAndroid Build Coastguard Worker namespace {
33*9880d681SAndroid Build Coastguard Worker
isCFAlu(const MachineInstr & MI)34*9880d681SAndroid Build Coastguard Worker static bool isCFAlu(const MachineInstr &MI) {
35*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
36*9880d681SAndroid Build Coastguard Worker case AMDGPU::CF_ALU:
37*9880d681SAndroid Build Coastguard Worker case AMDGPU::CF_ALU_PUSH_BEFORE:
38*9880d681SAndroid Build Coastguard Worker return true;
39*9880d681SAndroid Build Coastguard Worker default:
40*9880d681SAndroid Build Coastguard Worker return false;
41*9880d681SAndroid Build Coastguard Worker }
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker class R600ClauseMergePass : public MachineFunctionPass {
45*9880d681SAndroid Build Coastguard Worker
46*9880d681SAndroid Build Coastguard Worker private:
47*9880d681SAndroid Build Coastguard Worker static char ID;
48*9880d681SAndroid Build Coastguard Worker const R600InstrInfo *TII;
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Worker unsigned getCFAluSize(const MachineInstr &MI) const;
51*9880d681SAndroid Build Coastguard Worker bool isCFAluEnabled(const MachineInstr &MI) const;
52*9880d681SAndroid Build Coastguard Worker
53*9880d681SAndroid Build Coastguard Worker /// IfCvt pass can generate "disabled" ALU clause marker that need to be
54*9880d681SAndroid Build Coastguard Worker /// removed and their content affected to the previous alu clause.
55*9880d681SAndroid Build Coastguard Worker /// This function parse instructions after CFAlu until it find a disabled
56*9880d681SAndroid Build Coastguard Worker /// CFAlu and merge the content, or an enabled CFAlu.
57*9880d681SAndroid Build Coastguard Worker void cleanPotentialDisabledCFAlu(MachineInstr &CFAlu) const;
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
60*9880d681SAndroid Build Coastguard Worker /// it is the case.
61*9880d681SAndroid Build Coastguard Worker bool mergeIfPossible(MachineInstr &RootCFAlu,
62*9880d681SAndroid Build Coastguard Worker const MachineInstr &LatrCFAlu) const;
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker public:
R600ClauseMergePass(TargetMachine & tm)65*9880d681SAndroid Build Coastguard Worker R600ClauseMergePass(TargetMachine &tm) : MachineFunctionPass(ID) { }
66*9880d681SAndroid Build Coastguard Worker
67*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override;
70*9880d681SAndroid Build Coastguard Worker };
71*9880d681SAndroid Build Coastguard Worker
72*9880d681SAndroid Build Coastguard Worker char R600ClauseMergePass::ID = 0;
73*9880d681SAndroid Build Coastguard Worker
getCFAluSize(const MachineInstr & MI) const74*9880d681SAndroid Build Coastguard Worker unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr &MI) const {
75*9880d681SAndroid Build Coastguard Worker assert(isCFAlu(MI));
76*9880d681SAndroid Build Coastguard Worker return MI
77*9880d681SAndroid Build Coastguard Worker .getOperand(TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::COUNT))
78*9880d681SAndroid Build Coastguard Worker .getImm();
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
isCFAluEnabled(const MachineInstr & MI) const81*9880d681SAndroid Build Coastguard Worker bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr &MI) const {
82*9880d681SAndroid Build Coastguard Worker assert(isCFAlu(MI));
83*9880d681SAndroid Build Coastguard Worker return MI
84*9880d681SAndroid Build Coastguard Worker .getOperand(TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::Enabled))
85*9880d681SAndroid Build Coastguard Worker .getImm();
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker
cleanPotentialDisabledCFAlu(MachineInstr & CFAlu) const88*9880d681SAndroid Build Coastguard Worker void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
89*9880d681SAndroid Build Coastguard Worker MachineInstr &CFAlu) const {
90*9880d681SAndroid Build Coastguard Worker int CntIdx = TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::COUNT);
91*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = CFAlu, E = CFAlu.getParent()->end();
92*9880d681SAndroid Build Coastguard Worker I++;
93*9880d681SAndroid Build Coastguard Worker do {
94*9880d681SAndroid Build Coastguard Worker while (I != E && !isCFAlu(*I))
95*9880d681SAndroid Build Coastguard Worker I++;
96*9880d681SAndroid Build Coastguard Worker if (I == E)
97*9880d681SAndroid Build Coastguard Worker return;
98*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *I++;
99*9880d681SAndroid Build Coastguard Worker if (isCFAluEnabled(MI))
100*9880d681SAndroid Build Coastguard Worker break;
101*9880d681SAndroid Build Coastguard Worker CFAlu.getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI));
102*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
103*9880d681SAndroid Build Coastguard Worker } while (I != E);
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker
mergeIfPossible(MachineInstr & RootCFAlu,const MachineInstr & LatrCFAlu) const106*9880d681SAndroid Build Coastguard Worker bool R600ClauseMergePass::mergeIfPossible(MachineInstr &RootCFAlu,
107*9880d681SAndroid Build Coastguard Worker const MachineInstr &LatrCFAlu) const {
108*9880d681SAndroid Build Coastguard Worker assert(isCFAlu(RootCFAlu) && isCFAlu(LatrCFAlu));
109*9880d681SAndroid Build Coastguard Worker int CntIdx = TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::COUNT);
110*9880d681SAndroid Build Coastguard Worker unsigned RootInstCount = getCFAluSize(RootCFAlu),
111*9880d681SAndroid Build Coastguard Worker LaterInstCount = getCFAluSize(LatrCFAlu);
112*9880d681SAndroid Build Coastguard Worker unsigned CumuledInsts = RootInstCount + LaterInstCount;
113*9880d681SAndroid Build Coastguard Worker if (CumuledInsts >= TII->getMaxAlusPerClause()) {
114*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Excess inst counts\n");
115*9880d681SAndroid Build Coastguard Worker return false;
116*9880d681SAndroid Build Coastguard Worker }
117*9880d681SAndroid Build Coastguard Worker if (RootCFAlu.getOpcode() == AMDGPU::CF_ALU_PUSH_BEFORE)
118*9880d681SAndroid Build Coastguard Worker return false;
119*9880d681SAndroid Build Coastguard Worker // Is KCache Bank 0 compatible ?
120*9880d681SAndroid Build Coastguard Worker int Mode0Idx =
121*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_MODE0);
122*9880d681SAndroid Build Coastguard Worker int KBank0Idx =
123*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_BANK0);
124*9880d681SAndroid Build Coastguard Worker int KBank0LineIdx =
125*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_ADDR0);
126*9880d681SAndroid Build Coastguard Worker if (LatrCFAlu.getOperand(Mode0Idx).getImm() &&
127*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(Mode0Idx).getImm() &&
128*9880d681SAndroid Build Coastguard Worker (LatrCFAlu.getOperand(KBank0Idx).getImm() !=
129*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank0Idx).getImm() ||
130*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(KBank0LineIdx).getImm() !=
131*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank0LineIdx).getImm())) {
132*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Wrong KC0\n");
133*9880d681SAndroid Build Coastguard Worker return false;
134*9880d681SAndroid Build Coastguard Worker }
135*9880d681SAndroid Build Coastguard Worker // Is KCache Bank 1 compatible ?
136*9880d681SAndroid Build Coastguard Worker int Mode1Idx =
137*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_MODE1);
138*9880d681SAndroid Build Coastguard Worker int KBank1Idx =
139*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_BANK1);
140*9880d681SAndroid Build Coastguard Worker int KBank1LineIdx =
141*9880d681SAndroid Build Coastguard Worker TII->getOperandIdx(AMDGPU::CF_ALU, AMDGPU::OpName::KCACHE_ADDR1);
142*9880d681SAndroid Build Coastguard Worker if (LatrCFAlu.getOperand(Mode1Idx).getImm() &&
143*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(Mode1Idx).getImm() &&
144*9880d681SAndroid Build Coastguard Worker (LatrCFAlu.getOperand(KBank1Idx).getImm() !=
145*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank1Idx).getImm() ||
146*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(KBank1LineIdx).getImm() !=
147*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank1LineIdx).getImm())) {
148*9880d681SAndroid Build Coastguard Worker DEBUG(dbgs() << "Wrong KC0\n");
149*9880d681SAndroid Build Coastguard Worker return false;
150*9880d681SAndroid Build Coastguard Worker }
151*9880d681SAndroid Build Coastguard Worker if (LatrCFAlu.getOperand(Mode0Idx).getImm()) {
152*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(Mode0Idx).setImm(
153*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(Mode0Idx).getImm());
154*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank0Idx).setImm(
155*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(KBank0Idx).getImm());
156*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank0LineIdx)
157*9880d681SAndroid Build Coastguard Worker .setImm(LatrCFAlu.getOperand(KBank0LineIdx).getImm());
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker if (LatrCFAlu.getOperand(Mode1Idx).getImm()) {
160*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(Mode1Idx).setImm(
161*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(Mode1Idx).getImm());
162*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank1Idx).setImm(
163*9880d681SAndroid Build Coastguard Worker LatrCFAlu.getOperand(KBank1Idx).getImm());
164*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(KBank1LineIdx)
165*9880d681SAndroid Build Coastguard Worker .setImm(LatrCFAlu.getOperand(KBank1LineIdx).getImm());
166*9880d681SAndroid Build Coastguard Worker }
167*9880d681SAndroid Build Coastguard Worker RootCFAlu.getOperand(CntIdx).setImm(CumuledInsts);
168*9880d681SAndroid Build Coastguard Worker RootCFAlu.setDesc(TII->get(LatrCFAlu.getOpcode()));
169*9880d681SAndroid Build Coastguard Worker return true;
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)172*9880d681SAndroid Build Coastguard Worker bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) {
173*9880d681SAndroid Build Coastguard Worker if (skipFunction(*MF.getFunction()))
174*9880d681SAndroid Build Coastguard Worker return false;
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
177*9880d681SAndroid Build Coastguard Worker TII = ST.getInstrInfo();
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator BB = MF.begin(), BB_E = MF.end();
180*9880d681SAndroid Build Coastguard Worker BB != BB_E; ++BB) {
181*9880d681SAndroid Build Coastguard Worker MachineBasicBlock &MBB = *BB;
182*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
183*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator LatestCFAlu = E;
184*9880d681SAndroid Build Coastguard Worker while (I != E) {
185*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *I++;
186*9880d681SAndroid Build Coastguard Worker if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) ||
187*9880d681SAndroid Build Coastguard Worker TII->mustBeLastInClause(MI.getOpcode()))
188*9880d681SAndroid Build Coastguard Worker LatestCFAlu = E;
189*9880d681SAndroid Build Coastguard Worker if (!isCFAlu(MI))
190*9880d681SAndroid Build Coastguard Worker continue;
191*9880d681SAndroid Build Coastguard Worker cleanPotentialDisabledCFAlu(MI);
192*9880d681SAndroid Build Coastguard Worker
193*9880d681SAndroid Build Coastguard Worker if (LatestCFAlu != E && mergeIfPossible(*LatestCFAlu, MI)) {
194*9880d681SAndroid Build Coastguard Worker MI.eraseFromParent();
195*9880d681SAndroid Build Coastguard Worker } else {
196*9880d681SAndroid Build Coastguard Worker assert(MI.getOperand(8).getImm() && "CF ALU instruction disabled");
197*9880d681SAndroid Build Coastguard Worker LatestCFAlu = MI;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker }
200*9880d681SAndroid Build Coastguard Worker }
201*9880d681SAndroid Build Coastguard Worker return false;
202*9880d681SAndroid Build Coastguard Worker }
203*9880d681SAndroid Build Coastguard Worker
getPassName() const204*9880d681SAndroid Build Coastguard Worker const char *R600ClauseMergePass::getPassName() const {
205*9880d681SAndroid Build Coastguard Worker return "R600 Merge Clause Markers Pass";
206*9880d681SAndroid Build Coastguard Worker }
207*9880d681SAndroid Build Coastguard Worker
208*9880d681SAndroid Build Coastguard Worker } // end anonymous namespace
209*9880d681SAndroid Build Coastguard Worker
210*9880d681SAndroid Build Coastguard Worker
createR600ClauseMergePass(TargetMachine & TM)211*9880d681SAndroid Build Coastguard Worker llvm::FunctionPass *llvm::createR600ClauseMergePass(TargetMachine &TM) {
212*9880d681SAndroid Build Coastguard Worker return new R600ClauseMergePass(TM);
213*9880d681SAndroid Build Coastguard Worker }
214