18f0fd8f6SDimitry Andric //===----- R600Packetizer.cpp - VLIW packetizer ---------------------------===// 28f0fd8f6SDimitry Andric // 38f0fd8f6SDimitry Andric // The LLVM Compiler Infrastructure 48f0fd8f6SDimitry Andric // 58f0fd8f6SDimitry Andric // This file is distributed under the University of Illinois Open Source 68f0fd8f6SDimitry Andric // License. See LICENSE.TXT for details. 78f0fd8f6SDimitry Andric // 88f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 98f0fd8f6SDimitry Andric // 108f0fd8f6SDimitry Andric /// \file 118f0fd8f6SDimitry Andric /// This pass implements instructions packetization for R600. It unsets isLast 128f0fd8f6SDimitry Andric /// bit of instructions inside a bundle and substitutes src register with 138f0fd8f6SDimitry Andric /// PreviousVector when applicable. 148f0fd8f6SDimitry Andric // 158f0fd8f6SDimitry Andric //===----------------------------------------------------------------------===// 168f0fd8f6SDimitry Andric 178f0fd8f6SDimitry Andric #include "llvm/Support/Debug.h" 188f0fd8f6SDimitry Andric #include "AMDGPU.h" 198f0fd8f6SDimitry Andric #include "AMDGPUSubtarget.h" 208f0fd8f6SDimitry Andric #include "R600InstrInfo.h" 218f0fd8f6SDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h" 228f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 238f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 248f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 258f0fd8f6SDimitry Andric #include "llvm/CodeGen/Passes.h" 268f0fd8f6SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 278f0fd8f6SDimitry Andric #include "llvm/Support/raw_ostream.h" 288f0fd8f6SDimitry Andric 298f0fd8f6SDimitry Andric using namespace llvm; 308f0fd8f6SDimitry Andric 318f0fd8f6SDimitry Andric #define DEBUG_TYPE "packets" 328f0fd8f6SDimitry Andric 338f0fd8f6SDimitry Andric namespace { 348f0fd8f6SDimitry Andric 358f0fd8f6SDimitry Andric class R600Packetizer : public MachineFunctionPass { 368f0fd8f6SDimitry Andric 378f0fd8f6SDimitry Andric public: 388f0fd8f6SDimitry Andric static char ID; 398f0fd8f6SDimitry Andric R600Packetizer(const TargetMachine &TM) : MachineFunctionPass(ID) {} 408f0fd8f6SDimitry Andric 418f0fd8f6SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 428f0fd8f6SDimitry Andric AU.setPreservesCFG(); 438f0fd8f6SDimitry Andric AU.addRequired<MachineDominatorTree>(); 448f0fd8f6SDimitry Andric AU.addPreserved<MachineDominatorTree>(); 458f0fd8f6SDimitry Andric AU.addRequired<MachineLoopInfo>(); 468f0fd8f6SDimitry Andric AU.addPreserved<MachineLoopInfo>(); 478f0fd8f6SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 488f0fd8f6SDimitry Andric } 498f0fd8f6SDimitry Andric 508f0fd8f6SDimitry Andric const char *getPassName() const override { 518f0fd8f6SDimitry Andric return "R600 Packetizer"; 528f0fd8f6SDimitry Andric } 538f0fd8f6SDimitry Andric 548f0fd8f6SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 558f0fd8f6SDimitry Andric }; 568f0fd8f6SDimitry Andric char R600Packetizer::ID = 0; 578f0fd8f6SDimitry Andric 588f0fd8f6SDimitry Andric class R600PacketizerList : public VLIWPacketizerList { 598f0fd8f6SDimitry Andric private: 608f0fd8f6SDimitry Andric const R600InstrInfo *TII; 618f0fd8f6SDimitry Andric const R600RegisterInfo &TRI; 628f0fd8f6SDimitry Andric bool VLIW5; 638f0fd8f6SDimitry Andric bool ConsideredInstUsesAlreadyWrittenVectorElement; 648f0fd8f6SDimitry Andric 653ca95b02SDimitry Andric unsigned getSlot(const MachineInstr &MI) const { 663ca95b02SDimitry Andric return TRI.getHWRegChan(MI.getOperand(0).getReg()); 678f0fd8f6SDimitry Andric } 688f0fd8f6SDimitry Andric 698f0fd8f6SDimitry Andric /// \returns register to PV chan mapping for bundle/single instructions that 708f0fd8f6SDimitry Andric /// immediately precedes I. 718f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I) 728f0fd8f6SDimitry Andric const { 738f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> Result; 748f0fd8f6SDimitry Andric I--; 758f0fd8f6SDimitry Andric if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle()) 768f0fd8f6SDimitry Andric return Result; 778f0fd8f6SDimitry Andric MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); 788f0fd8f6SDimitry Andric if (I->isBundle()) 798f0fd8f6SDimitry Andric BI++; 808f0fd8f6SDimitry Andric int LastDstChan = -1; 818f0fd8f6SDimitry Andric do { 828f0fd8f6SDimitry Andric bool isTrans = false; 833ca95b02SDimitry Andric int BISlot = getSlot(*BI); 848f0fd8f6SDimitry Andric if (LastDstChan >= BISlot) 858f0fd8f6SDimitry Andric isTrans = true; 868f0fd8f6SDimitry Andric LastDstChan = BISlot; 873ca95b02SDimitry Andric if (TII->isPredicated(*BI)) 888f0fd8f6SDimitry Andric continue; 898f0fd8f6SDimitry Andric int OperandIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::write); 908f0fd8f6SDimitry Andric if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0) 918f0fd8f6SDimitry Andric continue; 928f0fd8f6SDimitry Andric int DstIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::dst); 938f0fd8f6SDimitry Andric if (DstIdx == -1) { 948f0fd8f6SDimitry Andric continue; 958f0fd8f6SDimitry Andric } 968f0fd8f6SDimitry Andric unsigned Dst = BI->getOperand(DstIdx).getReg(); 973ca95b02SDimitry Andric if (isTrans || TII->isTransOnly(*BI)) { 988f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PS; 998f0fd8f6SDimitry Andric continue; 1008f0fd8f6SDimitry Andric } 1018f0fd8f6SDimitry Andric if (BI->getOpcode() == AMDGPU::DOT4_r600 || 1028f0fd8f6SDimitry Andric BI->getOpcode() == AMDGPU::DOT4_eg) { 1038f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PV_X; 1048f0fd8f6SDimitry Andric continue; 1058f0fd8f6SDimitry Andric } 1068f0fd8f6SDimitry Andric if (Dst == AMDGPU::OQAP) { 1078f0fd8f6SDimitry Andric continue; 1088f0fd8f6SDimitry Andric } 1098f0fd8f6SDimitry Andric unsigned PVReg = 0; 1108f0fd8f6SDimitry Andric switch (TRI.getHWRegChan(Dst)) { 1118f0fd8f6SDimitry Andric case 0: 1128f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_X; 1138f0fd8f6SDimitry Andric break; 1148f0fd8f6SDimitry Andric case 1: 1158f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Y; 1168f0fd8f6SDimitry Andric break; 1178f0fd8f6SDimitry Andric case 2: 1188f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Z; 1198f0fd8f6SDimitry Andric break; 1208f0fd8f6SDimitry Andric case 3: 1218f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_W; 1228f0fd8f6SDimitry Andric break; 1238f0fd8f6SDimitry Andric default: 1248f0fd8f6SDimitry Andric llvm_unreachable("Invalid Chan"); 1258f0fd8f6SDimitry Andric } 1268f0fd8f6SDimitry Andric Result[Dst] = PVReg; 1278f0fd8f6SDimitry Andric } while ((++BI)->isBundledWithPred()); 1288f0fd8f6SDimitry Andric return Result; 1298f0fd8f6SDimitry Andric } 1308f0fd8f6SDimitry Andric 1313ca95b02SDimitry Andric void substitutePV(MachineInstr &MI, const DenseMap<unsigned, unsigned> &PVs) 1328f0fd8f6SDimitry Andric const { 1338f0fd8f6SDimitry Andric unsigned Ops[] = { 1348f0fd8f6SDimitry Andric AMDGPU::OpName::src0, 1358f0fd8f6SDimitry Andric AMDGPU::OpName::src1, 1368f0fd8f6SDimitry Andric AMDGPU::OpName::src2 1378f0fd8f6SDimitry Andric }; 1388f0fd8f6SDimitry Andric for (unsigned i = 0; i < 3; i++) { 1393ca95b02SDimitry Andric int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Ops[i]); 1408f0fd8f6SDimitry Andric if (OperandIdx < 0) 1418f0fd8f6SDimitry Andric continue; 1423ca95b02SDimitry Andric unsigned Src = MI.getOperand(OperandIdx).getReg(); 1438f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src); 1448f0fd8f6SDimitry Andric if (It != PVs.end()) 1453ca95b02SDimitry Andric MI.getOperand(OperandIdx).setReg(It->second); 1468f0fd8f6SDimitry Andric } 1478f0fd8f6SDimitry Andric } 1488f0fd8f6SDimitry Andric public: 1498f0fd8f6SDimitry Andric // Ctor. 1503ca95b02SDimitry Andric R600PacketizerList(MachineFunction &MF, const R600Subtarget &ST, 1513ca95b02SDimitry Andric MachineLoopInfo &MLI) 1527d523365SDimitry Andric : VLIWPacketizerList(MF, MLI, nullptr), 1533ca95b02SDimitry Andric TII(ST.getInstrInfo()), 1548f0fd8f6SDimitry Andric TRI(TII->getRegisterInfo()) { 1553ca95b02SDimitry Andric VLIW5 = !ST.hasCaymanISA(); 1568f0fd8f6SDimitry Andric } 1578f0fd8f6SDimitry Andric 1588f0fd8f6SDimitry Andric // initPacketizerState - initialize some internal flags. 1598f0fd8f6SDimitry Andric void initPacketizerState() override { 1608f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 1618f0fd8f6SDimitry Andric } 1628f0fd8f6SDimitry Andric 1638f0fd8f6SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 1643ca95b02SDimitry Andric bool ignorePseudoInstruction(const MachineInstr &MI, 1657d523365SDimitry Andric const MachineBasicBlock *MBB) override { 1668f0fd8f6SDimitry Andric return false; 1678f0fd8f6SDimitry Andric } 1688f0fd8f6SDimitry Andric 1698f0fd8f6SDimitry Andric // isSoloInstruction - return true if instruction MI can not be packetized 1708f0fd8f6SDimitry Andric // with any other instruction, which means that MI itself is a packet. 1713ca95b02SDimitry Andric bool isSoloInstruction(const MachineInstr &MI) override { 1723ca95b02SDimitry Andric if (TII->isVector(MI)) 1738f0fd8f6SDimitry Andric return true; 1743ca95b02SDimitry Andric if (!TII->isALUInstr(MI.getOpcode())) 1758f0fd8f6SDimitry Andric return true; 1763ca95b02SDimitry Andric if (MI.getOpcode() == AMDGPU::GROUP_BARRIER) 1778f0fd8f6SDimitry Andric return true; 1788f0fd8f6SDimitry Andric // XXX: This can be removed once the packetizer properly handles all the 1798f0fd8f6SDimitry Andric // LDS instruction group restrictions. 1803ca95b02SDimitry Andric return TII->isLDSInstr(MI.getOpcode()); 1818f0fd8f6SDimitry Andric } 1828f0fd8f6SDimitry Andric 1838f0fd8f6SDimitry Andric // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ 1848f0fd8f6SDimitry Andric // together. 1858f0fd8f6SDimitry Andric bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override { 1868f0fd8f6SDimitry Andric MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); 1873ca95b02SDimitry Andric if (getSlot(*MII) == getSlot(*MIJ)) 1888f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = true; 1898f0fd8f6SDimitry Andric // Does MII and MIJ share the same pred_sel ? 1908f0fd8f6SDimitry Andric int OpI = TII->getOperandIdx(MII->getOpcode(), AMDGPU::OpName::pred_sel), 1918f0fd8f6SDimitry Andric OpJ = TII->getOperandIdx(MIJ->getOpcode(), AMDGPU::OpName::pred_sel); 1928f0fd8f6SDimitry Andric unsigned PredI = (OpI > -1)?MII->getOperand(OpI).getReg():0, 1938f0fd8f6SDimitry Andric PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg():0; 1948f0fd8f6SDimitry Andric if (PredI != PredJ) 1958f0fd8f6SDimitry Andric return false; 1968f0fd8f6SDimitry Andric if (SUJ->isSucc(SUI)) { 1978f0fd8f6SDimitry Andric for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) { 1988f0fd8f6SDimitry Andric const SDep &Dep = SUJ->Succs[i]; 1998f0fd8f6SDimitry Andric if (Dep.getSUnit() != SUI) 2008f0fd8f6SDimitry Andric continue; 2018f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Anti) 2028f0fd8f6SDimitry Andric continue; 2038f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Output) 2048f0fd8f6SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 2058f0fd8f6SDimitry Andric continue; 2068f0fd8f6SDimitry Andric return false; 2078f0fd8f6SDimitry Andric } 2088f0fd8f6SDimitry Andric } 2098f0fd8f6SDimitry Andric 2103ca95b02SDimitry Andric bool ARDef = 2113ca95b02SDimitry Andric TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ); 2123ca95b02SDimitry Andric bool ARUse = 2133ca95b02SDimitry Andric TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ); 2148f0fd8f6SDimitry Andric 2153ca95b02SDimitry Andric return !ARDef || !ARUse; 2168f0fd8f6SDimitry Andric } 2178f0fd8f6SDimitry Andric 2188f0fd8f6SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependece between SUI 2198f0fd8f6SDimitry Andric // and SUJ. 2208f0fd8f6SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2218f0fd8f6SDimitry Andric return false; 2228f0fd8f6SDimitry Andric } 2238f0fd8f6SDimitry Andric 2248f0fd8f6SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 2258f0fd8f6SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::last); 2268f0fd8f6SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 2278f0fd8f6SDimitry Andric } 2288f0fd8f6SDimitry Andric 2293ca95b02SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr &MI, 2308f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 2318f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 2328f0fd8f6SDimitry Andric bool &isTransSlot) { 2338f0fd8f6SDimitry Andric isTransSlot = TII->isTransOnly(MI); 2348f0fd8f6SDimitry Andric assert (!isTransSlot || VLIW5); 2358f0fd8f6SDimitry Andric 2368f0fd8f6SDimitry Andric // Is the dst reg sequence legal ? 2378f0fd8f6SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 2383ca95b02SDimitry Andric if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) { 2398f0fd8f6SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 2408f0fd8f6SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 2418f0fd8f6SDimitry Andric isTransSlot = true; 2423ca95b02SDimitry Andric DEBUG({ 2433ca95b02SDimitry Andric dbgs() << "Considering as Trans Inst :"; 2443ca95b02SDimitry Andric MI.dump(); 2453ca95b02SDimitry Andric }); 2468f0fd8f6SDimitry Andric } 2478f0fd8f6SDimitry Andric else 2488f0fd8f6SDimitry Andric return false; 2498f0fd8f6SDimitry Andric } 2508f0fd8f6SDimitry Andric } 2518f0fd8f6SDimitry Andric 2528f0fd8f6SDimitry Andric // Are the Constants limitations met ? 2533ca95b02SDimitry Andric CurrentPacketMIs.push_back(&MI); 2548f0fd8f6SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 2553ca95b02SDimitry Andric DEBUG({ 2568f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2573ca95b02SDimitry Andric MI.dump(); 2588f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2598f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2608f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2618f0fd8f6SDimitry Andric dbgs() << "\n"; 2628f0fd8f6SDimitry Andric } 2638f0fd8f6SDimitry Andric dbgs() << "because of Consts read limitations\n"; 2643ca95b02SDimitry Andric }); 2658f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2668f0fd8f6SDimitry Andric return false; 2678f0fd8f6SDimitry Andric } 2688f0fd8f6SDimitry Andric 2698f0fd8f6SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 2708f0fd8f6SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 2718f0fd8f6SDimitry Andric PV, BS, isTransSlot)) { 2723ca95b02SDimitry Andric DEBUG({ 2738f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2743ca95b02SDimitry Andric MI.dump(); 2758f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2768f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2778f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2788f0fd8f6SDimitry Andric dbgs() << "\n"; 2798f0fd8f6SDimitry Andric } 2808f0fd8f6SDimitry Andric dbgs() << "because of Read port limitations\n"; 2813ca95b02SDimitry Andric }); 2828f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2838f0fd8f6SDimitry Andric return false; 2848f0fd8f6SDimitry Andric } 2858f0fd8f6SDimitry Andric 2868f0fd8f6SDimitry Andric // We cannot read LDS source registrs from the Trans slot. 2878f0fd8f6SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 2888f0fd8f6SDimitry Andric return false; 2898f0fd8f6SDimitry Andric 2908f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2918f0fd8f6SDimitry Andric return true; 2928f0fd8f6SDimitry Andric } 2938f0fd8f6SDimitry Andric 2943ca95b02SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override { 2958f0fd8f6SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 2963ca95b02SDimitry Andric CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front(); 2978f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 2988f0fd8f6SDimitry Andric getPreviousVector(FirstInBundle); 2998f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 3008f0fd8f6SDimitry Andric bool isTransSlot; 3018f0fd8f6SDimitry Andric 3028f0fd8f6SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 3038f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 3048f0fd8f6SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 3058f0fd8f6SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 3068f0fd8f6SDimitry Andric AMDGPU::OpName::bank_swizzle); 3078f0fd8f6SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 3088f0fd8f6SDimitry Andric } 3093ca95b02SDimitry Andric unsigned Op = 3103ca95b02SDimitry Andric TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::bank_swizzle); 3113ca95b02SDimitry Andric MI.getOperand(Op).setImm(BS.back()); 3128f0fd8f6SDimitry Andric if (!CurrentPacketMIs.empty()) 3138f0fd8f6SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 3148f0fd8f6SDimitry Andric substitutePV(MI, PV); 3158f0fd8f6SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 3168f0fd8f6SDimitry Andric if (isTransSlot) { 3178f0fd8f6SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 3188f0fd8f6SDimitry Andric } 3198f0fd8f6SDimitry Andric return It; 3208f0fd8f6SDimitry Andric } 3213ca95b02SDimitry Andric endPacket(MI.getParent(), MI); 3228f0fd8f6SDimitry Andric if (TII->isTransOnly(MI)) 3238f0fd8f6SDimitry Andric return MI; 3248f0fd8f6SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 3258f0fd8f6SDimitry Andric } 3268f0fd8f6SDimitry Andric }; 3278f0fd8f6SDimitry Andric 3288f0fd8f6SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 3293ca95b02SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 3303ca95b02SDimitry Andric const R600InstrInfo *TII = ST.getInstrInfo(); 3313ca95b02SDimitry Andric 3328f0fd8f6SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 3338f0fd8f6SDimitry Andric 3348f0fd8f6SDimitry Andric // Instantiate the packetizer. 3353ca95b02SDimitry Andric R600PacketizerList Packetizer(Fn, ST, MLI); 3368f0fd8f6SDimitry Andric 3378f0fd8f6SDimitry Andric // DFA state table should not be empty. 3388f0fd8f6SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 3398f0fd8f6SDimitry Andric 3403ca95b02SDimitry Andric if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty()) 3413ca95b02SDimitry Andric return false; 3423ca95b02SDimitry Andric 3438f0fd8f6SDimitry Andric // 3448f0fd8f6SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 3458f0fd8f6SDimitry Andric // These instructions confuse the dependence analysis. Consider: 3468f0fd8f6SDimitry Andric // D0 = ... (Insn 0) 3478f0fd8f6SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 3488f0fd8f6SDimitry Andric // R0 = ... (Insn 2) 3498f0fd8f6SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 3508f0fd8f6SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 3518f0fd8f6SDimitry Andric // packetization 3528f0fd8f6SDimitry Andric // 3538f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3548f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3558f0fd8f6SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 3568f0fd8f6SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 3578f0fd8f6SDimitry Andric while (MI != End) { 3588f0fd8f6SDimitry Andric if (MI->isKill() || MI->getOpcode() == AMDGPU::IMPLICIT_DEF || 3598f0fd8f6SDimitry Andric (MI->getOpcode() == AMDGPU::CF_ALU && !MI->getOperand(8).getImm())) { 3608f0fd8f6SDimitry Andric MachineBasicBlock::iterator DeleteMI = MI; 3618f0fd8f6SDimitry Andric ++MI; 3628f0fd8f6SDimitry Andric MBB->erase(DeleteMI); 3638f0fd8f6SDimitry Andric End = MBB->end(); 3648f0fd8f6SDimitry Andric continue; 3658f0fd8f6SDimitry Andric } 3668f0fd8f6SDimitry Andric ++MI; 3678f0fd8f6SDimitry Andric } 3688f0fd8f6SDimitry Andric } 3698f0fd8f6SDimitry Andric 3708f0fd8f6SDimitry Andric // Loop over all of the basic blocks. 3718f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3728f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3738f0fd8f6SDimitry Andric // Find scheduling regions and schedule / packetize each region. 3748f0fd8f6SDimitry Andric unsigned RemainingCount = MBB->size(); 3758f0fd8f6SDimitry Andric for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 3768f0fd8f6SDimitry Andric RegionEnd != MBB->begin();) { 3778f0fd8f6SDimitry Andric // The next region starts above the previous region. Look backward in the 3788f0fd8f6SDimitry Andric // instruction stream until we find the nearest boundary. 3798f0fd8f6SDimitry Andric MachineBasicBlock::iterator I = RegionEnd; 3808f0fd8f6SDimitry Andric for(;I != MBB->begin(); --I, --RemainingCount) { 3813ca95b02SDimitry Andric if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn)) 3828f0fd8f6SDimitry Andric break; 3838f0fd8f6SDimitry Andric } 3848f0fd8f6SDimitry Andric I = MBB->begin(); 3858f0fd8f6SDimitry Andric 3868f0fd8f6SDimitry Andric // Skip empty scheduling regions. 3878f0fd8f6SDimitry Andric if (I == RegionEnd) { 3888f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3898f0fd8f6SDimitry Andric --RemainingCount; 3908f0fd8f6SDimitry Andric continue; 3918f0fd8f6SDimitry Andric } 3928f0fd8f6SDimitry Andric // Skip regions with one instruction. 3938f0fd8f6SDimitry Andric if (I == std::prev(RegionEnd)) { 3948f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3958f0fd8f6SDimitry Andric continue; 3968f0fd8f6SDimitry Andric } 3978f0fd8f6SDimitry Andric 3987d523365SDimitry Andric Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd); 3998f0fd8f6SDimitry Andric RegionEnd = I; 4008f0fd8f6SDimitry Andric } 4018f0fd8f6SDimitry Andric } 4028f0fd8f6SDimitry Andric 4038f0fd8f6SDimitry Andric return true; 4048f0fd8f6SDimitry Andric 4058f0fd8f6SDimitry Andric } 4068f0fd8f6SDimitry Andric 4078f0fd8f6SDimitry Andric } // end anonymous namespace 4088f0fd8f6SDimitry Andric 4098f0fd8f6SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer(TargetMachine &tm) { 4108f0fd8f6SDimitry Andric return new R600Packetizer(tm); 4118f0fd8f6SDimitry Andric } 412