LLVM: lib/Target/AMDGPU/R600EmitClauseMarkers.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
21
22using namespace llvm;
23
24namespace {
25
27private:
28 const R600InstrInfo *TII = nullptr;
29 int Address = 0;
30
31 unsigned OccupiedDwords(MachineInstr &MI) const {
32 switch (MI.getOpcode()) {
33 case R600::INTERP_PAIR_XY:
34 case R600::INTERP_PAIR_ZW:
35 case R600::INTERP_VEC_LOAD:
36 case R600::DOT_4:
37 return 4;
38 case R600::KILL:
39 return 0;
40 default:
41 break;
42 }
43
44
45
46 if (TII->isLDSRetInstr(MI.getOpcode()))
47 return 2;
48
49 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()) ||
50 TII->isReductionOp(MI.getOpcode()))
51 return 4;
52
53 unsigned NumLiteral = 0;
56 It != E; ++It) {
57 MachineOperand &MO = *It;
58 if (MO.isReg() && MO.getReg() == R600::ALU_LITERAL_X)
59 ++NumLiteral;
60 }
61 return 1 + NumLiteral;
62 }
63
64 bool isALU(const MachineInstr &MI) const {
65 if (TII->isALUInstr(MI.getOpcode()))
66 return true;
67 if (TII->isVector(MI) || TII->isCubeOp(MI.getOpcode()))
68 return true;
69 switch (MI.getOpcode()) {
70 case R600::PRED_X:
71 case R600::INTERP_PAIR_XY:
72 case R600::INTERP_PAIR_ZW:
73 case R600::INTERP_VEC_LOAD:
74 case R600::COPY:
75 case R600::DOT_4:
76 return true;
77 default:
78 return false;
79 }
80 }
81
82 bool IsTrivialInst(MachineInstr &MI) const {
83 switch (MI.getOpcode()) {
84 case R600::KILL:
85 case R600::RETURN:
86 case R600::IMPLICIT_DEF:
87 return true;
88 default:
89 return false;
90 }
91 }
92
93 std::pair<unsigned, unsigned> getAccessedBankLine(unsigned Sel) const {
94
95
96
97 return std::pair<unsigned, unsigned>(
98 ((Sel >> 2) - 512) >> 12,
99
100
101
102
103
104 ((((Sel >> 2) - 512) & 4095) >> 5) << 1);
105 }
106
107 bool
108 SubstituteKCacheBank(MachineInstr &MI,
109 std::vector<std::pair<unsigned, unsigned>> &CachedConsts,
110 bool UpdateInstr = true) const {
111 std::vector<std::pair<unsigned, unsigned>> UsedKCache;
112
113 if (!TII->isALUInstr(MI.getOpcode()) && MI.getOpcode() != R600::DOT_4)
114 return true;
115
116 const SmallVectorImpl<std::pair<MachineOperand *, int64_t>> &Consts =
117 TII->getSrcs(MI);
119 (TII->isALUInstr(MI.getOpcode()) || MI.getOpcode() == R600::DOT_4) &&
120 "Can't assign Const");
121 for (auto &[Op, Sel] : Consts) {
122 if (Op->getReg() != R600::ALU_CONST)
123 continue;
124 unsigned Chan = Sel & 3, Index = ((Sel >> 2) - 512) & 31;
125 unsigned KCacheIndex = Index * 4 + Chan;
126 const std::pair<unsigned, unsigned> &BankLine = getAccessedBankLine(Sel);
127 if (CachedConsts.empty()) {
128 CachedConsts.push_back(BankLine);
129 UsedKCache.emplace_back(0, KCacheIndex);
130 continue;
131 }
132 if (CachedConsts[0] == BankLine) {
133 UsedKCache.emplace_back(0, KCacheIndex);
134 continue;
135 }
136 if (CachedConsts.size() == 1) {
137 CachedConsts.push_back(BankLine);
138 UsedKCache.emplace_back(1, KCacheIndex);
139 continue;
140 }
141 if (CachedConsts[1] == BankLine) {
142 UsedKCache.emplace_back(1, KCacheIndex);
143 continue;
144 }
145 return false;
146 }
147
148 if (!UpdateInstr)
149 return true;
150
151 unsigned j = 0;
152 for (auto &[Op, Sel] : Consts) {
153 if (Op->getReg() != R600::ALU_CONST)
154 continue;
155 switch (UsedKCache[j].first) {
156 case 0:
157 Op->setReg(R600::R600_KC0RegClass.getRegister(UsedKCache[j].second));
158 break;
159 case 1:
160 Op->setReg(R600::R600_KC1RegClass.getRegister(UsedKCache[j].second));
161 break;
162 default:
164 }
165 j++;
166 }
167 return true;
168 }
169
170 bool canClauseLocalKillFitInClause(
171 unsigned AluInstCount,
172 std::vector<std::pair<unsigned, unsigned>> KCacheBanks,
175 const R600RegisterInfo &TRI = TII->getRegisterInfo();
176
177 for (MachineOperand &MO : Def->all_defs()) {
178 if (TRI.isPhysRegLiveAcrossClauses(MO.getReg()))
179 continue;
180
181
182
183 unsigned LastUseCount = 0;
185 AluInstCount += OccupiedDwords(*UseI);
186
187 if (!SubstituteKCacheBank(*UseI, KCacheBanks, false))
188 return false;
189
190
191
192
193 if (AluInstCount >= TII->getMaxAlusPerClause())
194 return false;
195
196
197
198
199
200
201
202 if (UseI->readsRegister(MO.getReg(), &TRI))
203 LastUseCount = AluInstCount;
204
205
206 if (UseI != Def && UseI->killsRegister(MO.getReg(), &TRI))
207 break;
208 }
209 if (LastUseCount)
210 return LastUseCount <= TII->getMaxAlusPerClause();
211 llvm_unreachable("Clause local register live at end of clause.");
212 }
213 return true;
214 }
215
219 std::vector<std::pair<unsigned, unsigned>> KCacheBanks;
220 bool PushBeforeModifier = false;
221 unsigned AluInstCount = 0;
223 if (IsTrivialInst(*I))
224 continue;
225 if (!isALU(*I))
226 break;
227 if (AluInstCount > TII->getMaxAlusPerClause())
228 break;
229 if (I->getOpcode() == R600::PRED_X) {
230
231
232
233
234
235
236 if (AluInstCount > 0)
237 break;
238 if (TII->getFlagOp(*I).getImm() & MO_FLAG_PUSH)
239 PushBeforeModifier = true;
240 AluInstCount ++;
241 continue;
242 }
243
244
245
246
247
248
249
250 if (TII->mustBeLastInClause(I->getOpcode())) {
251 I++;
252 break;
253 }
254
255
256
257 if (!canClauseLocalKillFitInClause(AluInstCount, KCacheBanks, I, E))
258 break;
259
260 if (!SubstituteKCacheBank(*I, KCacheBanks))
261 break;
262 AluInstCount += OccupiedDwords(*I);
263 }
264 unsigned Opcode = PushBeforeModifier ?
265 R600::CF_ALU_PUSH_BEFORE : R600::CF_ALU;
267
268
269
270
271 .addImm(Address++)
272 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].first)
273 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].first)
274 .addImm(KCacheBanks.empty()?0:2)
275 .addImm((KCacheBanks.size() < 2)?0:2)
276 .addImm(KCacheBanks.empty()?0:KCacheBanks[0].second)
277 .addImm((KCacheBanks.size() < 2)?0:KCacheBanks[1].second)
278 .addImm(AluInstCount)
279 .addImm(1);
280 return I;
281 }
282
283public:
284 static char ID;
285
286 R600EmitClauseMarkers() : MachineFunctionPass(ID) {}
287
288 bool runOnMachineFunction(MachineFunction &MF) override {
289 const R600Subtarget &ST = MF.getSubtarget();
290 TII = ST.getInstrInfo();
291
292 for (MachineBasicBlock &MBB : MF) {
294 if (I != MBB.end() && I->getOpcode() == R600::CF_ALU)
295 continue;
297 if (isALU(*I)) {
298 auto next = MakeALUClause(MBB, I);
300 I = next;
301 } else
302 ++I;
303 }
304 }
305 return false;
306 }
307
308 StringRef getPassName() const override {
309 return "R600 Emit Clause Markers Pass";
310 }
311};
312
313char R600EmitClauseMarkers::ID = 0;
314
315}
316
318 "R600 Emit Clause Markers", false, false)
321
323 return new R600EmitClauseMarkers();
324}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
FunctionPass class - This class is used to implement most global optimizations.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
NodeAddr< DefNode * > Def
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createR600EmitClauseMarkers()
Definition R600EmitClauseMarkers.cpp:322
DWARFExpression::Operation Op