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 "AMDGPU.h" 188f0fd8f6SDimitry Andric #include "AMDGPUSubtarget.h" 198f0fd8f6SDimitry Andric #include "R600InstrInfo.h" 208f0fd8f6SDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h" 218f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 228f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 238f0fd8f6SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 248f0fd8f6SDimitry Andric #include "llvm/CodeGen/Passes.h" 258f0fd8f6SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 26db17bf38SDimitry Andric #include "llvm/Support/Debug.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; 39d8866befSDimitry Andric R600Packetizer() : 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 50d88c1a5aSDimitry Andric StringRef getPassName() const override { return "R600 Packetizer"; } 518f0fd8f6SDimitry Andric 528f0fd8f6SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 538f0fd8f6SDimitry Andric }; 548f0fd8f6SDimitry Andric char R600Packetizer::ID = 0; 558f0fd8f6SDimitry Andric 568f0fd8f6SDimitry Andric class R600PacketizerList : public VLIWPacketizerList { 578f0fd8f6SDimitry Andric private: 588f0fd8f6SDimitry Andric const R600InstrInfo *TII; 598f0fd8f6SDimitry Andric const R600RegisterInfo &TRI; 608f0fd8f6SDimitry Andric bool VLIW5; 618f0fd8f6SDimitry Andric bool ConsideredInstUsesAlreadyWrittenVectorElement; 628f0fd8f6SDimitry Andric 633ca95b02SDimitry Andric unsigned getSlot(const MachineInstr &MI) const { 643ca95b02SDimitry Andric return TRI.getHWRegChan(MI.getOperand(0).getReg()); 658f0fd8f6SDimitry Andric } 668f0fd8f6SDimitry Andric 678f0fd8f6SDimitry Andric /// \returns register to PV chan mapping for bundle/single instructions that 688f0fd8f6SDimitry Andric /// immediately precedes I. 698f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I) 708f0fd8f6SDimitry Andric const { 718f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> Result; 728f0fd8f6SDimitry Andric I--; 738f0fd8f6SDimitry Andric if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle()) 748f0fd8f6SDimitry Andric return Result; 758f0fd8f6SDimitry Andric MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); 768f0fd8f6SDimitry Andric if (I->isBundle()) 778f0fd8f6SDimitry Andric BI++; 788f0fd8f6SDimitry Andric int LastDstChan = -1; 798f0fd8f6SDimitry Andric do { 808f0fd8f6SDimitry Andric bool isTrans = false; 813ca95b02SDimitry Andric int BISlot = getSlot(*BI); 828f0fd8f6SDimitry Andric if (LastDstChan >= BISlot) 838f0fd8f6SDimitry Andric isTrans = true; 848f0fd8f6SDimitry Andric LastDstChan = BISlot; 853ca95b02SDimitry Andric if (TII->isPredicated(*BI)) 868f0fd8f6SDimitry Andric continue; 878f0fd8f6SDimitry Andric int OperandIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::write); 888f0fd8f6SDimitry Andric if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0) 898f0fd8f6SDimitry Andric continue; 908f0fd8f6SDimitry Andric int DstIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::dst); 918f0fd8f6SDimitry Andric if (DstIdx == -1) { 928f0fd8f6SDimitry Andric continue; 938f0fd8f6SDimitry Andric } 948f0fd8f6SDimitry Andric unsigned Dst = BI->getOperand(DstIdx).getReg(); 953ca95b02SDimitry Andric if (isTrans || TII->isTransOnly(*BI)) { 968f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PS; 978f0fd8f6SDimitry Andric continue; 988f0fd8f6SDimitry Andric } 998f0fd8f6SDimitry Andric if (BI->getOpcode() == AMDGPU::DOT4_r600 || 1008f0fd8f6SDimitry Andric BI->getOpcode() == AMDGPU::DOT4_eg) { 1018f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PV_X; 1028f0fd8f6SDimitry Andric continue; 1038f0fd8f6SDimitry Andric } 1048f0fd8f6SDimitry Andric if (Dst == AMDGPU::OQAP) { 1058f0fd8f6SDimitry Andric continue; 1068f0fd8f6SDimitry Andric } 1078f0fd8f6SDimitry Andric unsigned PVReg = 0; 1088f0fd8f6SDimitry Andric switch (TRI.getHWRegChan(Dst)) { 1098f0fd8f6SDimitry Andric case 0: 1108f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_X; 1118f0fd8f6SDimitry Andric break; 1128f0fd8f6SDimitry Andric case 1: 1138f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Y; 1148f0fd8f6SDimitry Andric break; 1158f0fd8f6SDimitry Andric case 2: 1168f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Z; 1178f0fd8f6SDimitry Andric break; 1188f0fd8f6SDimitry Andric case 3: 1198f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_W; 1208f0fd8f6SDimitry Andric break; 1218f0fd8f6SDimitry Andric default: 1228f0fd8f6SDimitry Andric llvm_unreachable("Invalid Chan"); 1238f0fd8f6SDimitry Andric } 1248f0fd8f6SDimitry Andric Result[Dst] = PVReg; 1258f0fd8f6SDimitry Andric } while ((++BI)->isBundledWithPred()); 1268f0fd8f6SDimitry Andric return Result; 1278f0fd8f6SDimitry Andric } 1288f0fd8f6SDimitry Andric 1293ca95b02SDimitry Andric void substitutePV(MachineInstr &MI, const DenseMap<unsigned, unsigned> &PVs) 1308f0fd8f6SDimitry Andric const { 1318f0fd8f6SDimitry Andric unsigned Ops[] = { 1328f0fd8f6SDimitry Andric AMDGPU::OpName::src0, 1338f0fd8f6SDimitry Andric AMDGPU::OpName::src1, 1348f0fd8f6SDimitry Andric AMDGPU::OpName::src2 1358f0fd8f6SDimitry Andric }; 1368f0fd8f6SDimitry Andric for (unsigned i = 0; i < 3; i++) { 1373ca95b02SDimitry Andric int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Ops[i]); 1388f0fd8f6SDimitry Andric if (OperandIdx < 0) 1398f0fd8f6SDimitry Andric continue; 1403ca95b02SDimitry Andric unsigned Src = MI.getOperand(OperandIdx).getReg(); 1418f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src); 1428f0fd8f6SDimitry Andric if (It != PVs.end()) 1433ca95b02SDimitry Andric MI.getOperand(OperandIdx).setReg(It->second); 1448f0fd8f6SDimitry Andric } 1458f0fd8f6SDimitry Andric } 1468f0fd8f6SDimitry Andric public: 1478f0fd8f6SDimitry Andric // Ctor. 1483ca95b02SDimitry Andric R600PacketizerList(MachineFunction &MF, const R600Subtarget &ST, 1493ca95b02SDimitry Andric MachineLoopInfo &MLI) 1507d523365SDimitry Andric : VLIWPacketizerList(MF, MLI, nullptr), 1513ca95b02SDimitry Andric TII(ST.getInstrInfo()), 1528f0fd8f6SDimitry Andric TRI(TII->getRegisterInfo()) { 1533ca95b02SDimitry Andric VLIW5 = !ST.hasCaymanISA(); 1548f0fd8f6SDimitry Andric } 1558f0fd8f6SDimitry Andric 1568f0fd8f6SDimitry Andric // initPacketizerState - initialize some internal flags. 1578f0fd8f6SDimitry Andric void initPacketizerState() override { 1588f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 1598f0fd8f6SDimitry Andric } 1608f0fd8f6SDimitry Andric 1618f0fd8f6SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 1623ca95b02SDimitry Andric bool ignorePseudoInstruction(const MachineInstr &MI, 1637d523365SDimitry Andric const MachineBasicBlock *MBB) override { 1648f0fd8f6SDimitry Andric return false; 1658f0fd8f6SDimitry Andric } 1668f0fd8f6SDimitry Andric 1678f0fd8f6SDimitry Andric // isSoloInstruction - return true if instruction MI can not be packetized 1688f0fd8f6SDimitry Andric // with any other instruction, which means that MI itself is a packet. 1693ca95b02SDimitry Andric bool isSoloInstruction(const MachineInstr &MI) override { 1703ca95b02SDimitry Andric if (TII->isVector(MI)) 1718f0fd8f6SDimitry Andric return true; 1723ca95b02SDimitry Andric if (!TII->isALUInstr(MI.getOpcode())) 1738f0fd8f6SDimitry Andric return true; 1743ca95b02SDimitry Andric if (MI.getOpcode() == AMDGPU::GROUP_BARRIER) 1758f0fd8f6SDimitry Andric return true; 1768f0fd8f6SDimitry Andric // XXX: This can be removed once the packetizer properly handles all the 1778f0fd8f6SDimitry Andric // LDS instruction group restrictions. 1783ca95b02SDimitry Andric return TII->isLDSInstr(MI.getOpcode()); 1798f0fd8f6SDimitry Andric } 1808f0fd8f6SDimitry Andric 1818f0fd8f6SDimitry Andric // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ 1828f0fd8f6SDimitry Andric // together. 1838f0fd8f6SDimitry Andric bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override { 1848f0fd8f6SDimitry Andric MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); 1853ca95b02SDimitry Andric if (getSlot(*MII) == getSlot(*MIJ)) 1868f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = true; 1878f0fd8f6SDimitry Andric // Does MII and MIJ share the same pred_sel ? 1888f0fd8f6SDimitry Andric int OpI = TII->getOperandIdx(MII->getOpcode(), AMDGPU::OpName::pred_sel), 1898f0fd8f6SDimitry Andric OpJ = TII->getOperandIdx(MIJ->getOpcode(), AMDGPU::OpName::pred_sel); 1908f0fd8f6SDimitry Andric unsigned PredI = (OpI > -1)?MII->getOperand(OpI).getReg():0, 1918f0fd8f6SDimitry Andric PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg():0; 1928f0fd8f6SDimitry Andric if (PredI != PredJ) 1938f0fd8f6SDimitry Andric return false; 1948f0fd8f6SDimitry Andric if (SUJ->isSucc(SUI)) { 1958f0fd8f6SDimitry Andric for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) { 1968f0fd8f6SDimitry Andric const SDep &Dep = SUJ->Succs[i]; 1978f0fd8f6SDimitry Andric if (Dep.getSUnit() != SUI) 1988f0fd8f6SDimitry Andric continue; 1998f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Anti) 2008f0fd8f6SDimitry Andric continue; 2018f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Output) 2028f0fd8f6SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 2038f0fd8f6SDimitry Andric continue; 2048f0fd8f6SDimitry Andric return false; 2058f0fd8f6SDimitry Andric } 2068f0fd8f6SDimitry Andric } 2078f0fd8f6SDimitry Andric 2083ca95b02SDimitry Andric bool ARDef = 2093ca95b02SDimitry Andric TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ); 2103ca95b02SDimitry Andric bool ARUse = 2113ca95b02SDimitry Andric TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ); 2128f0fd8f6SDimitry Andric 2133ca95b02SDimitry Andric return !ARDef || !ARUse; 2148f0fd8f6SDimitry Andric } 2158f0fd8f6SDimitry Andric 2168f0fd8f6SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependece between SUI 2178f0fd8f6SDimitry Andric // and SUJ. 2188f0fd8f6SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2198f0fd8f6SDimitry Andric return false; 2208f0fd8f6SDimitry Andric } 2218f0fd8f6SDimitry Andric 2228f0fd8f6SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 2238f0fd8f6SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::last); 2248f0fd8f6SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 2258f0fd8f6SDimitry Andric } 2268f0fd8f6SDimitry Andric 2273ca95b02SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr &MI, 2288f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 2298f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 2308f0fd8f6SDimitry Andric bool &isTransSlot) { 2318f0fd8f6SDimitry Andric isTransSlot = TII->isTransOnly(MI); 2328f0fd8f6SDimitry Andric assert (!isTransSlot || VLIW5); 2338f0fd8f6SDimitry Andric 2348f0fd8f6SDimitry Andric // Is the dst reg sequence legal ? 2358f0fd8f6SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 2363ca95b02SDimitry Andric if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) { 2378f0fd8f6SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 2388f0fd8f6SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 2398f0fd8f6SDimitry Andric isTransSlot = true; 2403ca95b02SDimitry Andric DEBUG({ 2413ca95b02SDimitry Andric dbgs() << "Considering as Trans Inst :"; 2423ca95b02SDimitry Andric MI.dump(); 2433ca95b02SDimitry Andric }); 2448f0fd8f6SDimitry Andric } 2458f0fd8f6SDimitry Andric else 2468f0fd8f6SDimitry Andric return false; 2478f0fd8f6SDimitry Andric } 2488f0fd8f6SDimitry Andric } 2498f0fd8f6SDimitry Andric 2508f0fd8f6SDimitry Andric // Are the Constants limitations met ? 2513ca95b02SDimitry Andric CurrentPacketMIs.push_back(&MI); 2528f0fd8f6SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 2533ca95b02SDimitry Andric DEBUG({ 2548f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2553ca95b02SDimitry Andric MI.dump(); 2568f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2578f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2588f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2598f0fd8f6SDimitry Andric dbgs() << "\n"; 2608f0fd8f6SDimitry Andric } 2618f0fd8f6SDimitry Andric dbgs() << "because of Consts read limitations\n"; 2623ca95b02SDimitry Andric }); 2638f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2648f0fd8f6SDimitry Andric return false; 2658f0fd8f6SDimitry Andric } 2668f0fd8f6SDimitry Andric 2678f0fd8f6SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 2688f0fd8f6SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 2698f0fd8f6SDimitry Andric PV, BS, isTransSlot)) { 2703ca95b02SDimitry Andric DEBUG({ 2718f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2723ca95b02SDimitry Andric MI.dump(); 2738f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2748f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2758f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2768f0fd8f6SDimitry Andric dbgs() << "\n"; 2778f0fd8f6SDimitry Andric } 2788f0fd8f6SDimitry Andric dbgs() << "because of Read port limitations\n"; 2793ca95b02SDimitry Andric }); 2808f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2818f0fd8f6SDimitry Andric return false; 2828f0fd8f6SDimitry Andric } 2838f0fd8f6SDimitry Andric 284d88c1a5aSDimitry Andric // We cannot read LDS source registers from the Trans slot. 2858f0fd8f6SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 2868f0fd8f6SDimitry Andric return false; 2878f0fd8f6SDimitry Andric 2888f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2898f0fd8f6SDimitry Andric return true; 2908f0fd8f6SDimitry Andric } 2918f0fd8f6SDimitry Andric 2923ca95b02SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override { 2938f0fd8f6SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 2943ca95b02SDimitry Andric CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front(); 2958f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 2968f0fd8f6SDimitry Andric getPreviousVector(FirstInBundle); 2978f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 2988f0fd8f6SDimitry Andric bool isTransSlot; 2998f0fd8f6SDimitry Andric 3008f0fd8f6SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 3018f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 3028f0fd8f6SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 3038f0fd8f6SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 3048f0fd8f6SDimitry Andric AMDGPU::OpName::bank_swizzle); 3058f0fd8f6SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 3068f0fd8f6SDimitry Andric } 3073ca95b02SDimitry Andric unsigned Op = 3083ca95b02SDimitry Andric TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::bank_swizzle); 3093ca95b02SDimitry Andric MI.getOperand(Op).setImm(BS.back()); 3108f0fd8f6SDimitry Andric if (!CurrentPacketMIs.empty()) 3118f0fd8f6SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 3128f0fd8f6SDimitry Andric substitutePV(MI, PV); 3138f0fd8f6SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 3148f0fd8f6SDimitry Andric if (isTransSlot) { 3158f0fd8f6SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 3168f0fd8f6SDimitry Andric } 3178f0fd8f6SDimitry Andric return It; 3188f0fd8f6SDimitry Andric } 3193ca95b02SDimitry Andric endPacket(MI.getParent(), MI); 3208f0fd8f6SDimitry Andric if (TII->isTransOnly(MI)) 3218f0fd8f6SDimitry Andric return MI; 3228f0fd8f6SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 3238f0fd8f6SDimitry Andric } 3248f0fd8f6SDimitry Andric }; 3258f0fd8f6SDimitry Andric 3268f0fd8f6SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 3273ca95b02SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 3283ca95b02SDimitry Andric const R600InstrInfo *TII = ST.getInstrInfo(); 3293ca95b02SDimitry Andric 3308f0fd8f6SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 3318f0fd8f6SDimitry Andric 3328f0fd8f6SDimitry Andric // Instantiate the packetizer. 3333ca95b02SDimitry Andric R600PacketizerList Packetizer(Fn, ST, MLI); 3348f0fd8f6SDimitry Andric 3358f0fd8f6SDimitry Andric // DFA state table should not be empty. 3368f0fd8f6SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 3378f0fd8f6SDimitry Andric 3383ca95b02SDimitry Andric if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty()) 3393ca95b02SDimitry Andric return false; 3403ca95b02SDimitry Andric 3418f0fd8f6SDimitry Andric // 3428f0fd8f6SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 3438f0fd8f6SDimitry Andric // These instructions confuse the dependence analysis. Consider: 3448f0fd8f6SDimitry Andric // D0 = ... (Insn 0) 3458f0fd8f6SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 3468f0fd8f6SDimitry Andric // R0 = ... (Insn 2) 3478f0fd8f6SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 3488f0fd8f6SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 3498f0fd8f6SDimitry Andric // packetization 3508f0fd8f6SDimitry Andric // 3518f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3528f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3538f0fd8f6SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 3548f0fd8f6SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 3558f0fd8f6SDimitry Andric while (MI != End) { 3568f0fd8f6SDimitry Andric if (MI->isKill() || MI->getOpcode() == AMDGPU::IMPLICIT_DEF || 3578f0fd8f6SDimitry Andric (MI->getOpcode() == AMDGPU::CF_ALU && !MI->getOperand(8).getImm())) { 3588f0fd8f6SDimitry Andric MachineBasicBlock::iterator DeleteMI = MI; 3598f0fd8f6SDimitry Andric ++MI; 3608f0fd8f6SDimitry Andric MBB->erase(DeleteMI); 3618f0fd8f6SDimitry Andric End = MBB->end(); 3628f0fd8f6SDimitry Andric continue; 3638f0fd8f6SDimitry Andric } 3648f0fd8f6SDimitry Andric ++MI; 3658f0fd8f6SDimitry Andric } 3668f0fd8f6SDimitry Andric } 3678f0fd8f6SDimitry Andric 3688f0fd8f6SDimitry Andric // Loop over all of the basic blocks. 3698f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3708f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3718f0fd8f6SDimitry Andric // Find scheduling regions and schedule / packetize each region. 3728f0fd8f6SDimitry Andric unsigned RemainingCount = MBB->size(); 3738f0fd8f6SDimitry Andric for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 3748f0fd8f6SDimitry Andric RegionEnd != MBB->begin();) { 3758f0fd8f6SDimitry Andric // The next region starts above the previous region. Look backward in the 3768f0fd8f6SDimitry Andric // instruction stream until we find the nearest boundary. 3778f0fd8f6SDimitry Andric MachineBasicBlock::iterator I = RegionEnd; 3788f0fd8f6SDimitry Andric for(;I != MBB->begin(); --I, --RemainingCount) { 3793ca95b02SDimitry Andric if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn)) 3808f0fd8f6SDimitry Andric break; 3818f0fd8f6SDimitry Andric } 3828f0fd8f6SDimitry Andric I = MBB->begin(); 3838f0fd8f6SDimitry Andric 3848f0fd8f6SDimitry Andric // Skip empty scheduling regions. 3858f0fd8f6SDimitry Andric if (I == RegionEnd) { 3868f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3878f0fd8f6SDimitry Andric --RemainingCount; 3888f0fd8f6SDimitry Andric continue; 3898f0fd8f6SDimitry Andric } 3908f0fd8f6SDimitry Andric // Skip regions with one instruction. 3918f0fd8f6SDimitry Andric if (I == std::prev(RegionEnd)) { 3928f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3938f0fd8f6SDimitry Andric continue; 3948f0fd8f6SDimitry Andric } 3958f0fd8f6SDimitry Andric 3967d523365SDimitry Andric Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd); 3978f0fd8f6SDimitry Andric RegionEnd = I; 3988f0fd8f6SDimitry Andric } 3998f0fd8f6SDimitry Andric } 4008f0fd8f6SDimitry Andric 4018f0fd8f6SDimitry Andric return true; 4028f0fd8f6SDimitry Andric 4038f0fd8f6SDimitry Andric } 4048f0fd8f6SDimitry Andric 4058f0fd8f6SDimitry Andric } // end anonymous namespace 4068f0fd8f6SDimitry Andric 407d8866befSDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() { 408d8866befSDimitry Andric return new R600Packetizer(); 4098f0fd8f6SDimitry Andric } 410