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; 340b57cec5SDimitry Andric R600Packetizer() : MachineFunctionPass(ID) {} 350b57cec5SDimitry Andric 360b57cec5SDimitry 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 450b57cec5SDimitry 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 570b57cec5SDimitry 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. 630b57cec5SDimitry 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 1230b57cec5SDimitry 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. 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. 1510b57cec5SDimitry Andric void initPacketizerState() override { 1520b57cec5SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 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. 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. 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 210*81ad6265SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependency between SUI 2110b57cec5SDimitry Andric // and SUJ. 2120b57cec5SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2130b57cec5SDimitry Andric return false; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry 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 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 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 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 4020b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() { 4030b57cec5SDimitry Andric return new R600Packetizer(); 4040b57cec5SDimitry Andric } 405