688 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// This pass compute turns all control flow pseudo instructions into native one11/// computing their address on the fly; it also sets STACK_SIZE info.12//13//===----------------------------------------------------------------------===//14 15#include "MCTargetDesc/R600MCTargetDesc.h"16#include "R600.h"17#include "R600MachineFunctionInfo.h"18#include "R600Subtarget.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include <set>21 22using namespace llvm;23 24#define DEBUG_TYPE "r600cf"25 26namespace {27 28struct CFStack {29 enum StackItem {30 ENTRY = 0,31 SUB_ENTRY = 1,32 FIRST_NON_WQM_PUSH = 2,33 FIRST_NON_WQM_PUSH_W_FULL_ENTRY = 334 };35 36 const R600Subtarget *ST;37 std::vector<StackItem> BranchStack;38 std::vector<StackItem> LoopStack;39 unsigned MaxStackSize;40 unsigned CurrentEntries = 0;41 unsigned CurrentSubEntries = 0;42 43 CFStack(const R600Subtarget *st, CallingConv::ID cc) : ST(st),44 // We need to reserve a stack entry for CALL_FS in vertex shaders.45 MaxStackSize(cc == CallingConv::AMDGPU_VS ? 1 : 0) {}46 47 unsigned getLoopDepth();48 bool branchStackContains(CFStack::StackItem);49 bool requiresWorkAroundForInst(unsigned Opcode);50 unsigned getSubEntrySize(CFStack::StackItem Item);51 void updateMaxStackSize();52 void pushBranch(unsigned Opcode, bool isWQM = false);53 void pushLoop();54 void popBranch();55 void popLoop();56};57 58unsigned CFStack::getLoopDepth() {59 return LoopStack.size();60}61 62bool CFStack::branchStackContains(CFStack::StackItem Item) {63 return llvm::is_contained(BranchStack, Item);64}65 66bool CFStack::requiresWorkAroundForInst(unsigned Opcode) {67 if (Opcode == R600::CF_ALU_PUSH_BEFORE && ST->hasCaymanISA() &&68 getLoopDepth() > 1)69 return true;70 71 if (!ST->hasCFAluBug())72 return false;73 74 switch(Opcode) {75 default: return false;76 case R600::CF_ALU_PUSH_BEFORE:77 case R600::CF_ALU_ELSE_AFTER:78 case R600::CF_ALU_BREAK:79 case R600::CF_ALU_CONTINUE:80 if (CurrentSubEntries == 0)81 return false;82 if (ST->getWavefrontSize() == 64) {83 // We are being conservative here. We only require this work-around if84 // CurrentSubEntries > 3 &&85 // (CurrentSubEntries % 4 == 3 || CurrentSubEntries % 4 == 0)86 //87 // We have to be conservative, because we don't know for certain that88 // our stack allocation algorithm for Evergreen/NI is correct. Applying this89 // work-around when CurrentSubEntries > 3 allows us to over-allocate stack90 // resources without any problems.91 return CurrentSubEntries > 3;92 }93 assert(ST->getWavefrontSize() == 32);94 // We are being conservative here. We only require the work-around if95 // CurrentSubEntries > 7 &&96 // (CurrentSubEntries % 8 == 7 || CurrentSubEntries % 8 == 0)97 // See the comment on the wavefront size == 64 case for why we are98 // being conservative.99 return CurrentSubEntries > 7;100 }101}102 103unsigned CFStack::getSubEntrySize(CFStack::StackItem Item) {104 switch(Item) {105 default:106 return 0;107 case CFStack::FIRST_NON_WQM_PUSH:108 assert(!ST->hasCaymanISA());109 if (ST->getGeneration() <= AMDGPUSubtarget::R700) {110 // +1 For the push operation.111 // +2 Extra space required.112 return 3;113 }114 // Some documentation says that this is not necessary on Evergreen,115 // but experimentation has show that we need to allocate 1 extra116 // sub-entry for the first non-WQM push.117 // +1 For the push operation.118 // +1 Extra space required.119 return 2;120 case CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY:121 assert(ST->getGeneration() >= AMDGPUSubtarget::EVERGREEN);122 // +1 For the push operation.123 // +1 Extra space required.124 return 2;125 case CFStack::SUB_ENTRY:126 return 1;127 }128}129 130void CFStack::updateMaxStackSize() {131 unsigned CurrentStackSize = CurrentEntries + divideCeil(CurrentSubEntries, 4);132 MaxStackSize = std::max(CurrentStackSize, MaxStackSize);133}134 135void CFStack::pushBranch(unsigned Opcode, bool isWQM) {136 CFStack::StackItem Item = CFStack::ENTRY;137 switch(Opcode) {138 case R600::CF_PUSH_EG:139 case R600::CF_ALU_PUSH_BEFORE:140 if (!isWQM) {141 if (!ST->hasCaymanISA() &&142 !branchStackContains(CFStack::FIRST_NON_WQM_PUSH))143 Item = CFStack::FIRST_NON_WQM_PUSH; // May not be required on Evergreen/NI144 // See comment in145 // CFStack::getSubEntrySize()146 else if (CurrentEntries > 0 &&147 ST->getGeneration() > AMDGPUSubtarget::EVERGREEN &&148 !ST->hasCaymanISA() &&149 !branchStackContains(CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY))150 Item = CFStack::FIRST_NON_WQM_PUSH_W_FULL_ENTRY;151 else152 Item = CFStack::SUB_ENTRY;153 } else154 Item = CFStack::ENTRY;155 break;156 }157 BranchStack.push_back(Item);158 if (Item == CFStack::ENTRY)159 CurrentEntries++;160 else161 CurrentSubEntries += getSubEntrySize(Item);162 updateMaxStackSize();163}164 165void CFStack::pushLoop() {166 LoopStack.push_back(CFStack::ENTRY);167 CurrentEntries++;168 updateMaxStackSize();169}170 171void CFStack::popBranch() {172 CFStack::StackItem Top = BranchStack.back();173 if (Top == CFStack::ENTRY)174 CurrentEntries--;175 else176 CurrentSubEntries-= getSubEntrySize(Top);177 BranchStack.pop_back();178}179 180void CFStack::popLoop() {181 CurrentEntries--;182 LoopStack.pop_back();183}184 185class R600ControlFlowFinalizer : public MachineFunctionPass {186private:187 using ClauseFile = std::pair<MachineInstr *, std::vector<MachineInstr *>>;188 189 enum ControlFlowInstruction {190 CF_TC,191 CF_VC,192 CF_CALL_FS,193 CF_WHILE_LOOP,194 CF_END_LOOP,195 CF_LOOP_BREAK,196 CF_LOOP_CONTINUE,197 CF_JUMP,198 CF_ELSE,199 CF_POP,200 CF_END201 };202 203 const R600InstrInfo *TII = nullptr;204 const R600RegisterInfo *TRI = nullptr;205 unsigned MaxFetchInst;206 const R600Subtarget *ST = nullptr;207 208 bool IsTrivialInst(MachineInstr &MI) const {209 switch (MI.getOpcode()) {210 case R600::KILL:211 case R600::RETURN:212 return true;213 default:214 return false;215 }216 }217 218 const MCInstrDesc &getHWInstrDesc(ControlFlowInstruction CFI) const {219 unsigned Opcode = 0;220 bool isEg = (ST->getGeneration() >= AMDGPUSubtarget::EVERGREEN);221 switch (CFI) {222 case CF_TC:223 Opcode = isEg ? R600::CF_TC_EG : R600::CF_TC_R600;224 break;225 case CF_VC:226 Opcode = isEg ? R600::CF_VC_EG : R600::CF_VC_R600;227 break;228 case CF_CALL_FS:229 Opcode = isEg ? R600::CF_CALL_FS_EG : R600::CF_CALL_FS_R600;230 break;231 case CF_WHILE_LOOP:232 Opcode = isEg ? R600::WHILE_LOOP_EG : R600::WHILE_LOOP_R600;233 break;234 case CF_END_LOOP:235 Opcode = isEg ? R600::END_LOOP_EG : R600::END_LOOP_R600;236 break;237 case CF_LOOP_BREAK:238 Opcode = isEg ? R600::LOOP_BREAK_EG : R600::LOOP_BREAK_R600;239 break;240 case CF_LOOP_CONTINUE:241 Opcode = isEg ? R600::CF_CONTINUE_EG : R600::CF_CONTINUE_R600;242 break;243 case CF_JUMP:244 Opcode = isEg ? R600::CF_JUMP_EG : R600::CF_JUMP_R600;245 break;246 case CF_ELSE:247 Opcode = isEg ? R600::CF_ELSE_EG : R600::CF_ELSE_R600;248 break;249 case CF_POP:250 Opcode = isEg ? R600::POP_EG : R600::POP_R600;251 break;252 case CF_END:253 if (ST->hasCaymanISA()) {254 Opcode = R600::CF_END_CM;255 break;256 }257 Opcode = isEg ? R600::CF_END_EG : R600::CF_END_R600;258 break;259 }260 assert (Opcode && "No opcode selected");261 return TII->get(Opcode);262 }263 264 bool isCompatibleWithClause(const MachineInstr &MI,265 std::set<unsigned> &DstRegs) const {266 unsigned DstMI, SrcMI;267 for (MachineInstr::const_mop_iterator I = MI.operands_begin(),268 E = MI.operands_end();269 I != E; ++I) {270 const MachineOperand &MO = *I;271 if (!MO.isReg())272 continue;273 if (MO.isDef()) {274 Register Reg = MO.getReg();275 if (R600::R600_Reg128RegClass.contains(Reg))276 DstMI = Reg;277 else278 DstMI = TRI->getMatchingSuperReg(Reg,279 R600RegisterInfo::getSubRegFromChannel(TRI->getHWRegChan(Reg)),280 &R600::R600_Reg128RegClass);281 }282 if (MO.isUse()) {283 Register Reg = MO.getReg();284 if (R600::R600_Reg128RegClass.contains(Reg))285 SrcMI = Reg;286 else287 SrcMI = TRI->getMatchingSuperReg(Reg,288 R600RegisterInfo::getSubRegFromChannel(TRI->getHWRegChan(Reg)),289 &R600::R600_Reg128RegClass);290 }291 }292 if ((DstRegs.find(SrcMI) == DstRegs.end())) {293 DstRegs.insert(DstMI);294 return true;295 }296 return false;297 }298 299 ClauseFile300 MakeFetchClause(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I)301 const {302 MachineBasicBlock::iterator ClauseHead = I;303 std::vector<MachineInstr *> ClauseContent;304 unsigned AluInstCount = 0;305 bool IsTex = TII->usesTextureCache(*ClauseHead);306 std::set<unsigned> DstRegs;307 for (MachineBasicBlock::iterator E = MBB.end(); I != E; ++I) {308 if (IsTrivialInst(*I))309 continue;310 if (AluInstCount >= MaxFetchInst)311 break;312 if ((IsTex && !TII->usesTextureCache(*I)) ||313 (!IsTex && !TII->usesVertexCache(*I)))314 break;315 if (!isCompatibleWithClause(*I, DstRegs))316 break;317 AluInstCount ++;318 ClauseContent.push_back(&*I);319 }320 MachineInstr *MIb = BuildMI(MBB, ClauseHead, MBB.findDebugLoc(ClauseHead),321 getHWInstrDesc(IsTex?CF_TC:CF_VC))322 .addImm(0) // ADDR323 .addImm(AluInstCount - 1); // COUNT324 return ClauseFile(MIb, std::move(ClauseContent));325 }326 327 void getLiteral(MachineInstr &MI, std::vector<MachineOperand *> &Lits) const {328 static const unsigned LiteralRegs[] = {329 R600::ALU_LITERAL_X,330 R600::ALU_LITERAL_Y,331 R600::ALU_LITERAL_Z,332 R600::ALU_LITERAL_W333 };334 const SmallVector<std::pair<MachineOperand *, int64_t>, 3> Srcs =335 TII->getSrcs(MI);336 for (const auto &Src:Srcs) {337 if (Src.first->getReg() != R600::ALU_LITERAL_X)338 continue;339 int64_t Imm = Src.second;340 std::vector<MachineOperand *>::iterator It =341 llvm::find_if(Lits, [&](MachineOperand *val) {342 return val->isImm() && (val->getImm() == Imm);343 });344 345 // Get corresponding Operand346 MachineOperand &Operand = MI.getOperand(347 TII->getOperandIdx(MI.getOpcode(), R600::OpName::literal));348 349 if (It != Lits.end()) {350 // Reuse existing literal reg351 unsigned Index = It - Lits.begin();352 Src.first->setReg(LiteralRegs[Index]);353 } else {354 // Allocate new literal reg355 assert(Lits.size() < 4 && "Too many literals in Instruction Group");356 Src.first->setReg(LiteralRegs[Lits.size()]);357 Lits.push_back(&Operand);358 }359 }360 }361 362 MachineBasicBlock::iterator insertLiterals(363 MachineBasicBlock::iterator InsertPos,364 const std::vector<unsigned> &Literals) const {365 MachineBasicBlock *MBB = InsertPos->getParent();366 for (unsigned i = 0, e = Literals.size(); i < e; i+=2) {367 unsigned LiteralPair0 = Literals[i];368 unsigned LiteralPair1 = (i + 1 < e)?Literals[i + 1]:0;369 InsertPos = BuildMI(MBB, InsertPos->getDebugLoc(),370 TII->get(R600::LITERALS))371 .addImm(LiteralPair0)372 .addImm(LiteralPair1);373 }374 return InsertPos;375 }376 377 ClauseFile378 MakeALUClause(MachineBasicBlock &MBB, MachineBasicBlock::iterator &I)379 const {380 MachineInstr &ClauseHead = *I;381 std::vector<MachineInstr *> ClauseContent;382 I++;383 for (MachineBasicBlock::instr_iterator E = MBB.instr_end(); I != E;) {384 if (IsTrivialInst(*I)) {385 ++I;386 continue;387 }388 if (!I->isBundle() && !TII->isALUInstr(I->getOpcode()))389 break;390 std::vector<MachineOperand *>Literals;391 if (I->isBundle()) {392 MachineInstr &DeleteMI = *I;393 MachineBasicBlock::instr_iterator BI = I.getInstrIterator();394 while (++BI != E && BI->isBundledWithPred()) {395 BI->unbundleFromPred();396 for (MachineOperand &MO : BI->operands()) {397 if (MO.isReg() && MO.isInternalRead())398 MO.setIsInternalRead(false);399 }400 getLiteral(*BI, Literals);401 ClauseContent.push_back(&*BI);402 }403 I = BI;404 DeleteMI.eraseFromParent();405 } else {406 getLiteral(*I, Literals);407 ClauseContent.push_back(&*I);408 I++;409 }410 for (unsigned i = 0, e = Literals.size(); i < e; i += 2) {411 MachineInstrBuilder MILit = BuildMI(MBB, I, I->getDebugLoc(),412 TII->get(R600::LITERALS));413 if (Literals[i]->isImm()) {414 MILit.addImm(Literals[i]->getImm());415 } else {416 MILit.addGlobalAddress(Literals[i]->getGlobal(),417 Literals[i]->getOffset());418 }419 if (i + 1 < e) {420 if (Literals[i + 1]->isImm()) {421 MILit.addImm(Literals[i + 1]->getImm());422 } else {423 MILit.addGlobalAddress(Literals[i + 1]->getGlobal(),424 Literals[i + 1]->getOffset());425 }426 } else427 MILit.addImm(0);428 ClauseContent.push_back(MILit);429 }430 }431 assert(ClauseContent.size() < 128 && "ALU clause is too big");432 ClauseHead.getOperand(7).setImm(ClauseContent.size() - 1);433 return ClauseFile(&ClauseHead, std::move(ClauseContent));434 }435 436 void EmitFetchClause(MachineBasicBlock::iterator InsertPos,437 const DebugLoc &DL, ClauseFile &Clause,438 unsigned &CfCount) {439 CounterPropagateAddr(*Clause.first, CfCount);440 MachineBasicBlock *BB = Clause.first->getParent();441 BuildMI(BB, DL, TII->get(R600::FETCH_CLAUSE)).addImm(CfCount);442 for (MachineInstr *MI : Clause.second)443 BB->splice(InsertPos, BB, MI);444 CfCount += 2 * Clause.second.size();445 }446 447 void EmitALUClause(MachineBasicBlock::iterator InsertPos, const DebugLoc &DL,448 ClauseFile &Clause, unsigned &CfCount) {449 Clause.first->getOperand(0).setImm(0);450 CounterPropagateAddr(*Clause.first, CfCount);451 MachineBasicBlock *BB = Clause.first->getParent();452 BuildMI(BB, DL, TII->get(R600::ALU_CLAUSE)).addImm(CfCount);453 for (MachineInstr *MI : Clause.second)454 BB->splice(InsertPos, BB, MI);455 CfCount += Clause.second.size();456 }457 458 void CounterPropagateAddr(MachineInstr &MI, unsigned Addr) const {459 MI.getOperand(0).setImm(Addr + MI.getOperand(0).getImm());460 }461 void CounterPropagateAddr(const std::set<MachineInstr *> &MIs,462 unsigned Addr) const {463 for (MachineInstr *MI : MIs) {464 CounterPropagateAddr(*MI, Addr);465 }466 }467 468public:469 static char ID;470 471 R600ControlFlowFinalizer() : MachineFunctionPass(ID) {}472 473 bool runOnMachineFunction(MachineFunction &MF) override {474 ST = &MF.getSubtarget<R600Subtarget>();475 MaxFetchInst = ST->getTexVTXClauseSize();476 TII = ST->getInstrInfo();477 TRI = ST->getRegisterInfo();478 479 R600MachineFunctionInfo *MFI = MF.getInfo<R600MachineFunctionInfo>();480 481 CFStack CFStack(ST, MF.getFunction().getCallingConv());482 for (MachineFunction::iterator MB = MF.begin(), ME = MF.end(); MB != ME;483 ++MB) {484 MachineBasicBlock &MBB = *MB;485 unsigned CfCount = 0;486 std::vector<std::pair<unsigned, std::set<MachineInstr *>>> LoopStack;487 std::vector<MachineInstr * > IfThenElseStack;488 if (MF.getFunction().getCallingConv() == CallingConv::AMDGPU_VS) {489 BuildMI(MBB, MBB.begin(), MBB.findDebugLoc(MBB.begin()),490 getHWInstrDesc(CF_CALL_FS));491 CfCount++;492 }493 std::vector<ClauseFile> FetchClauses, AluClauses;494 std::vector<MachineInstr *> LastAlu(1);495 std::vector<MachineInstr *> ToPopAfter;496 497 for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();498 I != E;) {499 if (TII->usesTextureCache(*I) || TII->usesVertexCache(*I)) {500 LLVM_DEBUG(dbgs() << CfCount << ":"; I->dump(););501 FetchClauses.push_back(MakeFetchClause(MBB, I));502 CfCount++;503 LastAlu.back() = nullptr;504 continue;505 }506 507 MachineBasicBlock::iterator MI = I;508 if (MI->getOpcode() != R600::ENDIF)509 LastAlu.back() = nullptr;510 if (MI->getOpcode() == R600::CF_ALU)511 LastAlu.back() = &*MI;512 I++;513 bool RequiresWorkAround =514 CFStack.requiresWorkAroundForInst(MI->getOpcode());515 switch (MI->getOpcode()) {516 case R600::CF_ALU_PUSH_BEFORE:517 if (RequiresWorkAround) {518 LLVM_DEBUG(dbgs()519 << "Applying bug work-around for ALU_PUSH_BEFORE\n");520 BuildMI(MBB, MI, MBB.findDebugLoc(MI), TII->get(R600::CF_PUSH_EG))521 .addImm(CfCount + 1)522 .addImm(1);523 MI->setDesc(TII->get(R600::CF_ALU));524 CfCount++;525 CFStack.pushBranch(R600::CF_PUSH_EG);526 } else527 CFStack.pushBranch(R600::CF_ALU_PUSH_BEFORE);528 [[fallthrough]];529 case R600::CF_ALU:530 I = MI;531 AluClauses.push_back(MakeALUClause(MBB, I));532 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););533 CfCount++;534 break;535 case R600::WHILELOOP: {536 CFStack.pushLoop();537 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),538 getHWInstrDesc(CF_WHILE_LOOP))539 .addImm(1);540 std::pair<unsigned, std::set<MachineInstr *>> Pair(CfCount,541 std::set<MachineInstr *>());542 Pair.second.insert(MIb);543 LoopStack.push_back(std::move(Pair));544 MI->eraseFromParent();545 CfCount++;546 break;547 }548 case R600::ENDLOOP: {549 CFStack.popLoop();550 std::pair<unsigned, std::set<MachineInstr *>> Pair =551 std::move(LoopStack.back());552 LoopStack.pop_back();553 CounterPropagateAddr(Pair.second, CfCount);554 BuildMI(MBB, MI, MBB.findDebugLoc(MI), getHWInstrDesc(CF_END_LOOP))555 .addImm(Pair.first + 1);556 MI->eraseFromParent();557 CfCount++;558 break;559 }560 case R600::IF_PREDICATE_SET: {561 LastAlu.push_back(nullptr);562 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),563 getHWInstrDesc(CF_JUMP))564 .addImm(0)565 .addImm(0);566 IfThenElseStack.push_back(MIb);567 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););568 MI->eraseFromParent();569 CfCount++;570 break;571 }572 case R600::ELSE: {573 MachineInstr * JumpInst = IfThenElseStack.back();574 IfThenElseStack.pop_back();575 CounterPropagateAddr(*JumpInst, CfCount);576 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),577 getHWInstrDesc(CF_ELSE))578 .addImm(0)579 .addImm(0);580 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););581 IfThenElseStack.push_back(MIb);582 MI->eraseFromParent();583 CfCount++;584 break;585 }586 case R600::ENDIF: {587 CFStack.popBranch();588 if (LastAlu.back()) {589 ToPopAfter.push_back(LastAlu.back());590 } else {591 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),592 getHWInstrDesc(CF_POP))593 .addImm(CfCount + 1)594 .addImm(1);595 (void)MIb;596 LLVM_DEBUG(dbgs() << CfCount << ":"; MIb->dump(););597 CfCount++;598 }599 600 MachineInstr *IfOrElseInst = IfThenElseStack.back();601 IfThenElseStack.pop_back();602 CounterPropagateAddr(*IfOrElseInst, CfCount);603 IfOrElseInst->getOperand(1).setImm(1);604 LastAlu.pop_back();605 MI->eraseFromParent();606 break;607 }608 case R600::BREAK: {609 CfCount ++;610 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),611 getHWInstrDesc(CF_LOOP_BREAK))612 .addImm(0);613 LoopStack.back().second.insert(MIb);614 MI->eraseFromParent();615 break;616 }617 case R600::CONTINUE: {618 MachineInstr *MIb = BuildMI(MBB, MI, MBB.findDebugLoc(MI),619 getHWInstrDesc(CF_LOOP_CONTINUE))620 .addImm(0);621 LoopStack.back().second.insert(MIb);622 MI->eraseFromParent();623 CfCount++;624 break;625 }626 case R600::RETURN: {627 DebugLoc DL = MBB.findDebugLoc(MI);628 BuildMI(MBB, MI, DL, getHWInstrDesc(CF_END));629 CfCount++;630 if (CfCount % 2) {631 BuildMI(MBB, I, DL, TII->get(R600::PAD));632 CfCount++;633 }634 MI->eraseFromParent();635 for (ClauseFile &CF : FetchClauses)636 EmitFetchClause(I, DL, CF, CfCount);637 for (ClauseFile &CF : AluClauses)638 EmitALUClause(I, DL, CF, CfCount);639 break;640 }641 default:642 if (TII->isExport(MI->getOpcode())) {643 LLVM_DEBUG(dbgs() << CfCount << ":"; MI->dump(););644 CfCount++;645 }646 break;647 }648 }649 for (MachineInstr *Alu : ToPopAfter) {650 BuildMI(MBB, Alu, MBB.findDebugLoc((MachineBasicBlock::iterator)Alu),651 TII->get(R600::CF_ALU_POP_AFTER))652 .addImm(Alu->getOperand(0).getImm())653 .addImm(Alu->getOperand(1).getImm())654 .addImm(Alu->getOperand(2).getImm())655 .addImm(Alu->getOperand(3).getImm())656 .addImm(Alu->getOperand(4).getImm())657 .addImm(Alu->getOperand(5).getImm())658 .addImm(Alu->getOperand(6).getImm())659 .addImm(Alu->getOperand(7).getImm())660 .addImm(Alu->getOperand(8).getImm());661 Alu->eraseFromParent();662 }663 MFI->CFStackSize = CFStack.MaxStackSize;664 }665 666 return false;667 }668 669 StringRef getPassName() const override {670 return "R600 Control Flow Finalizer Pass";671 }672};673 674} // end anonymous namespace675 676INITIALIZE_PASS_BEGIN(R600ControlFlowFinalizer, DEBUG_TYPE,677 "R600 Control Flow Finalizer", false, false)678INITIALIZE_PASS_END(R600ControlFlowFinalizer, DEBUG_TYPE,679 "R600 Control Flow Finalizer", false, false)680 681char R600ControlFlowFinalizer::ID = 0;682 683char &llvm::R600ControlFlowFinalizerID = R600ControlFlowFinalizer::ID;684 685FunctionPass *llvm::createR600ControlFlowFinalizer() {686 return new R600ControlFlowFinalizer();687}688