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