1 //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
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
7 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
15 #include "MCTargetDesc/R600MCTargetDesc.h"
17 #include "R600Subtarget.h"
18 #include "llvm/CodeGen/MachineFunctionPass.h"
22 #define DEBUG_TYPE "r600mergeclause"
26 static bool isCFAlu(const MachineInstr
&MI
) {
27 switch (MI
.getOpcode()) {
29 case R600::CF_ALU_PUSH_BEFORE
:
36 class R600ClauseMergePass
: public MachineFunctionPass
{
39 const R600InstrInfo
*TII
;
41 unsigned getCFAluSize(const MachineInstr
&MI
) const;
42 bool isCFAluEnabled(const MachineInstr
&MI
) const;
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;
50 /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
52 bool mergeIfPossible(MachineInstr
&RootCFAlu
,
53 const MachineInstr
&LatrCFAlu
) const;
58 R600ClauseMergePass() : MachineFunctionPass(ID
) { }
60 bool runOnMachineFunction(MachineFunction
&MF
) override
;
62 StringRef
getPassName() const override
;
65 } // end anonymous namespace
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)
72 char R600ClauseMergePass::ID
= 0;
74 char &llvm::R600ClauseMergePassID
= R600ClauseMergePass::ID
;
76 unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr
&MI
) const {
79 .getOperand(TII
->getOperandIdx(MI
.getOpcode(), R600::OpName::COUNT
))
83 bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr
&MI
) const {
86 .getOperand(TII
->getOperandIdx(MI
.getOpcode(), R600::OpName::Enabled
))
90 void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
91 MachineInstr
&CFAlu
) const {
92 int CntIdx
= TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::COUNT
);
93 MachineBasicBlock::iterator I
= CFAlu
, E
= CFAlu
.getParent()->end();
96 while (I
!= E
&& !isCFAlu(*I
))
100 MachineInstr
&MI
= *I
++;
101 if (isCFAluEnabled(MI
))
103 CFAlu
.getOperand(CntIdx
).setImm(getCFAluSize(CFAlu
) + getCFAluSize(MI
));
104 MI
.eraseFromParent();
108 bool R600ClauseMergePass::mergeIfPossible(MachineInstr
&RootCFAlu
,
109 const MachineInstr
&LatrCFAlu
) const {
110 assert(isCFAlu(RootCFAlu
) && isCFAlu(LatrCFAlu
));
111 int CntIdx
= TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::COUNT
);
112 unsigned RootInstCount
= getCFAluSize(RootCFAlu
),
113 LaterInstCount
= getCFAluSize(LatrCFAlu
);
114 unsigned CumuledInsts
= RootInstCount
+ LaterInstCount
;
115 if (CumuledInsts
>= TII
->getMaxAlusPerClause()) {
116 LLVM_DEBUG(dbgs() << "Excess inst counts\n");
119 if (RootCFAlu
.getOpcode() == R600::CF_ALU_PUSH_BEFORE
)
121 // Is KCache Bank 0 compatible ?
123 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_MODE0
);
125 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_BANK0
);
127 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_ADDR0
);
128 if (LatrCFAlu
.getOperand(Mode0Idx
).getImm() &&
129 RootCFAlu
.getOperand(Mode0Idx
).getImm() &&
130 (LatrCFAlu
.getOperand(KBank0Idx
).getImm() !=
131 RootCFAlu
.getOperand(KBank0Idx
).getImm() ||
132 LatrCFAlu
.getOperand(KBank0LineIdx
).getImm() !=
133 RootCFAlu
.getOperand(KBank0LineIdx
).getImm())) {
134 LLVM_DEBUG(dbgs() << "Wrong KC0\n");
137 // Is KCache Bank 1 compatible ?
139 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_MODE1
);
141 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_BANK1
);
143 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_ADDR1
);
144 if (LatrCFAlu
.getOperand(Mode1Idx
).getImm() &&
145 RootCFAlu
.getOperand(Mode1Idx
).getImm() &&
146 (LatrCFAlu
.getOperand(KBank1Idx
).getImm() !=
147 RootCFAlu
.getOperand(KBank1Idx
).getImm() ||
148 LatrCFAlu
.getOperand(KBank1LineIdx
).getImm() !=
149 RootCFAlu
.getOperand(KBank1LineIdx
).getImm())) {
150 LLVM_DEBUG(dbgs() << "Wrong KC0\n");
153 if (LatrCFAlu
.getOperand(Mode0Idx
).getImm()) {
154 RootCFAlu
.getOperand(Mode0Idx
).setImm(
155 LatrCFAlu
.getOperand(Mode0Idx
).getImm());
156 RootCFAlu
.getOperand(KBank0Idx
).setImm(
157 LatrCFAlu
.getOperand(KBank0Idx
).getImm());
158 RootCFAlu
.getOperand(KBank0LineIdx
)
159 .setImm(LatrCFAlu
.getOperand(KBank0LineIdx
).getImm());
161 if (LatrCFAlu
.getOperand(Mode1Idx
).getImm()) {
162 RootCFAlu
.getOperand(Mode1Idx
).setImm(
163 LatrCFAlu
.getOperand(Mode1Idx
).getImm());
164 RootCFAlu
.getOperand(KBank1Idx
).setImm(
165 LatrCFAlu
.getOperand(KBank1Idx
).getImm());
166 RootCFAlu
.getOperand(KBank1LineIdx
)
167 .setImm(LatrCFAlu
.getOperand(KBank1LineIdx
).getImm());
169 RootCFAlu
.getOperand(CntIdx
).setImm(CumuledInsts
);
170 RootCFAlu
.setDesc(TII
->get(LatrCFAlu
.getOpcode()));
174 bool R600ClauseMergePass::runOnMachineFunction(MachineFunction
&MF
) {
175 if (skipFunction(MF
.getFunction()))
178 const R600Subtarget
&ST
= MF
.getSubtarget
<R600Subtarget
>();
179 TII
= ST
.getInstrInfo();
181 for (MachineBasicBlock
&MBB
: MF
) {
182 MachineBasicBlock::iterator I
= MBB
.begin(), E
= MBB
.end();
183 MachineBasicBlock::iterator LatestCFAlu
= E
;
185 MachineInstr
&MI
= *I
++;
186 if ((!TII
->canBeConsideredALU(MI
) && !isCFAlu(MI
)) ||
187 TII
->mustBeLastInClause(MI
.getOpcode()))
191 cleanPotentialDisabledCFAlu(MI
);
193 if (LatestCFAlu
!= E
&& mergeIfPossible(*LatestCFAlu
, MI
)) {
194 MI
.eraseFromParent();
196 assert(MI
.getOperand(8).getImm() && "CF ALU instruction disabled");
204 StringRef
R600ClauseMergePass::getPassName() const {
205 return "R600 Merge Clause Markers Pass";
208 llvm::FunctionPass
*llvm::createR600ClauseMergePass() {
209 return new R600ClauseMergePass();