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