10b57cec5SDimitry Andric //===----- R600Packetizer.cpp - VLIW packetizer ---------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This pass implements instructions packetization for R600. It unsets isLast
110b57cec5SDimitry Andric /// bit of instructions inside a bundle and substitutes src register with
120b57cec5SDimitry Andric /// PreviousVector when applicable.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
16349cc55cSDimitry Andric #include "MCTargetDesc/R600MCTargetDesc.h"
17349cc55cSDimitry Andric #include "R600.h"
18e8d8bef9SDimitry Andric #include "R600Subtarget.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h"
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #define DEBUG_TYPE "packets"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric namespace {
290b57cec5SDimitry Andric 
300b57cec5SDimitry Andric class R600Packetizer : public MachineFunctionPass {
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric public:
330b57cec5SDimitry Andric   static char ID;
R600Packetizer()340b57cec5SDimitry Andric   R600Packetizer() : MachineFunctionPass(ID) {}
350b57cec5SDimitry Andric 
getAnalysisUsage(AnalysisUsage & AU) const360b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
370b57cec5SDimitry Andric     AU.setPreservesCFG();
380b57cec5SDimitry Andric     AU.addRequired<MachineDominatorTree>();
390b57cec5SDimitry Andric     AU.addPreserved<MachineDominatorTree>();
400b57cec5SDimitry Andric     AU.addRequired<MachineLoopInfo>();
410b57cec5SDimitry Andric     AU.addPreserved<MachineLoopInfo>();
420b57cec5SDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric 
getPassName() const450b57cec5SDimitry Andric   StringRef getPassName() const override { return "R600 Packetizer"; }
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric   bool runOnMachineFunction(MachineFunction &Fn) override;
480b57cec5SDimitry Andric };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric class R600PacketizerList : public VLIWPacketizerList {
510b57cec5SDimitry Andric private:
520b57cec5SDimitry Andric   const R600InstrInfo *TII;
530b57cec5SDimitry Andric   const R600RegisterInfo &TRI;
540b57cec5SDimitry Andric   bool VLIW5;
550b57cec5SDimitry Andric   bool ConsideredInstUsesAlreadyWrittenVectorElement;
560b57cec5SDimitry Andric 
getSlot(const MachineInstr & MI) const570b57cec5SDimitry Andric   unsigned getSlot(const MachineInstr &MI) const {
580b57cec5SDimitry Andric     return TRI.getHWRegChan(MI.getOperand(0).getReg());
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   /// \returns register to PV chan mapping for bundle/single instructions that
620b57cec5SDimitry Andric   /// immediately precedes I.
getPreviousVector(MachineBasicBlock::iterator I) const630b57cec5SDimitry Andric   DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I)
640b57cec5SDimitry Andric       const {
650b57cec5SDimitry Andric     DenseMap<unsigned, unsigned> Result;
660b57cec5SDimitry Andric     I--;
670b57cec5SDimitry Andric     if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle())
680b57cec5SDimitry Andric       return Result;
690b57cec5SDimitry Andric     MachineBasicBlock::instr_iterator BI = I.getInstrIterator();
700b57cec5SDimitry Andric     if (I->isBundle())
710b57cec5SDimitry Andric       BI++;
720b57cec5SDimitry Andric     int LastDstChan = -1;
730b57cec5SDimitry Andric     do {
740b57cec5SDimitry Andric       bool isTrans = false;
750b57cec5SDimitry Andric       int BISlot = getSlot(*BI);
760b57cec5SDimitry Andric       if (LastDstChan >= BISlot)
770b57cec5SDimitry Andric         isTrans = true;
780b57cec5SDimitry Andric       LastDstChan = BISlot;
790b57cec5SDimitry Andric       if (TII->isPredicated(*BI))
800b57cec5SDimitry Andric         continue;
810b57cec5SDimitry Andric       int OperandIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::write);
820b57cec5SDimitry Andric       if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0)
830b57cec5SDimitry Andric         continue;
840b57cec5SDimitry Andric       int DstIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::dst);
850b57cec5SDimitry Andric       if (DstIdx == -1) {
860b57cec5SDimitry Andric         continue;
870b57cec5SDimitry Andric       }
888bcb0991SDimitry Andric       Register Dst = BI->getOperand(DstIdx).getReg();
890b57cec5SDimitry Andric       if (isTrans || TII->isTransOnly(*BI)) {
900b57cec5SDimitry Andric         Result[Dst] = R600::PS;
910b57cec5SDimitry Andric         continue;
920b57cec5SDimitry Andric       }
930b57cec5SDimitry Andric       if (BI->getOpcode() == R600::DOT4_r600 ||
940b57cec5SDimitry Andric           BI->getOpcode() == R600::DOT4_eg) {
950b57cec5SDimitry Andric         Result[Dst] = R600::PV_X;
960b57cec5SDimitry Andric         continue;
970b57cec5SDimitry Andric       }
980b57cec5SDimitry Andric       if (Dst == R600::OQAP) {
990b57cec5SDimitry Andric         continue;
1000b57cec5SDimitry Andric       }
1010b57cec5SDimitry Andric       unsigned PVReg = 0;
1020b57cec5SDimitry Andric       switch (TRI.getHWRegChan(Dst)) {
1030b57cec5SDimitry Andric       case 0:
1040b57cec5SDimitry Andric         PVReg = R600::PV_X;
1050b57cec5SDimitry Andric         break;
1060b57cec5SDimitry Andric       case 1:
1070b57cec5SDimitry Andric         PVReg = R600::PV_Y;
1080b57cec5SDimitry Andric         break;
1090b57cec5SDimitry Andric       case 2:
1100b57cec5SDimitry Andric         PVReg = R600::PV_Z;
1110b57cec5SDimitry Andric         break;
1120b57cec5SDimitry Andric       case 3:
1130b57cec5SDimitry Andric         PVReg = R600::PV_W;
1140b57cec5SDimitry Andric         break;
1150b57cec5SDimitry Andric       default:
1160b57cec5SDimitry Andric         llvm_unreachable("Invalid Chan");
1170b57cec5SDimitry Andric       }
1180b57cec5SDimitry Andric       Result[Dst] = PVReg;
1190b57cec5SDimitry Andric     } while ((++BI)->isBundledWithPred());
1200b57cec5SDimitry Andric     return Result;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
substitutePV(MachineInstr & MI,const DenseMap<unsigned,unsigned> & PVs) const1230b57cec5SDimitry Andric   void substitutePV(MachineInstr &MI, const DenseMap<unsigned, unsigned> &PVs)
1240b57cec5SDimitry Andric       const {
1250b57cec5SDimitry Andric     unsigned Ops[] = {
1260b57cec5SDimitry Andric       R600::OpName::src0,
1270b57cec5SDimitry Andric       R600::OpName::src1,
1280b57cec5SDimitry Andric       R600::OpName::src2
1290b57cec5SDimitry Andric     };
1300eae32dcSDimitry Andric     for (unsigned Op : Ops) {
1310eae32dcSDimitry Andric       int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Op);
1320b57cec5SDimitry Andric       if (OperandIdx < 0)
1330b57cec5SDimitry Andric         continue;
1348bcb0991SDimitry Andric       Register Src = MI.getOperand(OperandIdx).getReg();
1350b57cec5SDimitry Andric       const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src);
1360b57cec5SDimitry Andric       if (It != PVs.end())
1370b57cec5SDimitry Andric         MI.getOperand(OperandIdx).setReg(It->second);
1380b57cec5SDimitry Andric     }
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric public:
1410b57cec5SDimitry Andric   // Ctor.
R600PacketizerList(MachineFunction & MF,const R600Subtarget & ST,MachineLoopInfo & MLI)1420b57cec5SDimitry Andric   R600PacketizerList(MachineFunction &MF, const R600Subtarget &ST,
1430b57cec5SDimitry Andric                      MachineLoopInfo &MLI)
1440b57cec5SDimitry Andric       : VLIWPacketizerList(MF, MLI, nullptr),
1450b57cec5SDimitry Andric         TII(ST.getInstrInfo()),
1460b57cec5SDimitry Andric         TRI(TII->getRegisterInfo()) {
1470b57cec5SDimitry Andric     VLIW5 = !ST.hasCaymanISA();
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   // initPacketizerState - initialize some internal flags.
initPacketizerState()1510b57cec5SDimitry Andric   void initPacketizerState() override {
1520b57cec5SDimitry Andric     ConsideredInstUsesAlreadyWrittenVectorElement = false;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric   // ignorePseudoInstruction - Ignore bundling of pseudo instructions.
ignorePseudoInstruction(const MachineInstr & MI,const MachineBasicBlock * MBB)1560b57cec5SDimitry Andric   bool ignorePseudoInstruction(const MachineInstr &MI,
1570b57cec5SDimitry Andric                                const MachineBasicBlock *MBB) override {
1580b57cec5SDimitry Andric     return false;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // isSoloInstruction - return true if instruction MI can not be packetized
1620b57cec5SDimitry Andric   // with any other instruction, which means that MI itself is a packet.
isSoloInstruction(const MachineInstr & MI)1630b57cec5SDimitry Andric   bool isSoloInstruction(const MachineInstr &MI) override {
1640b57cec5SDimitry Andric     if (TII->isVector(MI))
1650b57cec5SDimitry Andric       return true;
1660b57cec5SDimitry Andric     if (!TII->isALUInstr(MI.getOpcode()))
1670b57cec5SDimitry Andric       return true;
1680b57cec5SDimitry Andric     if (MI.getOpcode() == R600::GROUP_BARRIER)
1690b57cec5SDimitry Andric       return true;
1700b57cec5SDimitry Andric     // XXX: This can be removed once the packetizer properly handles all the
1710b57cec5SDimitry Andric     // LDS instruction group restrictions.
1720b57cec5SDimitry Andric     return TII->isLDSInstr(MI.getOpcode());
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ
1760b57cec5SDimitry Andric   // together.
isLegalToPacketizeTogether(SUnit * SUI,SUnit * SUJ)1770b57cec5SDimitry Andric   bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override {
1780b57cec5SDimitry Andric     MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr();
1790b57cec5SDimitry Andric     if (getSlot(*MII) == getSlot(*MIJ))
1800b57cec5SDimitry Andric       ConsideredInstUsesAlreadyWrittenVectorElement = true;
1810b57cec5SDimitry Andric     // Does MII and MIJ share the same pred_sel ?
1820b57cec5SDimitry Andric     int OpI = TII->getOperandIdx(MII->getOpcode(), R600::OpName::pred_sel),
1830b57cec5SDimitry Andric         OpJ = TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel);
1840b57cec5SDimitry Andric     Register PredI = (OpI > -1)?MII->getOperand(OpI).getReg() : Register(),
1850b57cec5SDimitry Andric       PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() : Register();
1860b57cec5SDimitry Andric     if (PredI != PredJ)
1870b57cec5SDimitry Andric       return false;
1880b57cec5SDimitry Andric     if (SUJ->isSucc(SUI)) {
1890b57cec5SDimitry Andric       for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) {
1900b57cec5SDimitry Andric         const SDep &Dep = SUJ->Succs[i];
1910b57cec5SDimitry Andric         if (Dep.getSUnit() != SUI)
1920b57cec5SDimitry Andric           continue;
1930b57cec5SDimitry Andric         if (Dep.getKind() == SDep::Anti)
1940b57cec5SDimitry Andric           continue;
1950b57cec5SDimitry Andric         if (Dep.getKind() == SDep::Output)
1960b57cec5SDimitry Andric           if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg())
1970b57cec5SDimitry Andric             continue;
1980b57cec5SDimitry Andric         return false;
1990b57cec5SDimitry Andric       }
2000b57cec5SDimitry Andric     }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric     bool ARDef =
2030b57cec5SDimitry Andric         TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ);
2040b57cec5SDimitry Andric     bool ARUse =
2050b57cec5SDimitry Andric         TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric     return !ARDef || !ARUse;
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
21081ad6265SDimitry Andric   // isLegalToPruneDependencies - Is it legal to prune dependency between SUI
2110b57cec5SDimitry Andric   // and SUJ.
isLegalToPruneDependencies(SUnit * SUI,SUnit * SUJ)2120b57cec5SDimitry Andric   bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override {
2130b57cec5SDimitry Andric     return false;
2140b57cec5SDimitry Andric   }
2150b57cec5SDimitry Andric 
setIsLastBit(MachineInstr * MI,unsigned Bit) const2160b57cec5SDimitry Andric   void setIsLastBit(MachineInstr *MI, unsigned Bit) const {
2170b57cec5SDimitry Andric     unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), R600::OpName::last);
2180b57cec5SDimitry Andric     MI->getOperand(LastOp).setImm(Bit);
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric 
isBundlableWithCurrentPMI(MachineInstr & MI,const DenseMap<unsigned,unsigned> & PV,std::vector<R600InstrInfo::BankSwizzle> & BS,bool & isTransSlot)2210b57cec5SDimitry Andric   bool isBundlableWithCurrentPMI(MachineInstr &MI,
2220b57cec5SDimitry Andric                                  const DenseMap<unsigned, unsigned> &PV,
2230b57cec5SDimitry Andric                                  std::vector<R600InstrInfo::BankSwizzle> &BS,
2240b57cec5SDimitry Andric                                  bool &isTransSlot) {
2250b57cec5SDimitry Andric     isTransSlot = TII->isTransOnly(MI);
2260b57cec5SDimitry Andric     assert (!isTransSlot || VLIW5);
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric     // Is the dst reg sequence legal ?
2290b57cec5SDimitry Andric     if (!isTransSlot && !CurrentPacketMIs.empty()) {
2300b57cec5SDimitry Andric       if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) {
2310b57cec5SDimitry Andric         if (ConsideredInstUsesAlreadyWrittenVectorElement &&
2320b57cec5SDimitry Andric             !TII->isVectorOnly(MI) && VLIW5) {
2330b57cec5SDimitry Andric           isTransSlot = true;
2340b57cec5SDimitry Andric           LLVM_DEBUG({
2350b57cec5SDimitry Andric             dbgs() << "Considering as Trans Inst :";
2360b57cec5SDimitry Andric             MI.dump();
2370b57cec5SDimitry Andric           });
2380b57cec5SDimitry Andric         }
2390b57cec5SDimitry Andric         else
2400b57cec5SDimitry Andric           return false;
2410b57cec5SDimitry Andric       }
2420b57cec5SDimitry Andric     }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric     // Are the Constants limitations met ?
2450b57cec5SDimitry Andric     CurrentPacketMIs.push_back(&MI);
2460b57cec5SDimitry Andric     if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) {
2470b57cec5SDimitry Andric       LLVM_DEBUG({
2480b57cec5SDimitry Andric         dbgs() << "Couldn't pack :\n";
2490b57cec5SDimitry Andric         MI.dump();
2500b57cec5SDimitry Andric         dbgs() << "with the following packets :\n";
2510b57cec5SDimitry Andric         for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
2520b57cec5SDimitry Andric           CurrentPacketMIs[i]->dump();
2530b57cec5SDimitry Andric           dbgs() << "\n";
2540b57cec5SDimitry Andric         }
2550b57cec5SDimitry Andric         dbgs() << "because of Consts read limitations\n";
2560b57cec5SDimitry Andric       });
2570b57cec5SDimitry Andric       CurrentPacketMIs.pop_back();
2580b57cec5SDimitry Andric       return false;
2590b57cec5SDimitry Andric     }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric     // Is there a BankSwizzle set that meet Read Port limitations ?
2620b57cec5SDimitry Andric     if (!TII->fitsReadPortLimitations(CurrentPacketMIs,
2630b57cec5SDimitry Andric             PV, BS, isTransSlot)) {
2640b57cec5SDimitry Andric       LLVM_DEBUG({
2650b57cec5SDimitry Andric         dbgs() << "Couldn't pack :\n";
2660b57cec5SDimitry Andric         MI.dump();
2670b57cec5SDimitry Andric         dbgs() << "with the following packets :\n";
2680b57cec5SDimitry Andric         for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
2690b57cec5SDimitry Andric           CurrentPacketMIs[i]->dump();
2700b57cec5SDimitry Andric           dbgs() << "\n";
2710b57cec5SDimitry Andric         }
2720b57cec5SDimitry Andric         dbgs() << "because of Read port limitations\n";
2730b57cec5SDimitry Andric       });
2740b57cec5SDimitry Andric       CurrentPacketMIs.pop_back();
2750b57cec5SDimitry Andric       return false;
2760b57cec5SDimitry Andric     }
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric     // We cannot read LDS source registers from the Trans slot.
2790b57cec5SDimitry Andric     if (isTransSlot && TII->readsLDSSrcReg(MI))
2800b57cec5SDimitry Andric       return false;
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric     CurrentPacketMIs.pop_back();
2830b57cec5SDimitry Andric     return true;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
addToPacket(MachineInstr & MI)2860b57cec5SDimitry Andric   MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override {
2870b57cec5SDimitry Andric     MachineBasicBlock::iterator FirstInBundle =
2880b57cec5SDimitry Andric         CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front();
2890b57cec5SDimitry Andric     const DenseMap<unsigned, unsigned> &PV =
2900b57cec5SDimitry Andric         getPreviousVector(FirstInBundle);
2910b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> BS;
2920b57cec5SDimitry Andric     bool isTransSlot;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric     if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) {
2950b57cec5SDimitry Andric       for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) {
2960b57cec5SDimitry Andric         MachineInstr *MI = CurrentPacketMIs[i];
2970b57cec5SDimitry Andric         unsigned Op = TII->getOperandIdx(MI->getOpcode(),
2980b57cec5SDimitry Andric             R600::OpName::bank_swizzle);
2990b57cec5SDimitry Andric         MI->getOperand(Op).setImm(BS[i]);
3000b57cec5SDimitry Andric       }
3010b57cec5SDimitry Andric       unsigned Op =
3020b57cec5SDimitry Andric           TII->getOperandIdx(MI.getOpcode(), R600::OpName::bank_swizzle);
3030b57cec5SDimitry Andric       MI.getOperand(Op).setImm(BS.back());
3040b57cec5SDimitry Andric       if (!CurrentPacketMIs.empty())
3050b57cec5SDimitry Andric         setIsLastBit(CurrentPacketMIs.back(), 0);
3060b57cec5SDimitry Andric       substitutePV(MI, PV);
3070b57cec5SDimitry Andric       MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI);
3080b57cec5SDimitry Andric       if (isTransSlot) {
3090b57cec5SDimitry Andric         endPacket(std::next(It)->getParent(), std::next(It));
3100b57cec5SDimitry Andric       }
3110b57cec5SDimitry Andric       return It;
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric     endPacket(MI.getParent(), MI);
3140b57cec5SDimitry Andric     if (TII->isTransOnly(MI))
3150b57cec5SDimitry Andric       return MI;
3160b57cec5SDimitry Andric     return VLIWPacketizerList::addToPacket(MI);
3170b57cec5SDimitry Andric   }
3180b57cec5SDimitry Andric };
3190b57cec5SDimitry Andric 
runOnMachineFunction(MachineFunction & Fn)3200b57cec5SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) {
3210b57cec5SDimitry Andric   const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>();
3220b57cec5SDimitry Andric   const R600InstrInfo *TII = ST.getInstrInfo();
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   // Instantiate the packetizer.
3270b57cec5SDimitry Andric   R600PacketizerList Packetizer(Fn, ST, MLI);
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   // DFA state table should not be empty.
3300b57cec5SDimitry Andric   assert(Packetizer.getResourceTracker() && "Empty DFA table!");
3310b57cec5SDimitry Andric   assert(Packetizer.getResourceTracker()->getInstrItins());
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric   if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty())
3340b57cec5SDimitry Andric     return false;
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   //
3370b57cec5SDimitry Andric   // Loop over all basic blocks and remove KILL pseudo-instructions
3380b57cec5SDimitry Andric   // These instructions confuse the dependence analysis. Consider:
3390b57cec5SDimitry Andric   // D0 = ...   (Insn 0)
3400b57cec5SDimitry Andric   // R0 = KILL R0, D0 (Insn 1)
3410b57cec5SDimitry Andric   // R0 = ... (Insn 2)
3420b57cec5SDimitry Andric   // Here, Insn 1 will result in the dependence graph not emitting an output
3430b57cec5SDimitry Andric   // dependence between Insn 0 and Insn 2. This can lead to incorrect
3440b57cec5SDimitry Andric   // packetization
3450b57cec5SDimitry Andric   //
3464824e7fdSDimitry Andric   for (MachineBasicBlock &MBB : Fn) {
3474824e7fdSDimitry Andric     for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
3484824e7fdSDimitry Andric       if (MI.isKill() || MI.getOpcode() == R600::IMPLICIT_DEF ||
3494824e7fdSDimitry Andric           (MI.getOpcode() == R600::CF_ALU && !MI.getOperand(8).getImm()))
3504824e7fdSDimitry Andric         MBB.erase(MI);
3510b57cec5SDimitry Andric     }
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   // Loop over all of the basic blocks.
3550b57cec5SDimitry Andric   for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
3560b57cec5SDimitry Andric        MBB != MBBe; ++MBB) {
3570b57cec5SDimitry Andric     // Find scheduling regions and schedule / packetize each region.
3580b57cec5SDimitry Andric     unsigned RemainingCount = MBB->size();
3590b57cec5SDimitry Andric     for(MachineBasicBlock::iterator RegionEnd = MBB->end();
3600b57cec5SDimitry Andric         RegionEnd != MBB->begin();) {
3610b57cec5SDimitry Andric       // The next region starts above the previous region. Look backward in the
3620b57cec5SDimitry Andric       // instruction stream until we find the nearest boundary.
3630b57cec5SDimitry Andric       MachineBasicBlock::iterator I = RegionEnd;
3640b57cec5SDimitry Andric       for(;I != MBB->begin(); --I, --RemainingCount) {
3650b57cec5SDimitry Andric         if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn))
3660b57cec5SDimitry Andric           break;
3670b57cec5SDimitry Andric       }
3680b57cec5SDimitry Andric       I = MBB->begin();
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric       // Skip empty scheduling regions.
3710b57cec5SDimitry Andric       if (I == RegionEnd) {
3720b57cec5SDimitry Andric         RegionEnd = std::prev(RegionEnd);
3730b57cec5SDimitry Andric         --RemainingCount;
3740b57cec5SDimitry Andric         continue;
3750b57cec5SDimitry Andric       }
3760b57cec5SDimitry Andric       // Skip regions with one instruction.
3770b57cec5SDimitry Andric       if (I == std::prev(RegionEnd)) {
3780b57cec5SDimitry Andric         RegionEnd = std::prev(RegionEnd);
3790b57cec5SDimitry Andric         continue;
3800b57cec5SDimitry Andric       }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric       Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd);
3830b57cec5SDimitry Andric       RegionEnd = I;
3840b57cec5SDimitry Andric     }
3850b57cec5SDimitry Andric   }
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   return true;
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric }
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric } // end anonymous namespace
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(R600Packetizer, DEBUG_TYPE,
3940b57cec5SDimitry Andric                      "R600 Packetizer", false, false)
3950b57cec5SDimitry Andric INITIALIZE_PASS_END(R600Packetizer, DEBUG_TYPE,
3960b57cec5SDimitry Andric                     "R600 Packetizer", false, false)
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric char R600Packetizer::ID = 0;
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric char &llvm::R600PacketizerID = R600Packetizer::ID;
4010b57cec5SDimitry Andric 
createR600Packetizer()4020b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() {
4030b57cec5SDimitry Andric   return new R600Packetizer();
4040b57cec5SDimitry Andric }
405