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