1 //===-- R600ClauseMergePass - Merge consecutive CF_ALU -------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// R600EmitClauseMarker pass emits CFAlu instruction in a conservative maneer.
12 /// This pass is merging consecutive CFAlus where applicable.
13 /// It needs to be called after IfCvt for best results.
14 //===----------------------------------------------------------------------===//
17 #include "AMDGPUSubtarget.h"
18 #include "R600Defines.h"
19 #include "R600InstrInfo.h"
20 #include "R600MachineFunctionInfo.h"
21 #include "R600RegisterInfo.h"
22 #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
23 #include "llvm/CodeGen/MachineFunctionPass.h"
24 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #include "llvm/CodeGen/MachineRegisterInfo.h"
26 #include "llvm/Support/Debug.h"
27 #include "llvm/Support/raw_ostream.h"
31 #define DEBUG_TYPE "r600mergeclause"
35 static bool isCFAlu(const MachineInstr
&MI
) {
36 switch (MI
.getOpcode()) {
38 case R600::CF_ALU_PUSH_BEFORE
:
45 class R600ClauseMergePass
: public MachineFunctionPass
{
48 const R600InstrInfo
*TII
;
50 unsigned getCFAluSize(const MachineInstr
&MI
) const;
51 bool isCFAluEnabled(const MachineInstr
&MI
) const;
53 /// IfCvt pass can generate "disabled" ALU clause marker that need to be
54 /// removed and their content affected to the previous alu clause.
55 /// This function parse instructions after CFAlu until it find a disabled
56 /// CFAlu and merge the content, or an enabled CFAlu.
57 void cleanPotentialDisabledCFAlu(MachineInstr
&CFAlu
) const;
59 /// Check whether LatrCFAlu can be merged into RootCFAlu and do it if
61 bool mergeIfPossible(MachineInstr
&RootCFAlu
,
62 const MachineInstr
&LatrCFAlu
) const;
67 R600ClauseMergePass() : MachineFunctionPass(ID
) { }
69 bool runOnMachineFunction(MachineFunction
&MF
) override
;
71 StringRef
getPassName() const override
;
74 } // end anonymous namespace
76 INITIALIZE_PASS_BEGIN(R600ClauseMergePass
, DEBUG_TYPE
,
77 "R600 Clause Merge", false, false)
78 INITIALIZE_PASS_END(R600ClauseMergePass
, DEBUG_TYPE
,
79 "R600 Clause Merge", false, false)
81 char R600ClauseMergePass::ID
= 0;
83 char &llvm::R600ClauseMergePassID
= R600ClauseMergePass::ID
;
85 unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr
&MI
) const {
88 .getOperand(TII
->getOperandIdx(MI
.getOpcode(), R600::OpName::COUNT
))
92 bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr
&MI
) const {
95 .getOperand(TII
->getOperandIdx(MI
.getOpcode(), R600::OpName::Enabled
))
99 void R600ClauseMergePass::cleanPotentialDisabledCFAlu(
100 MachineInstr
&CFAlu
) const {
101 int CntIdx
= TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::COUNT
);
102 MachineBasicBlock::iterator I
= CFAlu
, E
= CFAlu
.getParent()->end();
105 while (I
!= E
&& !isCFAlu(*I
))
109 MachineInstr
&MI
= *I
++;
110 if (isCFAluEnabled(MI
))
112 CFAlu
.getOperand(CntIdx
).setImm(getCFAluSize(CFAlu
) + getCFAluSize(MI
));
113 MI
.eraseFromParent();
117 bool R600ClauseMergePass::mergeIfPossible(MachineInstr
&RootCFAlu
,
118 const MachineInstr
&LatrCFAlu
) const {
119 assert(isCFAlu(RootCFAlu
) && isCFAlu(LatrCFAlu
));
120 int CntIdx
= TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::COUNT
);
121 unsigned RootInstCount
= getCFAluSize(RootCFAlu
),
122 LaterInstCount
= getCFAluSize(LatrCFAlu
);
123 unsigned CumuledInsts
= RootInstCount
+ LaterInstCount
;
124 if (CumuledInsts
>= TII
->getMaxAlusPerClause()) {
125 LLVM_DEBUG(dbgs() << "Excess inst counts\n");
128 if (RootCFAlu
.getOpcode() == R600::CF_ALU_PUSH_BEFORE
)
130 // Is KCache Bank 0 compatible ?
132 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_MODE0
);
134 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_BANK0
);
136 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_ADDR0
);
137 if (LatrCFAlu
.getOperand(Mode0Idx
).getImm() &&
138 RootCFAlu
.getOperand(Mode0Idx
).getImm() &&
139 (LatrCFAlu
.getOperand(KBank0Idx
).getImm() !=
140 RootCFAlu
.getOperand(KBank0Idx
).getImm() ||
141 LatrCFAlu
.getOperand(KBank0LineIdx
).getImm() !=
142 RootCFAlu
.getOperand(KBank0LineIdx
).getImm())) {
143 LLVM_DEBUG(dbgs() << "Wrong KC0\n");
146 // Is KCache Bank 1 compatible ?
148 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_MODE1
);
150 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_BANK1
);
152 TII
->getOperandIdx(R600::CF_ALU
, R600::OpName::KCACHE_ADDR1
);
153 if (LatrCFAlu
.getOperand(Mode1Idx
).getImm() &&
154 RootCFAlu
.getOperand(Mode1Idx
).getImm() &&
155 (LatrCFAlu
.getOperand(KBank1Idx
).getImm() !=
156 RootCFAlu
.getOperand(KBank1Idx
).getImm() ||
157 LatrCFAlu
.getOperand(KBank1LineIdx
).getImm() !=
158 RootCFAlu
.getOperand(KBank1LineIdx
).getImm())) {
159 LLVM_DEBUG(dbgs() << "Wrong KC0\n");
162 if (LatrCFAlu
.getOperand(Mode0Idx
).getImm()) {
163 RootCFAlu
.getOperand(Mode0Idx
).setImm(
164 LatrCFAlu
.getOperand(Mode0Idx
).getImm());
165 RootCFAlu
.getOperand(KBank0Idx
).setImm(
166 LatrCFAlu
.getOperand(KBank0Idx
).getImm());
167 RootCFAlu
.getOperand(KBank0LineIdx
)
168 .setImm(LatrCFAlu
.getOperand(KBank0LineIdx
).getImm());
170 if (LatrCFAlu
.getOperand(Mode1Idx
).getImm()) {
171 RootCFAlu
.getOperand(Mode1Idx
).setImm(
172 LatrCFAlu
.getOperand(Mode1Idx
).getImm());
173 RootCFAlu
.getOperand(KBank1Idx
).setImm(
174 LatrCFAlu
.getOperand(KBank1Idx
).getImm());
175 RootCFAlu
.getOperand(KBank1LineIdx
)
176 .setImm(LatrCFAlu
.getOperand(KBank1LineIdx
).getImm());
178 RootCFAlu
.getOperand(CntIdx
).setImm(CumuledInsts
);
179 RootCFAlu
.setDesc(TII
->get(LatrCFAlu
.getOpcode()));
183 bool R600ClauseMergePass::runOnMachineFunction(MachineFunction
&MF
) {
184 if (skipFunction(MF
.getFunction()))
187 const R600Subtarget
&ST
= MF
.getSubtarget
<R600Subtarget
>();
188 TII
= ST
.getInstrInfo();
190 for (MachineFunction::iterator BB
= MF
.begin(), BB_E
= MF
.end();
192 MachineBasicBlock
&MBB
= *BB
;
193 MachineBasicBlock::iterator I
= MBB
.begin(), E
= MBB
.end();
194 MachineBasicBlock::iterator LatestCFAlu
= E
;
196 MachineInstr
&MI
= *I
++;
197 if ((!TII
->canBeConsideredALU(MI
) && !isCFAlu(MI
)) ||
198 TII
->mustBeLastInClause(MI
.getOpcode()))
202 cleanPotentialDisabledCFAlu(MI
);
204 if (LatestCFAlu
!= E
&& mergeIfPossible(*LatestCFAlu
, MI
)) {
205 MI
.eraseFromParent();
207 assert(MI
.getOperand(8).getImm() && "CF ALU instruction disabled");
215 StringRef
R600ClauseMergePass::getPassName() const {
216 return "R600 Merge Clause Markers Pass";
219 llvm::FunctionPass
*llvm::createR600ClauseMergePass() {
220 return new R600ClauseMergePass();