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 ClauseFile
363 const {
364 MachineInstr &ClauseHead = *I;
365 std::vector<MachineInstr *> ClauseContent;
366 I++;
367 for (MachineBasicBlock::instr_iterator E = MBB.instr_end(); I != E;) {
368 if (IsTrivialInst(*I)) {
369 ++I;
370 continue;
371 }
372 if (!I->isBundle() && !TII->isALUInstr(I->getOpcode()))
373 break;
374 std::vector<MachineOperand *>Literals;
375 if (I->isBundle()) {
376 MachineInstr &DeleteMI = *I;
377 MachineBasicBlock::instr_iterator BI = I.getInstrIterator();
378 while (++BI != E && BI->isBundledWithPred()) {
379 BI->unbundleFromPred();
380 for (MachineOperand &MO : BI->operands()) {
381 if (MO.isReg() && MO.isInternalRead())
382 MO.setIsInternalRead(false);
383 }
384 getLiteral(*BI, Literals);
385 ClauseContent.push_back(&*BI);
386 }
387 I = BI;
388 DeleteMI.eraseFromParent();
389 } else {
390 getLiteral(*I, Literals);
391 ClauseContent.push_back(&*I);
392 I++;
393 }
394 for (unsigned i = 0, e = Literals.size(); i < e; i += 2) {
395 MachineInstrBuilder MILit = BuildMI(MBB, I, I->getDebugLoc(),
396 TII->get(R600::LITERALS));
397 if (Literals[i]->isImm()) {
398 MILit.addImm(Literals[i]->getImm());
399 } else {
400 MILit.addGlobalAddress(Literals[i]->getGlobal(),
401 Literals[i]->getOffset());
402 }
403 if (i + 1 < e) {
404 if (Literals[i + 1]->isImm()) {
405 MILit.addImm(Literals[i + 1]->getImm());
406 } else {
407 MILit.addGlobalAddress(Literals[i + 1]->getGlobal(),
408 Literals[i + 1]->getOffset());
409 }
410 } else
411 MILit.addImm(0);
412 ClauseContent.push_back(MILit);
413 }
414 }
415 assert(ClauseContent.size() < 128 && "ALU clause is too big");
416 ClauseHead.getOperand(7).setImm(ClauseContent.size() - 1);
417 return ClauseFile(&ClauseHead, std::move(ClauseContent));
418 }
419
420 void EmitFetchClause(MachineBasicBlock::iterator InsertPos,
421 const DebugLoc &DL, ClauseFile &Clause,
422 unsigned &CfCount) {
423 CounterPropagateAddr(*Clause.first, CfCount);
424 MachineBasicBlock *BB = Clause.first->getParent();
425 BuildMI(BB, DL, TII->get(R600::FETCH_CLAUSE)).addImm(CfCount);
426 for (MachineInstr *MI : Clause.second)
427 BB->splice(InsertPos, BB, MI);
428 CfCount += 2 * Clause.second.size();
429 }
430
431 void EmitALUClause(MachineBasicBlock::iterator InsertPos, const DebugLoc &DL,
432 ClauseFile &Clause, unsigned &CfCount) {
433 Clause.first->getOperand(0).setImm(0);
434 CounterPropagateAddr(*Clause.first, CfCount);
435 MachineBasicBlock *BB = Clause.first->getParent();
436 BuildMI(BB, DL, TII->get(R600::ALU_CLAUSE)).addImm(CfCount);
437 for (MachineInstr *MI : Clause.second)
438 BB->splice(InsertPos, BB, MI);
439 CfCount += Clause.second.size();
440 }
441
442 void CounterPropagateAddr(MachineInstr &MI, unsigned Addr) const {
443 MI.getOperand(0).setImm(Addr + MI.getOperand(0).getImm());
444 }
445 void CounterPropagateAddr(const std::set<MachineInstr *> &MIs,
446 unsigned Addr) const {
447 for (MachineInstr *MI : MIs) {
448 CounterPropagateAddr(*MI, Addr);
449 }
450 }
451
452public:
453 static char ID;
454
455 R600ControlFlowFinalizer() : MachineFunctionPass(ID) {}
456
457 bool runOnMachineFunction(MachineFunction &MF) override {
458 ST = &MF.getSubtarget<R600Subtarget>();
459 MaxFetchInst = ST->getTexVTXClauseSize();
460 TII = ST->getInstrInfo();
461 TRI = ST->getRegisterInfo();
462
464
465 CFStack CFStack(ST, MF.getFunction().getCallingConv());
466 for (MachineFunction::iterator MB = MF.begin(), ME = MF.end(); MB != ME;
467 ++MB) {
468 MachineBasicBlock &MBB = *MB;
469 unsigned CfCount = 0;
470 std::vector<std::pair<unsigned, std::set<MachineInstr *>>> LoopStack;
471 std::vector<MachineInstr * > IfThenElseStack;
473 BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()),
474 getHWInstrDesc(CF_CALL_FS));
475 CfCount++;
476 }
477 std::vector<ClauseFile> FetchClauses, AluClauses;
478 std::vector<MachineInstr *> LastAlu(1);
479 std::vector<MachineInstr *> ToPopAfter;
480
481 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
482 I != E;) {
483 if (TII->usesTextureCache(*I) || TII->usesVertexCache(*I)) {
484 LLVM_DEBUG(dbgs() << CfCount << ":"; I->dump(););
485 FetchClauses.push_back(MakeFetchClause(MBB, I));
486 CfCount++;
487 LastAlu.back() = nullptr;
488 continue;
489 }
490
492 if (MI->getOpcode() != R600::ENDIF)
493 LastAlu.back() = nullptr;
494 if (MI->getOpcode() == R600::CF_ALU)
495 LastAlu.back() = &*MI;
496 I++;
497 bool RequiresWorkAround =
498 CFStack.requiresWorkAroundForInst(MI->getOpcode());
499 switch (MI->getOpcode()) {
500 case R600::CF_ALU_PUSH_BEFORE:
501 if (RequiresWorkAround) {
503 << "Applying bug work-around for ALU_PUSH_BEFORE\n");
504 BuildMI(MBB, MI, MBB.findDebugLoc(MI), TII->get(R600::CF_PUSH_EG))
505 .addImm(CfCount + 1)
506 .addImm(1);
507 MI->setDesc(TII->get(R600::CF_ALU));
508 CfCount++;
509 CFStack.pushBranch(R600::CF_PUSH_EG);
510 } else
511 CFStack.pushBranch(R600::CF_ALU_PUSH_BEFORE);
512 [[fallthrough]];
513 case R600::CF_ALU:
514 I = MI;
515 AluClauses.push_back(MakeALUClause(MBB, I));
516 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););
517 CfCount++;
518 break;
519 case R600::WHILELOOP: {
520 CFStack.pushLoop();
521 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
522 getHWInstrDesc(CF_WHILE_LOOP))
523 .addImm(1);
524 std::pair<unsigned, std::set<MachineInstr *>> Pair(CfCount,
525 std::set<MachineInstr *>());
526 Pair.second.insert(MIb);
527 LoopStack.push_back(std::move(Pair));
528 MI->eraseFromParent();
529 CfCount++;
530 break;
531 }
532 case R600::ENDLOOP: {
533 CFStack.popLoop();
534 std::pair<unsigned, std::set<MachineInstr *>> Pair =
535 std::move(LoopStack.back());
536 LoopStack.pop_back();
537 CounterPropagateAddr(Pair.second, CfCount);
538 BuildMI(MBB, MI, MBB.findDebugLoc(MI), getHWInstrDesc(CF_END_LOOP))
539 .addImm(Pair.first + 1);
540 MI->eraseFromParent();
541 CfCount++;
542 break;
543 }
544 case R600::IF_PREDICATE_SET: {
545 LastAlu.push_back(nullptr);
546 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
547 getHWInstrDesc(CF_JUMP))
548 .addImm(0)
549 .addImm(0);
550 IfThenElseStack.push_back(MIb);
551 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
552 MI->eraseFromParent();
553 CfCount++;
554 break;
555 }
556 case R600::ELSE: {
557 MachineInstr * JumpInst = IfThenElseStack.back();
558 IfThenElseStack.pop_back();
559 CounterPropagateAddr(*JumpInst, CfCount);
560 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
561 getHWInstrDesc(CF_ELSE))
562 .addImm(0)
563 .addImm(0);
564 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
565 IfThenElseStack.push_back(MIb);
566 MI->eraseFromParent();
567 CfCount++;
568 break;
569 }
570 case R600::ENDIF: {
571 CFStack.popBranch();
572 if (LastAlu.back()) {
573 ToPopAfter.push_back(LastAlu.back());
574 } else {
575 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
576 getHWInstrDesc(CF_POP))
577 .addImm(CfCount + 1)
578 .addImm(1);
579 (void)MIb;
580 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););
581 CfCount++;
582 }
583
584 MachineInstr *IfOrElseInst = IfThenElseStack.back();
585 IfThenElseStack.pop_back();
586 CounterPropagateAddr(*IfOrElseInst, CfCount);
587 IfOrElseInst->getOperand(1).setImm(1);
588 LastAlu.pop_back();
589 MI->eraseFromParent();
590 break;
591 }
592 case R600::BREAK: {
593 CfCount ++;
594 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
595 getHWInstrDesc(CF_LOOP_BREAK))
596 .addImm(0);
597 LoopStack.back().second.insert(MIb);
598 MI->eraseFromParent();
599 break;
600 }
601 case R600::CONTINUE: {
602 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),
603 getHWInstrDesc(CF_LOOP_CONTINUE))
604 .addImm(0);
605 LoopStack.back().second.insert(MIb);
606 MI->eraseFromParent();
607 CfCount++;
608 break;
609 }
610 case R600::RETURN: {
611 DebugLoc DL = MBB.findDebugLoc(MI);
612 BuildMI(MBB, MI, DL, getHWInstrDesc(CF_END));
613 CfCount++;
614 if (CfCount % 2) {
615 BuildMI(MBB, I, DL, TII->get(R600::PAD));
616 CfCount++;
617 }
618 MI->eraseFromParent();
619 for (ClauseFile &CF : FetchClauses)
620 EmitFetchClause(I, DL, CF, CfCount);
621 for (ClauseFile &CF : AluClauses)
622 EmitALUClause(I, DL, CF, CfCount);
623 break;
624 }
625 default:
626 if (TII->isExport(MI->getOpcode())) {
627 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););
628 CfCount++;
629 }
630 break;
631 }
632 }
633 for (MachineInstr *Alu : ToPopAfter) {
634 BuildMI(MBB, Alu, MBB.findDebugLoc((MachineBasicBlock::iterator)Alu),
635 TII->get(R600::CF_ALU_POP_AFTER))
636 .addImm(Alu->getOperand(0).getImm())
637 .addImm(Alu->getOperand(1).getImm())
638 .addImm(Alu->getOperand(2).getImm())
639 .addImm(Alu->getOperand(3).getImm())
640 .addImm(Alu->getOperand(4).getImm())
641 .addImm(Alu->getOperand(5).getImm())
642 .addImm(Alu->getOperand(6).getImm())
643 .addImm(Alu->getOperand(7).getImm())
644 .addImm(Alu->getOperand(8).getImm());
645 Alu->eraseFromParent();
646 }
647 MFI->CFStackSize = CFStack.MaxStackSize;
648 }
649
650 return false;
651 }
652
653 StringRef getPassName() const override {
654 return "R600 Control Flow Finalizer Pass";
655 }
656};
657
658} // end anonymous namespace
659
660INITIALIZE_PASS_BEGIN(R600ControlFlowFinalizer, DEBUG_TYPE,
661 "R600 Control Flow Finalizer", false, false)
662INITIALIZE_PASS_END(R600ControlFlowFinalizer, DEBUG_TYPE,
663 "R600 Control Flow Finalizer", false, false)
664
665char R600ControlFlowFinalizer::ID = 0;
666
667char &llvm::R600ControlFlowFinalizerID = R600ControlFlowFinalizer::ID;
668
670 return new R600ControlFlowFinalizer();
671}
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:273
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:1788
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
static unsigned getSubRegFromChannel(unsigned Channel)