LLVM 20.0.0git
R600ClauseMergePass.cpp
Go to the documentation of this file.
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
16#include "R600.h"
17#include "R600Subtarget.h"
19
20using namespace llvm;
21
22#define DEBUG_TYPE "r600mergeclause"
23
24namespace {
25
26static 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
36class R600ClauseMergePass : public MachineFunctionPass {
37
38private:
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
55public:
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
67INITIALIZE_PASS_BEGIN(R600ClauseMergePass, DEBUG_TYPE,
68 "R600 Clause Merge", false, false)
69INITIALIZE_PASS_END(R600ClauseMergePass, DEBUG_TYPE,
71
72char R600ClauseMergePass::ID = 0;
73
74char &llvm::R600ClauseMergePassID = R600ClauseMergePass::ID;
75
76unsigned R600ClauseMergePass::getCFAluSize(const MachineInstr &MI) const {
77 assert(isCFAlu(MI));
78 return MI
79 .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::COUNT))
80 .getImm();
81}
82
83bool R600ClauseMergePass::isCFAluEnabled(const MachineInstr &MI) const {
84 assert(isCFAlu(MI));
85 return MI
86 .getOperand(TII->getOperandIdx(MI.getOpcode(), R600::OpName::Enabled))
87 .getImm();
88}
89
90void 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();
94 I++;
95 do {
96 while (I != E && !isCFAlu(*I))
97 I++;
98 if (I == E)
99 return;
100 MachineInstr &MI = *I++;
101 if (isCFAluEnabled(MI))
102 break;
103 CFAlu.getOperand(CntIdx).setImm(getCFAluSize(CFAlu) + getCFAluSize(MI));
104 MI.eraseFromParent();
105 } while (I != E);
106}
107
108bool 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");
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(R600::CF_ALU, R600::OpName::KCACHE_MODE0);
124 int KBank0Idx =
125 TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK0);
126 int KBank0LineIdx =
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");
135 return false;
136 }
137 // Is KCache Bank 1 compatible ?
138 int Mode1Idx =
139 TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_MODE1);
140 int KBank1Idx =
141 TII->getOperandIdx(R600::CF_ALU, R600::OpName::KCACHE_BANK1);
142 int KBank1LineIdx =
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");
151 return false;
152 }
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());
160 }
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());
168 }
169 RootCFAlu.getOperand(CntIdx).setImm(CumuledInsts);
170 RootCFAlu.setDesc(TII->get(LatrCFAlu.getOpcode()));
171 return true;
172}
173
174bool R600ClauseMergePass::runOnMachineFunction(MachineFunction &MF) {
175 if (skipFunction(MF.getFunction()))
176 return false;
177
179 TII = ST.getInstrInfo();
180
181 for (MachineBasicBlock &MBB : MF) {
183 MachineBasicBlock::iterator LatestCFAlu = E;
184 while (I != E) {
185 MachineInstr &MI = *I++;
186 if ((!TII->canBeConsideredALU(MI) && !isCFAlu(MI)) ||
187 TII->mustBeLastInClause(MI.getOpcode()))
188 LatestCFAlu = E;
189 if (!isCFAlu(MI))
190 continue;
191 cleanPotentialDisabledCFAlu(MI);
192
193 if (LatestCFAlu != E && mergeIfPossible(*LatestCFAlu, 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
204StringRef R600ClauseMergePass::getPassName() const {
205 return "R600 Merge Clause Markers Pass";
206}
207
209 return new R600ClauseMergePass();
210}
aarch64 promote const
MachineBasicBlock & MBB
#define LLVM_DEBUG(...)
Definition: Debug.h:106
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:57
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
R600 Clause Merge
#define DEBUG_TYPE
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:347
void setDesc(const MCInstrDesc &TID)
Replace the instruction descriptor (thus opcode) of the current instruction with a new one.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
void setImm(int64_t immVal)
int64_t getImm() const
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
char & R600ClauseMergePassID
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
FunctionPass * createR600ClauseMergePass()