LCOV - code coverage report
Current view: top level - lib/Target/AMDGPU - R600ControlFlowFinalizer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 322 351 91.7 %
Date: 2017-09-14 15:23:50 Functions: 19 20 95.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13