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(); 38*0fca6ea1SDimitry Andric AU.addRequired<MachineDominatorTreeWrapperPass>(); 39*0fca6ea1SDimitry Andric AU.addPreserved<MachineDominatorTreeWrapperPass>(); 40*0fca6ea1SDimitry Andric AU.addRequired<MachineLoopInfoWrapperPass>(); 41*0fca6ea1SDimitry Andric AU.addPreserved<MachineLoopInfoWrapperPass>(); 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)) { 189*0fca6ea1SDimitry Andric for (const SDep &Dep : SUJ->Succs) { 1900b57cec5SDimitry Andric if (Dep.getSUnit() != SUI) 1910b57cec5SDimitry Andric continue; 1920b57cec5SDimitry Andric if (Dep.getKind() == SDep::Anti) 1930b57cec5SDimitry Andric continue; 1940b57cec5SDimitry Andric if (Dep.getKind() == SDep::Output) 1950b57cec5SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 1960b57cec5SDimitry Andric continue; 1970b57cec5SDimitry Andric return false; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric bool ARDef = 2020b57cec5SDimitry Andric TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ); 2030b57cec5SDimitry Andric bool ARUse = 2040b57cec5SDimitry Andric TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ); 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric return !ARDef || !ARUse; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 20981ad6265SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependency between SUI 2100b57cec5SDimitry Andric // and SUJ. 2110b57cec5SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2120b57cec5SDimitry Andric return false; 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 2160b57cec5SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), R600::OpName::last); 2170b57cec5SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr &MI, 2210b57cec5SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 2220b57cec5SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 2230b57cec5SDimitry Andric bool &isTransSlot) { 2240b57cec5SDimitry Andric isTransSlot = TII->isTransOnly(MI); 2250b57cec5SDimitry Andric assert (!isTransSlot || VLIW5); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric // Is the dst reg sequence legal ? 2280b57cec5SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 2290b57cec5SDimitry Andric if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) { 2300b57cec5SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 2310b57cec5SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 2320b57cec5SDimitry Andric isTransSlot = true; 2330b57cec5SDimitry Andric LLVM_DEBUG({ 2340b57cec5SDimitry Andric dbgs() << "Considering as Trans Inst :"; 2350b57cec5SDimitry Andric MI.dump(); 2360b57cec5SDimitry Andric }); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric else 2390b57cec5SDimitry Andric return false; 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric } 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric // Are the Constants limitations met ? 2440b57cec5SDimitry Andric CurrentPacketMIs.push_back(&MI); 2450b57cec5SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 2460b57cec5SDimitry Andric LLVM_DEBUG({ 2470b57cec5SDimitry Andric dbgs() << "Couldn't pack :\n"; 2480b57cec5SDimitry Andric MI.dump(); 2490b57cec5SDimitry Andric dbgs() << "with the following packets :\n"; 2500b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2510b57cec5SDimitry Andric CurrentPacketMIs[i]->dump(); 2520b57cec5SDimitry Andric dbgs() << "\n"; 2530b57cec5SDimitry Andric } 2540b57cec5SDimitry Andric dbgs() << "because of Consts read limitations\n"; 2550b57cec5SDimitry Andric }); 2560b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 2570b57cec5SDimitry Andric return false; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 2610b57cec5SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 2620b57cec5SDimitry Andric PV, BS, isTransSlot)) { 2630b57cec5SDimitry Andric LLVM_DEBUG({ 2640b57cec5SDimitry Andric dbgs() << "Couldn't pack :\n"; 2650b57cec5SDimitry Andric MI.dump(); 2660b57cec5SDimitry Andric dbgs() << "with the following packets :\n"; 2670b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2680b57cec5SDimitry Andric CurrentPacketMIs[i]->dump(); 2690b57cec5SDimitry Andric dbgs() << "\n"; 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric dbgs() << "because of Read port limitations\n"; 2720b57cec5SDimitry Andric }); 2730b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 2740b57cec5SDimitry Andric return false; 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // We cannot read LDS source registers from the Trans slot. 2780b57cec5SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 2790b57cec5SDimitry Andric return false; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 2820b57cec5SDimitry Andric return true; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override { 2860b57cec5SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 2870b57cec5SDimitry Andric CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front(); 2880b57cec5SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 2890b57cec5SDimitry Andric getPreviousVector(FirstInBundle); 2900b57cec5SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 2910b57cec5SDimitry Andric bool isTransSlot; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 2940b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 2950b57cec5SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 2960b57cec5SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 2970b57cec5SDimitry Andric R600::OpName::bank_swizzle); 2980b57cec5SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric unsigned Op = 3010b57cec5SDimitry Andric TII->getOperandIdx(MI.getOpcode(), R600::OpName::bank_swizzle); 3020b57cec5SDimitry Andric MI.getOperand(Op).setImm(BS.back()); 3030b57cec5SDimitry Andric if (!CurrentPacketMIs.empty()) 3040b57cec5SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 3050b57cec5SDimitry Andric substitutePV(MI, PV); 3060b57cec5SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 3070b57cec5SDimitry Andric if (isTransSlot) { 3080b57cec5SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 3090b57cec5SDimitry Andric } 3100b57cec5SDimitry Andric return It; 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric endPacket(MI.getParent(), MI); 3130b57cec5SDimitry Andric if (TII->isTransOnly(MI)) 3140b57cec5SDimitry Andric return MI; 3150b57cec5SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 3160b57cec5SDimitry Andric } 3170b57cec5SDimitry Andric }; 3180b57cec5SDimitry Andric 3190b57cec5SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 3200b57cec5SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 3210b57cec5SDimitry Andric const R600InstrInfo *TII = ST.getInstrInfo(); 3220b57cec5SDimitry Andric 323*0fca6ea1SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfoWrapperPass>().getLI(); 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric // Instantiate the packetizer. 3260b57cec5SDimitry Andric R600PacketizerList Packetizer(Fn, ST, MLI); 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric // DFA state table should not be empty. 3290b57cec5SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 3300b57cec5SDimitry Andric assert(Packetizer.getResourceTracker()->getInstrItins()); 3310b57cec5SDimitry Andric 3320b57cec5SDimitry Andric if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty()) 3330b57cec5SDimitry Andric return false; 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric // 3360b57cec5SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 3370b57cec5SDimitry Andric // These instructions confuse the dependence analysis. Consider: 3380b57cec5SDimitry Andric // D0 = ... (Insn 0) 3390b57cec5SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 3400b57cec5SDimitry Andric // R0 = ... (Insn 2) 3410b57cec5SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 3420b57cec5SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 3430b57cec5SDimitry Andric // packetization 3440b57cec5SDimitry Andric // 3454824e7fdSDimitry Andric for (MachineBasicBlock &MBB : Fn) { 3464824e7fdSDimitry Andric for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) { 3474824e7fdSDimitry Andric if (MI.isKill() || MI.getOpcode() == R600::IMPLICIT_DEF || 3484824e7fdSDimitry Andric (MI.getOpcode() == R600::CF_ALU && !MI.getOperand(8).getImm())) 3494824e7fdSDimitry Andric MBB.erase(MI); 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric // Loop over all of the basic blocks. 3540b57cec5SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3550b57cec5SDimitry Andric MBB != MBBe; ++MBB) { 3560b57cec5SDimitry Andric // Find scheduling regions and schedule / packetize each region. 3570b57cec5SDimitry Andric unsigned RemainingCount = MBB->size(); 3580b57cec5SDimitry Andric for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 3590b57cec5SDimitry Andric RegionEnd != MBB->begin();) { 3600b57cec5SDimitry Andric // The next region starts above the previous region. Look backward in the 3610b57cec5SDimitry Andric // instruction stream until we find the nearest boundary. 3620b57cec5SDimitry Andric MachineBasicBlock::iterator I = RegionEnd; 3630b57cec5SDimitry Andric for(;I != MBB->begin(); --I, --RemainingCount) { 3640b57cec5SDimitry Andric if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn)) 3650b57cec5SDimitry Andric break; 3660b57cec5SDimitry Andric } 3670b57cec5SDimitry Andric I = MBB->begin(); 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric // Skip empty scheduling regions. 3700b57cec5SDimitry Andric if (I == RegionEnd) { 3710b57cec5SDimitry Andric RegionEnd = std::prev(RegionEnd); 3720b57cec5SDimitry Andric --RemainingCount; 3730b57cec5SDimitry Andric continue; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric // Skip regions with one instruction. 3760b57cec5SDimitry Andric if (I == std::prev(RegionEnd)) { 3770b57cec5SDimitry Andric RegionEnd = std::prev(RegionEnd); 3780b57cec5SDimitry Andric continue; 3790b57cec5SDimitry Andric } 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd); 3820b57cec5SDimitry Andric RegionEnd = I; 3830b57cec5SDimitry Andric } 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric return true; 3870b57cec5SDimitry Andric 3880b57cec5SDimitry Andric } 3890b57cec5SDimitry Andric 3900b57cec5SDimitry Andric } // end anonymous namespace 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(R600Packetizer, DEBUG_TYPE, 3930b57cec5SDimitry Andric "R600 Packetizer", false, false) 3940b57cec5SDimitry Andric INITIALIZE_PASS_END(R600Packetizer, DEBUG_TYPE, 3950b57cec5SDimitry Andric "R600 Packetizer", false, false) 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric char R600Packetizer::ID = 0; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric char &llvm::R600PacketizerID = R600Packetizer::ID; 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() { 4020b57cec5SDimitry Andric return new R600Packetizer(); 4030b57cec5SDimitry Andric } 404