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 558f0fd8f6SDimitry Andric class R600PacketizerList : public VLIWPacketizerList { 568f0fd8f6SDimitry Andric private: 578f0fd8f6SDimitry Andric const R600InstrInfo *TII; 588f0fd8f6SDimitry Andric const R600RegisterInfo &TRI; 598f0fd8f6SDimitry Andric bool VLIW5; 608f0fd8f6SDimitry Andric bool ConsideredInstUsesAlreadyWrittenVectorElement; 618f0fd8f6SDimitry Andric 623ca95b02SDimitry Andric unsigned getSlot(const MachineInstr &MI) const { 633ca95b02SDimitry Andric return TRI.getHWRegChan(MI.getOperand(0).getReg()); 648f0fd8f6SDimitry Andric } 658f0fd8f6SDimitry Andric 668f0fd8f6SDimitry Andric /// \returns register to PV chan mapping for bundle/single instructions that 678f0fd8f6SDimitry Andric /// immediately precedes I. 688f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I) 698f0fd8f6SDimitry Andric const { 708f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> Result; 718f0fd8f6SDimitry Andric I--; 728f0fd8f6SDimitry Andric if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle()) 738f0fd8f6SDimitry Andric return Result; 748f0fd8f6SDimitry Andric MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); 758f0fd8f6SDimitry Andric if (I->isBundle()) 768f0fd8f6SDimitry Andric BI++; 778f0fd8f6SDimitry Andric int LastDstChan = -1; 788f0fd8f6SDimitry Andric do { 798f0fd8f6SDimitry Andric bool isTrans = false; 803ca95b02SDimitry Andric int BISlot = getSlot(*BI); 818f0fd8f6SDimitry Andric if (LastDstChan >= BISlot) 828f0fd8f6SDimitry Andric isTrans = true; 838f0fd8f6SDimitry Andric LastDstChan = BISlot; 843ca95b02SDimitry Andric if (TII->isPredicated(*BI)) 858f0fd8f6SDimitry Andric continue; 868f0fd8f6SDimitry Andric int OperandIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::write); 878f0fd8f6SDimitry Andric if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0) 888f0fd8f6SDimitry Andric continue; 898f0fd8f6SDimitry Andric int DstIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::dst); 908f0fd8f6SDimitry Andric if (DstIdx == -1) { 918f0fd8f6SDimitry Andric continue; 928f0fd8f6SDimitry Andric } 938f0fd8f6SDimitry Andric unsigned Dst = BI->getOperand(DstIdx).getReg(); 943ca95b02SDimitry Andric if (isTrans || TII->isTransOnly(*BI)) { 958f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PS; 968f0fd8f6SDimitry Andric continue; 978f0fd8f6SDimitry Andric } 988f0fd8f6SDimitry Andric if (BI->getOpcode() == AMDGPU::DOT4_r600 || 998f0fd8f6SDimitry Andric BI->getOpcode() == AMDGPU::DOT4_eg) { 1008f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PV_X; 1018f0fd8f6SDimitry Andric continue; 1028f0fd8f6SDimitry Andric } 1038f0fd8f6SDimitry Andric if (Dst == AMDGPU::OQAP) { 1048f0fd8f6SDimitry Andric continue; 1058f0fd8f6SDimitry Andric } 1068f0fd8f6SDimitry Andric unsigned PVReg = 0; 1078f0fd8f6SDimitry Andric switch (TRI.getHWRegChan(Dst)) { 1088f0fd8f6SDimitry Andric case 0: 1098f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_X; 1108f0fd8f6SDimitry Andric break; 1118f0fd8f6SDimitry Andric case 1: 1128f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Y; 1138f0fd8f6SDimitry Andric break; 1148f0fd8f6SDimitry Andric case 2: 1158f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Z; 1168f0fd8f6SDimitry Andric break; 1178f0fd8f6SDimitry Andric case 3: 1188f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_W; 1198f0fd8f6SDimitry Andric break; 1208f0fd8f6SDimitry Andric default: 1218f0fd8f6SDimitry Andric llvm_unreachable("Invalid Chan"); 1228f0fd8f6SDimitry Andric } 1238f0fd8f6SDimitry Andric Result[Dst] = PVReg; 1248f0fd8f6SDimitry Andric } while ((++BI)->isBundledWithPred()); 1258f0fd8f6SDimitry Andric return Result; 1268f0fd8f6SDimitry Andric } 1278f0fd8f6SDimitry Andric 1283ca95b02SDimitry Andric void substitutePV(MachineInstr &MI, const DenseMap<unsigned, unsigned> &PVs) 1298f0fd8f6SDimitry Andric const { 1308f0fd8f6SDimitry Andric unsigned Ops[] = { 1318f0fd8f6SDimitry Andric AMDGPU::OpName::src0, 1328f0fd8f6SDimitry Andric AMDGPU::OpName::src1, 1338f0fd8f6SDimitry Andric AMDGPU::OpName::src2 1348f0fd8f6SDimitry Andric }; 1358f0fd8f6SDimitry Andric for (unsigned i = 0; i < 3; i++) { 1363ca95b02SDimitry Andric int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Ops[i]); 1378f0fd8f6SDimitry Andric if (OperandIdx < 0) 1388f0fd8f6SDimitry Andric continue; 1393ca95b02SDimitry Andric unsigned Src = MI.getOperand(OperandIdx).getReg(); 1408f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src); 1418f0fd8f6SDimitry Andric if (It != PVs.end()) 1423ca95b02SDimitry Andric MI.getOperand(OperandIdx).setReg(It->second); 1438f0fd8f6SDimitry Andric } 1448f0fd8f6SDimitry Andric } 1458f0fd8f6SDimitry Andric public: 1468f0fd8f6SDimitry Andric // Ctor. 1473ca95b02SDimitry Andric R600PacketizerList(MachineFunction &MF, const R600Subtarget &ST, 1483ca95b02SDimitry Andric MachineLoopInfo &MLI) 1497d523365SDimitry Andric : VLIWPacketizerList(MF, MLI, nullptr), 1503ca95b02SDimitry Andric TII(ST.getInstrInfo()), 1518f0fd8f6SDimitry Andric TRI(TII->getRegisterInfo()) { 1523ca95b02SDimitry Andric VLIW5 = !ST.hasCaymanISA(); 1538f0fd8f6SDimitry Andric } 1548f0fd8f6SDimitry Andric 1558f0fd8f6SDimitry Andric // initPacketizerState - initialize some internal flags. 1568f0fd8f6SDimitry Andric void initPacketizerState() override { 1578f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 1588f0fd8f6SDimitry Andric } 1598f0fd8f6SDimitry Andric 1608f0fd8f6SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 1613ca95b02SDimitry Andric bool ignorePseudoInstruction(const MachineInstr &MI, 1627d523365SDimitry Andric const MachineBasicBlock *MBB) override { 1638f0fd8f6SDimitry Andric return false; 1648f0fd8f6SDimitry Andric } 1658f0fd8f6SDimitry Andric 1668f0fd8f6SDimitry Andric // isSoloInstruction - return true if instruction MI can not be packetized 1678f0fd8f6SDimitry Andric // with any other instruction, which means that MI itself is a packet. 1683ca95b02SDimitry Andric bool isSoloInstruction(const MachineInstr &MI) override { 1693ca95b02SDimitry Andric if (TII->isVector(MI)) 1708f0fd8f6SDimitry Andric return true; 1713ca95b02SDimitry Andric if (!TII->isALUInstr(MI.getOpcode())) 1728f0fd8f6SDimitry Andric return true; 1733ca95b02SDimitry Andric if (MI.getOpcode() == AMDGPU::GROUP_BARRIER) 1748f0fd8f6SDimitry Andric return true; 1758f0fd8f6SDimitry Andric // XXX: This can be removed once the packetizer properly handles all the 1768f0fd8f6SDimitry Andric // LDS instruction group restrictions. 1773ca95b02SDimitry Andric return TII->isLDSInstr(MI.getOpcode()); 1788f0fd8f6SDimitry Andric } 1798f0fd8f6SDimitry Andric 1808f0fd8f6SDimitry Andric // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ 1818f0fd8f6SDimitry Andric // together. 1828f0fd8f6SDimitry Andric bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override { 1838f0fd8f6SDimitry Andric MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); 1843ca95b02SDimitry Andric if (getSlot(*MII) == getSlot(*MIJ)) 1858f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = true; 1868f0fd8f6SDimitry Andric // Does MII and MIJ share the same pred_sel ? 1878f0fd8f6SDimitry Andric int OpI = TII->getOperandIdx(MII->getOpcode(), AMDGPU::OpName::pred_sel), 1888f0fd8f6SDimitry Andric OpJ = TII->getOperandIdx(MIJ->getOpcode(), AMDGPU::OpName::pred_sel); 1898f0fd8f6SDimitry Andric unsigned PredI = (OpI > -1)?MII->getOperand(OpI).getReg():0, 1908f0fd8f6SDimitry Andric PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg():0; 1918f0fd8f6SDimitry Andric if (PredI != PredJ) 1928f0fd8f6SDimitry Andric return false; 1938f0fd8f6SDimitry Andric if (SUJ->isSucc(SUI)) { 1948f0fd8f6SDimitry Andric for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) { 1958f0fd8f6SDimitry Andric const SDep &Dep = SUJ->Succs[i]; 1968f0fd8f6SDimitry Andric if (Dep.getSUnit() != SUI) 1978f0fd8f6SDimitry Andric continue; 1988f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Anti) 1998f0fd8f6SDimitry Andric continue; 2008f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Output) 2018f0fd8f6SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 2028f0fd8f6SDimitry Andric continue; 2038f0fd8f6SDimitry Andric return false; 2048f0fd8f6SDimitry Andric } 2058f0fd8f6SDimitry Andric } 2068f0fd8f6SDimitry Andric 2073ca95b02SDimitry Andric bool ARDef = 2083ca95b02SDimitry Andric TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ); 2093ca95b02SDimitry Andric bool ARUse = 2103ca95b02SDimitry Andric TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ); 2118f0fd8f6SDimitry Andric 2123ca95b02SDimitry Andric return !ARDef || !ARUse; 2138f0fd8f6SDimitry Andric } 2148f0fd8f6SDimitry Andric 2158f0fd8f6SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependece between SUI 2168f0fd8f6SDimitry Andric // and SUJ. 2178f0fd8f6SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2188f0fd8f6SDimitry Andric return false; 2198f0fd8f6SDimitry Andric } 2208f0fd8f6SDimitry Andric 2218f0fd8f6SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 2228f0fd8f6SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::last); 2238f0fd8f6SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 2248f0fd8f6SDimitry Andric } 2258f0fd8f6SDimitry Andric 2263ca95b02SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr &MI, 2278f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 2288f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 2298f0fd8f6SDimitry Andric bool &isTransSlot) { 2308f0fd8f6SDimitry Andric isTransSlot = TII->isTransOnly(MI); 2318f0fd8f6SDimitry Andric assert (!isTransSlot || VLIW5); 2328f0fd8f6SDimitry Andric 2338f0fd8f6SDimitry Andric // Is the dst reg sequence legal ? 2348f0fd8f6SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 2353ca95b02SDimitry Andric if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) { 2368f0fd8f6SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 2378f0fd8f6SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 2388f0fd8f6SDimitry Andric isTransSlot = true; 2393ca95b02SDimitry Andric DEBUG({ 2403ca95b02SDimitry Andric dbgs() << "Considering as Trans Inst :"; 2413ca95b02SDimitry Andric MI.dump(); 2423ca95b02SDimitry Andric }); 2438f0fd8f6SDimitry Andric } 2448f0fd8f6SDimitry Andric else 2458f0fd8f6SDimitry Andric return false; 2468f0fd8f6SDimitry Andric } 2478f0fd8f6SDimitry Andric } 2488f0fd8f6SDimitry Andric 2498f0fd8f6SDimitry Andric // Are the Constants limitations met ? 2503ca95b02SDimitry Andric CurrentPacketMIs.push_back(&MI); 2518f0fd8f6SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 2523ca95b02SDimitry Andric DEBUG({ 2538f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2543ca95b02SDimitry Andric MI.dump(); 2558f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2568f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2578f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2588f0fd8f6SDimitry Andric dbgs() << "\n"; 2598f0fd8f6SDimitry Andric } 2608f0fd8f6SDimitry Andric dbgs() << "because of Consts read limitations\n"; 2613ca95b02SDimitry Andric }); 2628f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2638f0fd8f6SDimitry Andric return false; 2648f0fd8f6SDimitry Andric } 2658f0fd8f6SDimitry Andric 2668f0fd8f6SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 2678f0fd8f6SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 2688f0fd8f6SDimitry Andric PV, BS, isTransSlot)) { 2693ca95b02SDimitry Andric DEBUG({ 2708f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2713ca95b02SDimitry Andric MI.dump(); 2728f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2738f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2748f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2758f0fd8f6SDimitry Andric dbgs() << "\n"; 2768f0fd8f6SDimitry Andric } 2778f0fd8f6SDimitry Andric dbgs() << "because of Read port limitations\n"; 2783ca95b02SDimitry Andric }); 2798f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2808f0fd8f6SDimitry Andric return false; 2818f0fd8f6SDimitry Andric } 2828f0fd8f6SDimitry Andric 283d88c1a5aSDimitry Andric // We cannot read LDS source registers from the Trans slot. 2848f0fd8f6SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 2858f0fd8f6SDimitry Andric return false; 2868f0fd8f6SDimitry Andric 2878f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2888f0fd8f6SDimitry Andric return true; 2898f0fd8f6SDimitry Andric } 2908f0fd8f6SDimitry Andric 2913ca95b02SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override { 2928f0fd8f6SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 2933ca95b02SDimitry Andric CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front(); 2948f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 2958f0fd8f6SDimitry Andric getPreviousVector(FirstInBundle); 2968f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 2978f0fd8f6SDimitry Andric bool isTransSlot; 2988f0fd8f6SDimitry Andric 2998f0fd8f6SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 3008f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 3018f0fd8f6SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 3028f0fd8f6SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 3038f0fd8f6SDimitry Andric AMDGPU::OpName::bank_swizzle); 3048f0fd8f6SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 3058f0fd8f6SDimitry Andric } 3063ca95b02SDimitry Andric unsigned Op = 3073ca95b02SDimitry Andric TII->getOperandIdx(MI.getOpcode(), AMDGPU::OpName::bank_swizzle); 3083ca95b02SDimitry Andric MI.getOperand(Op).setImm(BS.back()); 3098f0fd8f6SDimitry Andric if (!CurrentPacketMIs.empty()) 3108f0fd8f6SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 3118f0fd8f6SDimitry Andric substitutePV(MI, PV); 3128f0fd8f6SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 3138f0fd8f6SDimitry Andric if (isTransSlot) { 3148f0fd8f6SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 3158f0fd8f6SDimitry Andric } 3168f0fd8f6SDimitry Andric return It; 3178f0fd8f6SDimitry Andric } 3183ca95b02SDimitry Andric endPacket(MI.getParent(), MI); 3198f0fd8f6SDimitry Andric if (TII->isTransOnly(MI)) 3208f0fd8f6SDimitry Andric return MI; 3218f0fd8f6SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 3228f0fd8f6SDimitry Andric } 3238f0fd8f6SDimitry Andric }; 3248f0fd8f6SDimitry Andric 3258f0fd8f6SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 3263ca95b02SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 3273ca95b02SDimitry Andric const R600InstrInfo *TII = ST.getInstrInfo(); 3283ca95b02SDimitry Andric 3298f0fd8f6SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 3308f0fd8f6SDimitry Andric 3318f0fd8f6SDimitry Andric // Instantiate the packetizer. 3323ca95b02SDimitry Andric R600PacketizerList Packetizer(Fn, ST, MLI); 3338f0fd8f6SDimitry Andric 3348f0fd8f6SDimitry Andric // DFA state table should not be empty. 3358f0fd8f6SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 3368f0fd8f6SDimitry Andric 3373ca95b02SDimitry Andric if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty()) 3383ca95b02SDimitry Andric return false; 3393ca95b02SDimitry Andric 3408f0fd8f6SDimitry Andric // 3418f0fd8f6SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 3428f0fd8f6SDimitry Andric // These instructions confuse the dependence analysis. Consider: 3438f0fd8f6SDimitry Andric // D0 = ... (Insn 0) 3448f0fd8f6SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 3458f0fd8f6SDimitry Andric // R0 = ... (Insn 2) 3468f0fd8f6SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 3478f0fd8f6SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 3488f0fd8f6SDimitry Andric // packetization 3498f0fd8f6SDimitry Andric // 3508f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3518f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3528f0fd8f6SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 3538f0fd8f6SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 3548f0fd8f6SDimitry Andric while (MI != End) { 3558f0fd8f6SDimitry Andric if (MI->isKill() || MI->getOpcode() == AMDGPU::IMPLICIT_DEF || 3568f0fd8f6SDimitry Andric (MI->getOpcode() == AMDGPU::CF_ALU && !MI->getOperand(8).getImm())) { 3578f0fd8f6SDimitry Andric MachineBasicBlock::iterator DeleteMI = MI; 3588f0fd8f6SDimitry Andric ++MI; 3598f0fd8f6SDimitry Andric MBB->erase(DeleteMI); 3608f0fd8f6SDimitry Andric End = MBB->end(); 3618f0fd8f6SDimitry Andric continue; 3628f0fd8f6SDimitry Andric } 3638f0fd8f6SDimitry Andric ++MI; 3648f0fd8f6SDimitry Andric } 3658f0fd8f6SDimitry Andric } 3668f0fd8f6SDimitry Andric 3678f0fd8f6SDimitry Andric // Loop over all of the basic blocks. 3688f0fd8f6SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 3698f0fd8f6SDimitry Andric MBB != MBBe; ++MBB) { 3708f0fd8f6SDimitry Andric // Find scheduling regions and schedule / packetize each region. 3718f0fd8f6SDimitry Andric unsigned RemainingCount = MBB->size(); 3728f0fd8f6SDimitry Andric for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 3738f0fd8f6SDimitry Andric RegionEnd != MBB->begin();) { 3748f0fd8f6SDimitry Andric // The next region starts above the previous region. Look backward in the 3758f0fd8f6SDimitry Andric // instruction stream until we find the nearest boundary. 3768f0fd8f6SDimitry Andric MachineBasicBlock::iterator I = RegionEnd; 3778f0fd8f6SDimitry Andric for(;I != MBB->begin(); --I, --RemainingCount) { 3783ca95b02SDimitry Andric if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn)) 3798f0fd8f6SDimitry Andric break; 3808f0fd8f6SDimitry Andric } 3818f0fd8f6SDimitry Andric I = MBB->begin(); 3828f0fd8f6SDimitry Andric 3838f0fd8f6SDimitry Andric // Skip empty scheduling regions. 3848f0fd8f6SDimitry Andric if (I == RegionEnd) { 3858f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3868f0fd8f6SDimitry Andric --RemainingCount; 3878f0fd8f6SDimitry Andric continue; 3888f0fd8f6SDimitry Andric } 3898f0fd8f6SDimitry Andric // Skip regions with one instruction. 3908f0fd8f6SDimitry Andric if (I == std::prev(RegionEnd)) { 3918f0fd8f6SDimitry Andric RegionEnd = std::prev(RegionEnd); 3928f0fd8f6SDimitry Andric continue; 3938f0fd8f6SDimitry Andric } 3948f0fd8f6SDimitry Andric 3957d523365SDimitry Andric Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd); 3968f0fd8f6SDimitry Andric RegionEnd = I; 3978f0fd8f6SDimitry Andric } 3988f0fd8f6SDimitry Andric } 3998f0fd8f6SDimitry Andric 4008f0fd8f6SDimitry Andric return true; 4018f0fd8f6SDimitry Andric 4028f0fd8f6SDimitry Andric } 4038f0fd8f6SDimitry Andric 4048f0fd8f6SDimitry Andric } // end anonymous namespace 4058f0fd8f6SDimitry Andric 4062cab237bSDimitry Andric INITIALIZE_PASS_BEGIN(R600Packetizer, DEBUG_TYPE, 4072cab237bSDimitry Andric "R600 Packetizer", false, false) 4082cab237bSDimitry Andric INITIALIZE_PASS_END(R600Packetizer, DEBUG_TYPE, 4092cab237bSDimitry Andric "R600 Packetizer", false, false) 4102cab237bSDimitry Andric 4112cab237bSDimitry Andric char R600Packetizer::ID = 0; 4122cab237bSDimitry Andric 4132cab237bSDimitry Andric char &llvm::R600PacketizerID = R600Packetizer::ID; 4142cab237bSDimitry Andric 415d8866befSDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() { 416d8866befSDimitry Andric return new R600Packetizer(); 4178f0fd8f6SDimitry Andric } 418