LLVM 24.0.0git
R600ControlFlowFinalizer.cpp
Go to the documentation of this file.
1//===- R600ControlFlowFinalizer.cpp - Finalize Control Flow Inst ----------===//
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/// This pass compute turns all control flow pseudo instructions into native one
11/// computing their address on the fly; it also sets STACK_SIZE info.
12//
13//===----------------------------------------------------------------------===//
14
16#include "R600.h"
18#include "R600Subtarget.h"
20
21using namespace llvm;
22
23#define DEBUG_TYPE "r600cf"
24
25namespace {
26
27struct CFStack {
28 enum StackItem {
29 ENTRY = 0,
30 SUB_ENTRY = 1,
31 FIRST_NON_WQM_PUSH = 2,
32 FIRST_NON_WQM_PUSH_W_FULL_ENTRY = 3
33 };
34
35 const R600Subtarget *ST;
36 std::vector<StackItem> BranchStack;
37 std::vector<StackItem> LoopStack;
38 unsigned MaxStackSize;
39 unsigned CurrentEntries = 0;
40 unsigned CurrentSubEntries = 0;
41
42 CFStack(const R600Subtarget *st, CallingConv::ID cc) : ST(st),
43 // We need to reserve a stack entry for CALL_FS in vertex shaders.
44 MaxStackSize(cc == CallingConv::AMDGPU_VS ? 1 : 0) {}
45
46 unsigned getLoopDepth();
47 bool branchStackContains(CFStack::StackItem);
48 bool requiresWorkAroundForInst(unsigned Opcode);
49 unsigned getSubEntrySize(CFStack::StackItem Item);
50 void updateMaxStackSize();
51 void pushBranch(unsigned Opcode, bool isWQM = false);
52 void pushLoop();
53 void popBranch();
54 void popLoop();
55};
56
57unsigned CFStack::getLoopDepth() {
58 return LoopStack.size();
59}
60
61bool CFStack::branchStackContains(CFStack::StackItem Item) {
62 return llvm::is_contained(BranchStack, Item);
63}
64
65bool CFStack::requiresWorkAroundForInst(unsigned Opcode) {
66 if (Opcode == R600::CF_ALU_PUSH_BEFORE && ST->hasCaymanISA() &&
67 getLoopDepth() > 1)
68 return true;
69
70 if (!ST->hasCFALUBug())
71 return false;
72
73 switch(Opcode) {
74 default: return false;
75 case R600::CF_ALU_PUSH_BEFORE:
76 case R600::CF_ALU_ELSE_AFTER:
77 case R600::CF_ALU_BREAK:
78 case R600::CF_ALU_CONTINUE:
79 if (CurrentSubEntries == 0)
80 return false;
81 if (ST->getWavefrontSize() == 64) {
82 // We are being conservative here. We only require this work-around if
83 // CurrentSubEntries > 3 &&
84 // (CurrentSubEntries % 4 == 3 || CurrentSubEntries % 4 == 0)
85 //
86 // We have to be conservative, because we don't know for certain that
87 // our stack allocation algorithm for Evergreen/NI is correct. Applying this
88 // work-around when CurrentSubEntries > 3 allows us to over-allocate stack
89 // resources without any problems.
90 return CurrentSubEntries > 3;
91 }
92 assert(ST->getWavefrontSize() == 32);
93 // We are being conservative here. We only require the work-around if
94 // CurrentSubEntries > 7 &&
95 // (CurrentSubEntries % 8 == 7 || CurrentSubEntries % 8 == 0)
96 // See the comment on the wavefront size == 64 case for why we are
97 // being conservative.
98 return CurrentSubEntries > 7;
99 }
100}
101
102unsigned CFStack::getSubEntrySize(CFStack::StackItem Item) {
103 switch(Item) {
104 default:
105 return 0;
106 case CFStack::FIRST_NON_WQM_PUSH:
107 assert(!ST->hasCaymanISA());
109 // +1 For the push operation.
110 // +2 Extra space required.
111 return 3;
112 }
113 // Some documentation says that this is not necessary on Evergreen,
114 // but experimentation has show that we need to allocate 1 extra
115 // sub-entry for the first non-WQM push.
116 // +1 For the push operation.
117 // +1 Extra space required.
118 return 2;
119 case CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY:
121 // +1 For the push operation.
122 // +1 Extra space required.
123 return 2;
124 case CFStack::SUB_ENTRY:
125 return 1;
126 }
127}
128
129void CFStack::updateMaxStackSize() {
130 unsigned CurrentStackSize = CurrentEntries + divideCeil(CurrentSubEntries, 4);
131 MaxStackSize = std::max(CurrentStackSize, MaxStackSize);
132}
133
134void CFStack::pushBranch(unsigned Opcode, bool isWQM) {
135 CFStack::StackItem Item = CFStack::ENTRY;
136 switch(Opcode) {
137 case R600::CF_PUSH_EG:
138 case R600::CF_ALU_PUSH_BEFORE:
139 if (!isWQM) {
140 if (!ST->hasCaymanISA() &&
141 !branchStackContains(CFStack::FIRST_NON_WQM_PUSH))
142 Item = CFStack::FIRST_NON_WQM_PUSH; // May not be required on Evergreen/NI
143 // See comment in
144 // CFStack::getSubEntrySize()
145 else if (CurrentEntries > 0 &&
147 !ST->hasCaymanISA() &&
148 !branchStackContains(CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY))
149 Item = CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY;
150 else
151 Item = CFStack::SUB_ENTRY;
152 } else
153 Item = CFStack::ENTRY;
154 break;
155 }
156 BranchStack.push_back(Item);
157 if (Item == CFStack::ENTRY)
158 CurrentEntries++;
159 else
160 CurrentSubEntries += getSubEntrySize(Item);
161 updateMaxStackSize();
162}
163
164void CFStack::pushLoop() {
165 LoopStack.push_back(CFStack::ENTRY);
166 CurrentEntries++;
167 updateMaxStackSize();
168}
169
170void CFStack::popBranch() {
171 CFStack::StackItem Top = BranchStack.back();
172 if (Top == CFStack::ENTRY)
173 CurrentEntries--;
174 else
175 CurrentSubEntries-= getSubEntrySize(Top);
176 BranchStack.pop_back();
177}
178
179void CFStack::popLoop() {
180 CurrentEntries--;
181 LoopStack.pop_back();
182}
183
184class R600ControlFlowFinalizer : public MachineFunctionPass {
185private:
186 using ClauseFile = std::pair<MachineInstr *, std::vector<MachineInstr *>>;
187
188 enum ControlFlowInstruction {
189 CF_TC,
190 CF_VC,
191 CF_CALL_FS,
192 CF_WHILE_LOOP,
193 CF_END_LOOP,
194 CF_LOOP_BREAK,
195 CF_LOOP_CONTINUE,
196 CF_JUMP,
197 CF_ELSE,
198 CF_POP,
199 CF_END
200 };
201
202 const R600InstrInfo *TII = nullptr;
203 const R600RegisterInfo *TRI = nullptr;
204 unsigned MaxFetchInst;
205 const R600Subtarget *ST = nullptr;
206
207 bool IsTrivialInst(MachineInstr &MI) const {
208 switch (MI.getOpcode()) {
209 case R600::KILL:
210 case R600::RETURN:
211 return true;
212 default:
213 return false;
214 }
215 }
216
217 const MCInstrDesc &getHWInstrDesc(ControlFlowInstruction CFI) const {
218 unsigned Opcode = 0;
219 bool isEg = (ST->getGeneration() >= AMDGPUSubtarget::EVERGREEN);
220 switch (CFI) {
221 case CF_TC:
222 Opcode = isEg ? R600::CF_TC_EG : R600::CF_TC_R600;
223 break;
224 case CF_VC:
225 Opcode = isEg ? R600::CF_VC_EG : R600::CF_VC_R600;
226 break;
227 case CF_CALL_FS:
228 Opcode = isEg ? R600::CF_CALL_FS_EG : R600::CF_CALL_FS_R600;
229 break;
230 case CF_WHILE_LOOP:
231 Opcode = isEg ? R600::WHILE_LOOP_EG : R600::WHILE_LOOP_R600;
232 break;
233 case CF_END_LOOP:
234 Opcode = isEg ? R600::END_LOOP_EG : R600::END_LOOP_R600;
235 break;
236 case CF_LOOP_BREAK:
237 Opcode = isEg ? R600::LOOP_BREAK_EG : R600::LOOP_BREAK_R600;
238 break;
239 case CF_LOOP_CONTINUE:
240 Opcode = isEg ? R600::CF_CONTINUE_EG : R600::CF_CONTINUE_R600;
241 break;
242 case CF_JUMP:
243 Opcode = isEg ? R600::CF_JUMP_EG : R600::CF_JUMP_R600;
244 break;
245 case CF_ELSE:
246 Opcode = isEg ? R600::CF_ELSE_EG : R600::CF_ELSE_R600;
247 break;
248 case CF_POP:
249 Opcode = isEg ? R600::POP_EG : R600::POP_R600;
250 break;
251 case CF_END:
252 if (ST->hasCaymanISA()) {
253 Opcode = R600::CF_END_CM;
254 break;
255 }
256 Opcode = isEg ? R600::CF_END_EG : R600::CF_END_R600;
257 break;
258 }
259 assert (Opcode && "No opcode selected");
260 return TII->get(Opcode);
261 }
262
263 bool isCompatibleWithClause(const MachineInstr &MI,
264 std::set<unsigned> &DstRegs) const {
265 unsigned DstMI, SrcMI;
266 for (MachineInstr::const_mop_iterator I = MI.operands_begin(),
267 E = MI.operands_end();
268 I != E; ++I) {
269 const MachineOperand &MO = *I;
270 if (!MO.isReg())
271 continue;
272 if (MO.isDef()) {
273 Register Reg = MO.getReg();
274 if (R600::R600_Reg128RegClass.contains(Reg))
275 DstMI = Reg;
276 else
277 DstMI = TRI->getMatchingSuperReg(Reg,
279 &R600::R600_Reg128RegClass);
280 }
281 if (MO.isUse()) {
282 Register Reg = MO.getReg();
283 if (R600::R600_Reg128RegClass.contains(Reg))
284 SrcMI = Reg;
285 else
286 SrcMI = TRI->getMatchingSuperReg(Reg,
288 &R600::R600_Reg128RegClass);
289 }
290 }
291 if ((DstRegs.find(SrcMI) == DstRegs.end())) {
292 DstRegs.insert(DstMI);
293 return true;
294 }
295 return false;
296 }
297
298 ClauseFile
300 const {
301 MachineBasicBlock::iterator ClauseHead = I;
302 std::vector<MachineInstr *> ClauseContent;
303 unsigned AluInstCount = 0;
304 bool IsTex = TII->usesTextureCache(*ClauseHead);
305 std::set<unsigned> DstRegs;
306 for (MachineBasicBlock::iterator E = MBB.end(); I != E; ++I) {
307 if (IsTrivialInst(*I))
308 continue;
309 if (AluInstCount >= MaxFetchInst)
310 break;
311 if ((IsTex && !TII->usesTextureCache(*I)) ||
312 (!IsTex && !TII->usesVertexCache(*I)))
313 break;
314 if (!isCompatibleWithClause(*I, DstRegs))
315 break;
316 AluInstCount ++;
317 ClauseContent.push_back(&*I);
318 }
319 MachineInstr *MIb = BuildMI(MBB, ClauseHead, MBB.findDebugLoc(ClauseHead),
320 getHWInstrDesc(IsTex?CF_TC:CF_VC))
321 .addImm(0) // ADDR
322 .addImm(AluInstCount - 1); // COUNT
323 return ClauseFile(MIb, std::move(ClauseContent));
324 }
325
326 void getLiteral(MachineInstr &MI, std::vector<MachineOperand *> &Lits) const {
327 static const unsigned LiteralRegs[] = {
328 R600::ALU_LITERAL_X,
329 R600::ALU_LITERAL_Y,
330 R600::ALU_LITERAL_Z,
331 R600::ALU_LITERAL_W
332 };
334 TII->getSrcs(MI);
335 for (const auto &Src:Srcs) {
336 if (Src.first->getReg() != R600::ALU_LITERAL_X)
337 continue;
338 int64_t Imm = Src.second;
339 std::vector<MachineOperand *>::iterator It =
340 llvm::find_if(Lits, [&](MachineOperand *val) {
341 return val->isImm() && (val->getImm() == Imm);
342 });
343
344 // Get corresponding Operand
345 MachineOperand &Operand = MI.getOperand(
346 TII->getOperandIdx(MI.getOpcode(), R600::OpName::literal));
347
348 if (It != Lits.end()) {
349 // Reuse existing literal reg
350 unsigned Index = It - Lits.begin();
351 Src.first->setReg(LiteralRegs[Index]);
352 } else {
353 // Allocate new literal reg
354 assert(Lits.size() < 4 && "Too many literals in Instruction Group");
355 Src.first->setReg(LiteralRegs[Lits.size()]);
356 Lits.push_back(&Operand);
357 }
358 }
359 }
360
361 MachineBasicBlock::iterator insertLiterals(
363 const std::vector<unsigned> &Literals) const {
364 MachineBasicBlock *MBB = InsertPos->getParent();
365 for (unsigned i = 0, e = Literals.size(); i < e; i+=2) {
366 unsigned LiteralPair0 = Literals[i];
367 unsigned LiteralPair1 = (i + 1 < e)?Literals[i + 1]:0;
368 InsertPos = BuildMI(MBB, InsertPos->getDebugLoc(),
369 TII->get(R600::LITERALS))
370 .addImm(LiteralPair0)
371 .addImm(LiteralPair1);
372 }
373 return InsertPos;
374 }
375
376 ClauseFile
378 const {
379 MachineInstr &ClauseHead = *I;
380 std::vector<MachineInstr *> ClauseContent;
381 I++;
382 for (MachineBasicBlock::instr_iterator E = MBB.instr_end(); I != E;) {
383 if (IsTrivialInst(*I)) {
384 ++I;
385 continue;
386 }
387 if (!I->isBundle() && !TII->isALUInstr(I->getOpcode()))
388 break;
389 std::vector<MachineOperand *>Literals;
390 if (I->isBundle()) {
391 MachineInstr &DeleteMI = *I;
392 MachineBasicBlock::instr_iterator BI = I.getInstrIterator();
393 while (++BI != E && BI->isBundledWithPred()) {
394 BI->unbundleFromPred();
395 for (MachineOperand &MO : BI->operands()) {
396 if (MO.isReg() && MO.isInternalRead())
397 MO.setIsInternalRead(false);
398 }
399 getLiteral(*BI, Literals);
400 ClauseContent.push_back(&*BI);
401 }
402 I = BI;
403 DeleteMI.eraseFromParent();
404 } else {
405 getLiteral(*I, Literals);
406 ClauseContent.push_back(&*I);
407 I++;
408 }
409 for (unsigned i = 0, e = Literals.size(); i < e; i += 2) {
410 MachineInstrBuilder MILit = BuildMI(MBB, I, I->getDebugLoc(),
411 TII->get(R600::LITERALS));
412 if (Literals[i]->isImm()) {
413 MILit.addImm(Literals[i]->getImm());
414 } else {
415 MILit.addGlobalAddress(Literals[i]->getGlobal(),
416 Literals[i]->getOffset());
417 }
418 if (i + 1 < e) {
419 if (Literals[i + 1]->isImm()) {
420 MILit.addImm(Literals[i + 1]->getImm());
421 } else {
422 MILit.addGlobalAddress(Literals[i + 1]->getGlobal(),
423 Literals[i + 1]->getOffset());
424 }
425 } else
426 MILit.addImm(0);
427 ClauseContent.push_back(MILit);
428 }
429 }
430 assert(ClauseContent.size() < 128 && "ALU clause is too big");
431 ClauseHead.getOperand(7).setImm(ClauseContent.size() - 1);
432 return ClauseFile(&ClauseHead, std::move(ClauseContent));
433 }
434
435 void EmitFetchClause(MachineBasicBlock::iterator InsertPos,
436 const DebugLoc &DL, ClauseFile &Clause,
437 unsigned &CfCount) {
438 CounterPropagateAddr(*Clause.first, CfCount);
439 MachineBasicBlock *BB = Clause.first->getParent();
440 BuildMI(BB, DL, TII->get(R600::FETCH_CLAUSE)).addImm(CfCount);
441 for (MachineInstr *MI : Clause.second)
442 BB->splice(InsertPos, BB, MI);
443 CfCount += 2 * Clause.second.size();
444 }
445
446 void EmitALUClause(MachineBasicBlock::iterator InsertPos, const DebugLoc &DL,
447 ClauseFile &Clause, unsigned &CfCount) {
448 Clause.first->getOperand(0).setImm(0);
449 CounterPropagateAddr(*Clause.first, CfCount);
450 MachineBasicBlock *BB = Clause.first->getParent();
451 BuildMI(BB, DL, TII->get(R600::ALU_CLAUSE)).addImm(CfCount);
452 for (MachineInstr *MI : Clause.second)
453 BB->splice(InsertPos, BB, MI);
454 CfCount += Clause.second.size();
455 }
456
457 void CounterPropagateAddr(MachineInstr &MI, unsigned Addr) const {
458 MI.getOperand(0).setImm(Addr + MI.getOperand(0).getImm());
459 }
460 void CounterPropagateAddr(const std::set<MachineInstr *> &MIs,
461 unsigned Addr) const {
462 for (MachineInstr *MI : MIs) {
463 CounterPropagateAddr(*MI, Addr);
464 }
465 }
466
467public:
468 static char ID;
469
470 R600ControlFlowFinalizer() : MachineFunctionPass(ID) {}
471
472 bool runOnMachineFunction(MachineFunction &MF) override {
473 ST = &MF.getSubtarget<R600Subtarget>();
474 MaxFetchInst = ST->getTexVTXClauseSize();
475 TII = ST->getInstrInfo();
476 TRI = ST->getRegisterInfo();
477
479
480 CFStack CFStack(ST, MF.getFunction().getCallingConv());
481 for (MachineFunction::iterator MB = MF.begin(), ME = MF.end(); MB != ME;
482 ++MB) {
483 MachineBasicBlock &MBB = *MB;
484 unsigned CfCount = 0;
485 std::vector<std::pair<unsigned, std::set<MachineInstr *>>> LoopStack;
486 std::vector<MachineInstr * > IfThenElseStack;
488 BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()),
489 getHWInstrDesc(CF_CALL_FS));
490 CfCount++;
491 }
492 std::vector<ClauseFile> FetchClauses, AluClauses;
493 std::vector<MachineInstr *> LastAlu(1);
494 std::vector<MachineInstr *> ToPopAfter;
495
496 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
497 I != E;) {
498 if (TII->usesTextureCache(*I) || TII->usesVertexCache(*I)) {
499 LLVM_DEBUG(dbgs() << CfCount << ":"; I->dump(););
500 FetchClauses.push_back(MakeFetchClause(MBB, I));
501 CfCount++;
502 LastAlu.back() = nullptr;
503 continue;
504 }
505
507 if (MI->getOpcode() != R600::ENDIF)
508 LastAlu.back() = nullptr;
509 if (MI->getOpcode() == R600::CF_ALU)
510 LastAlu.back() = &*MI;
511 I++;
512 bool RequiresWorkAround =
513 CFStack.requiresWorkAroundForInst(MI->getOpcode());
514 switch (MI->getOpcode()) {
515 case R600::CF_ALU_PUSH_BEFORE:
516 if (RequiresWorkAround) {
518 << "Applying bug work-around for ALU_PUSH_BEFORE\n");
519 BuildMI(MBB, MI, MBB.findDebugLoc(MI), TII->get(R600::CF_PUSH_EG))
520 .addImm(CfCount + 1)
521 .addImm(1);
522 MI->setDesc(TII->get(R600::CF_ALU));
523 CfCount++;
524 CFStack.pushBranch(R600::CF_PUSH_EG);
525 } else
526 CFStack.pushBranch(R600::CF_ALU_PUSH_BEFORE);
527 [[fallthrough]];
528 case R600::CF_ALU:
529 I = MI;
530 AluClauses.push_back(MakeALUClause(MBB, I));
531 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););
532 CfCount++;
533 break;
534 case R600::WHILELOOP: {
535 CFStack.pushLoop();
536 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
537 getHWInstrDesc(CF_WHILE_LOOP))
538 .addImm(1);
539 std::pair<unsigned, std::set<MachineInstr *>> Pair(CfCount,
540 std::set<MachineInstr *>());
541 Pair.second.insert(MIb);
542 LoopStack.push_back(std::move(Pair));
543 MI->eraseFromParent();
544 CfCount++;
545 break;
546 }
547 case R600::ENDLOOP: {
548 CFStack.popLoop();
549 std::pair<unsigned, std::set<MachineInstr *>> Pair =
550 std::move(LoopStack.back());
551 LoopStack.pop_back();
552 CounterPropagateAddr(Pair.second, CfCount);
553 BuildMI(MBB, MI, MBB.findDebugLoc(MI), getHWInstrDesc(CF_END_LOOP))
554 .addImm(Pair.first + 1);
555 MI->eraseFromParent();
556 CfCount++;
557 break;
558 }
559 case R600::IF_PREDICATE_SET: {
560 LastAlu.push_back(nullptr);
561 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
562 getHWInstrDesc(CF_JUMP))
563 .addImm(0)
564 .addImm(0);
565 IfThenElseStack.push_back(MIb);
566 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
567 MI->eraseFromParent();
568 CfCount++;
569 break;
570 }
571 case R600::ELSE: {
572 MachineInstr * JumpInst = IfThenElseStack.back();
573 IfThenElseStack.pop_back();
574 CounterPropagateAddr(*JumpInst, CfCount);
575 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
576 getHWInstrDesc(CF_ELSE))
577 .addImm(0)
578 .addImm(0);
579 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
580 IfThenElseStack.push_back(MIb);
581 MI->eraseFromParent();
582 CfCount++;
583 break;
584 }
585 case R600::ENDIF: {
586 CFStack.popBranch();
587 if (LastAlu.back()) {
588 ToPopAfter.push_back(LastAlu.back());
589 } else {
590 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
591 getHWInstrDesc(CF_POP))
592 .addImm(CfCount + 1)
593 .addImm(1);
594 (void)MIb;
595 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
596 CfCount++;
597 }
598
599 MachineInstr *IfOrElseInst = IfThenElseStack.back();
600 IfThenElseStack.pop_back();
601 CounterPropagateAddr(*IfOrElseInst, CfCount);
602 IfOrElseInst->getOperand(1).setImm(1);
603 LastAlu.pop_back();
604 MI->eraseFromParent();
605 break;
606 }
607 case R600::BREAK: {
608 CfCount ++;
609 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
610 getHWInstrDesc(CF_LOOP_BREAK))
611 .addImm(0);
612 LoopStack.back().second.insert(MIb);
613 MI->eraseFromParent();
614 break;
615 }
616 case R600::CONTINUE: {
617 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
618 getHWInstrDesc(CF_LOOP_CONTINUE))
619 .addImm(0);
620 LoopStack.back().second.insert(MIb);
621 MI->eraseFromParent();
622 CfCount++;
623 break;
624 }
625 case R600::RETURN: {
626 DebugLoc DL = MBB.findDebugLoc(MI);
627 BuildMI(MBB, MI, DL, getHWInstrDesc(CF_END));
628 CfCount++;
629 if (CfCount % 2) {
630 BuildMI(MBB, I, DL, TII->get(R600::PAD));
631 CfCount++;
632 }
633 MI->eraseFromParent();
634 for (ClauseFile &CF : FetchClauses)
635 EmitFetchClause(I, DL, CF, CfCount);
636 for (ClauseFile &CF : AluClauses)
637 EmitALUClause(I, DL, CF, CfCount);
638 break;
639 }
640 default:
641 if (TII->isExport(MI->getOpcode())) {
642 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););
643 CfCount++;
644 }
645 break;
646 }
647 }
648 for (MachineInstr *Alu : ToPopAfter) {
649 BuildMI(MBB, Alu, MBB.findDebugLoc((MachineBasicBlock::iterator)Alu),
650 TII->get(R600::CF_ALU_POP_AFTER))
651 .addImm(Alu->getOperand(0).getImm())
652 .addImm(Alu->getOperand(1).getImm())
653 .addImm(Alu->getOperand(2).getImm())
654 .addImm(Alu->getOperand(3).getImm())
655 .addImm(Alu->getOperand(4).getImm())
656 .addImm(Alu->getOperand(5).getImm())
657 .addImm(Alu->getOperand(6).getImm())
658 .addImm(Alu->getOperand(7).getImm())
659 .addImm(Alu->getOperand(8).getImm());
660 Alu->eraseFromParent();
661 }
662 MFI->CFStackSize = CFStack.MaxStackSize;
663 }
664
665 return false;
666 }
667
668 StringRef getPassName() const override {
669 return "R600 Control Flow Finalizer Pass";
670 }
671};
672
673} // end anonymous namespace
674
675INITIALIZE_PASS_BEGIN(R600ControlFlowFinalizer, DEBUG_TYPE,
676 "R600 Control Flow Finalizer", false, false)
677INITIALIZE_PASS_END(R600ControlFlowFinalizer, DEBUG_TYPE,
678 "R600 Control Flow Finalizer", false, false)
679
680char R600ControlFlowFinalizer::ID = 0;
681
682char &llvm::R600ControlFlowFinalizerID = R600ControlFlowFinalizer::ID;
683
685 return new R600ControlFlowFinalizer();
686}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define ENTRY(ASMNAME, ENUM)
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
Provides R600 specific target descriptions.
AMDGPU R600 specific subclass of TargetSubtarget.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
#define LLVM_DEBUG(...)
Definition Debug.h:119
unsigned getWavefrontSize() const
A debug info location.
Definition DebugLoc.h:126
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
Definition Function.h:272
Describe properties that are true of each instruction in the target description file.
Instructions::iterator instr_iterator
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
Representation of each machine instruction.
const MachineOperand * const_mop_iterator
LLVM_ABI void dump() const
const MachineOperand & getOperand(unsigned i) const
LLVM_ABI MachineInstrBundleIterator< MachineInstr > eraseFromParent()
Unlink 'this' from the containing basic block and delete it.
MachineOperand class - Representation of each machine instruction operand.
void setImm(int64_t immVal)
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
Register getReg() const
getReg - Returns the register number.
bool hasCaymanISA() const
bool hasCFALUBug() const
Generation getGeneration() const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ AMDGPU_VS
Used for Mesa vertex shaders, or AMDPAL last shader stage before rasterization (vertex shader if tess...
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.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:389
FunctionPass * createR600ControlFlowFinalizer()
char & R600ControlFlowFinalizerID
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1772
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
static unsigned getSubRegFromChannel(unsigned Channel)