xref: /aosp_15_r20/external/llvm/lib/Target/AMDGPU/R600ClauseMergePass.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
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