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 608f0fd8f6SDimitry Andric private: 618f0fd8f6SDimitry Andric const R600InstrInfo *TII; 628f0fd8f6SDimitry Andric const R600RegisterInfo &TRI; 638f0fd8f6SDimitry Andric bool VLIW5; 648f0fd8f6SDimitry Andric bool ConsideredInstUsesAlreadyWrittenVectorElement; 658f0fd8f6SDimitry Andric 668f0fd8f6SDimitry Andric unsigned getSlot(const MachineInstr *MI) const { 678f0fd8f6SDimitry Andric return TRI.getHWRegChan(MI->getOperand(0).getReg()); 688f0fd8f6SDimitry Andric } 698f0fd8f6SDimitry Andric 708f0fd8f6SDimitry Andric /// \returns register to PV chan mapping for bundle/single instructions that 718f0fd8f6SDimitry Andric /// immediately precedes I. 728f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I) 738f0fd8f6SDimitry Andric const { 748f0fd8f6SDimitry Andric DenseMap<unsigned, unsigned> Result; 758f0fd8f6SDimitry Andric I--; 768f0fd8f6SDimitry Andric if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle()) 778f0fd8f6SDimitry Andric return Result; 788f0fd8f6SDimitry Andric MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); 798f0fd8f6SDimitry Andric if (I->isBundle()) 808f0fd8f6SDimitry Andric BI++; 818f0fd8f6SDimitry Andric int LastDstChan = -1; 828f0fd8f6SDimitry Andric do { 838f0fd8f6SDimitry Andric bool isTrans = false; 848f0fd8f6SDimitry Andric int BISlot = getSlot(BI); 858f0fd8f6SDimitry Andric if (LastDstChan >= BISlot) 868f0fd8f6SDimitry Andric isTrans = true; 878f0fd8f6SDimitry Andric LastDstChan = BISlot; 888f0fd8f6SDimitry Andric if (TII->isPredicated(BI)) 898f0fd8f6SDimitry Andric continue; 908f0fd8f6SDimitry Andric int OperandIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::write); 918f0fd8f6SDimitry Andric if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0) 928f0fd8f6SDimitry Andric continue; 938f0fd8f6SDimitry Andric int DstIdx = TII->getOperandIdx(BI->getOpcode(), AMDGPU::OpName::dst); 948f0fd8f6SDimitry Andric if (DstIdx == -1) { 958f0fd8f6SDimitry Andric continue; 968f0fd8f6SDimitry Andric } 978f0fd8f6SDimitry Andric unsigned Dst = BI->getOperand(DstIdx).getReg(); 988f0fd8f6SDimitry Andric if (isTrans || TII->isTransOnly(BI)) { 998f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PS; 1008f0fd8f6SDimitry Andric continue; 1018f0fd8f6SDimitry Andric } 1028f0fd8f6SDimitry Andric if (BI->getOpcode() == AMDGPU::DOT4_r600 || 1038f0fd8f6SDimitry Andric BI->getOpcode() == AMDGPU::DOT4_eg) { 1048f0fd8f6SDimitry Andric Result[Dst] = AMDGPU::PV_X; 1058f0fd8f6SDimitry Andric continue; 1068f0fd8f6SDimitry Andric } 1078f0fd8f6SDimitry Andric if (Dst == AMDGPU::OQAP) { 1088f0fd8f6SDimitry Andric continue; 1098f0fd8f6SDimitry Andric } 1108f0fd8f6SDimitry Andric unsigned PVReg = 0; 1118f0fd8f6SDimitry Andric switch (TRI.getHWRegChan(Dst)) { 1128f0fd8f6SDimitry Andric case 0: 1138f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_X; 1148f0fd8f6SDimitry Andric break; 1158f0fd8f6SDimitry Andric case 1: 1168f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Y; 1178f0fd8f6SDimitry Andric break; 1188f0fd8f6SDimitry Andric case 2: 1198f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_Z; 1208f0fd8f6SDimitry Andric break; 1218f0fd8f6SDimitry Andric case 3: 1228f0fd8f6SDimitry Andric PVReg = AMDGPU::PV_W; 1238f0fd8f6SDimitry Andric break; 1248f0fd8f6SDimitry Andric default: 1258f0fd8f6SDimitry Andric llvm_unreachable("Invalid Chan"); 1268f0fd8f6SDimitry Andric } 1278f0fd8f6SDimitry Andric Result[Dst] = PVReg; 1288f0fd8f6SDimitry Andric } while ((++BI)->isBundledWithPred()); 1298f0fd8f6SDimitry Andric return Result; 1308f0fd8f6SDimitry Andric } 1318f0fd8f6SDimitry Andric 1328f0fd8f6SDimitry Andric void substitutePV(MachineInstr *MI, const DenseMap<unsigned, unsigned> &PVs) 1338f0fd8f6SDimitry Andric const { 1348f0fd8f6SDimitry Andric unsigned Ops[] = { 1358f0fd8f6SDimitry Andric AMDGPU::OpName::src0, 1368f0fd8f6SDimitry Andric AMDGPU::OpName::src1, 1378f0fd8f6SDimitry Andric AMDGPU::OpName::src2 1388f0fd8f6SDimitry Andric }; 1398f0fd8f6SDimitry Andric for (unsigned i = 0; i < 3; i++) { 1408f0fd8f6SDimitry Andric int OperandIdx = TII->getOperandIdx(MI->getOpcode(), Ops[i]); 1418f0fd8f6SDimitry Andric if (OperandIdx < 0) 1428f0fd8f6SDimitry Andric continue; 1438f0fd8f6SDimitry Andric unsigned Src = MI->getOperand(OperandIdx).getReg(); 1448f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src); 1458f0fd8f6SDimitry Andric if (It != PVs.end()) 1468f0fd8f6SDimitry Andric MI->getOperand(OperandIdx).setReg(It->second); 1478f0fd8f6SDimitry Andric } 1488f0fd8f6SDimitry Andric } 1498f0fd8f6SDimitry Andric public: 1508f0fd8f6SDimitry Andric // Ctor. 1518f0fd8f6SDimitry Andric R600PacketizerList(MachineFunction &MF, MachineLoopInfo &MLI) 1528f0fd8f6SDimitry Andric : VLIWPacketizerList(MF, MLI, true), 1538f0fd8f6SDimitry Andric TII(static_cast<const R600InstrInfo *>( 1548f0fd8f6SDimitry Andric MF.getSubtarget().getInstrInfo())), 1558f0fd8f6SDimitry Andric TRI(TII->getRegisterInfo()) { 1568f0fd8f6SDimitry Andric VLIW5 = !MF.getSubtarget<AMDGPUSubtarget>().hasCaymanISA(); 1578f0fd8f6SDimitry Andric } 1588f0fd8f6SDimitry Andric 1598f0fd8f6SDimitry Andric // initPacketizerState - initialize some internal flags. 1608f0fd8f6SDimitry Andric void initPacketizerState() override { 1618f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 1628f0fd8f6SDimitry Andric } 1638f0fd8f6SDimitry Andric 1648f0fd8f6SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 1658f0fd8f6SDimitry Andric bool ignorePseudoInstruction(MachineInstr *MI, 1668f0fd8f6SDimitry Andric MachineBasicBlock *MBB) override { 1678f0fd8f6SDimitry Andric return false; 1688f0fd8f6SDimitry Andric } 1698f0fd8f6SDimitry Andric 1708f0fd8f6SDimitry Andric // isSoloInstruction - return true if instruction MI can not be packetized 1718f0fd8f6SDimitry Andric // with any other instruction, which means that MI itself is a packet. 1728f0fd8f6SDimitry Andric bool isSoloInstruction(MachineInstr *MI) override { 1738f0fd8f6SDimitry Andric if (TII->isVector(*MI)) 1748f0fd8f6SDimitry Andric return true; 1758f0fd8f6SDimitry Andric if (!TII->isALUInstr(MI->getOpcode())) 1768f0fd8f6SDimitry Andric return true; 1778f0fd8f6SDimitry Andric if (MI->getOpcode() == AMDGPU::GROUP_BARRIER) 1788f0fd8f6SDimitry Andric return true; 1798f0fd8f6SDimitry Andric // XXX: This can be removed once the packetizer properly handles all the 1808f0fd8f6SDimitry Andric // LDS instruction group restrictions. 1818f0fd8f6SDimitry Andric if (TII->isLDSInstr(MI->getOpcode())) 1828f0fd8f6SDimitry Andric return true; 1838f0fd8f6SDimitry Andric return false; 1848f0fd8f6SDimitry Andric } 1858f0fd8f6SDimitry Andric 1868f0fd8f6SDimitry Andric // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ 1878f0fd8f6SDimitry Andric // together. 1888f0fd8f6SDimitry Andric bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override { 1898f0fd8f6SDimitry Andric MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); 1908f0fd8f6SDimitry Andric if (getSlot(MII) == getSlot(MIJ)) 1918f0fd8f6SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = true; 1928f0fd8f6SDimitry Andric // Does MII and MIJ share the same pred_sel ? 1938f0fd8f6SDimitry Andric int OpI = TII->getOperandIdx(MII->getOpcode(), AMDGPU::OpName::pred_sel), 1948f0fd8f6SDimitry Andric OpJ = TII->getOperandIdx(MIJ->getOpcode(), AMDGPU::OpName::pred_sel); 1958f0fd8f6SDimitry Andric unsigned PredI = (OpI > -1)?MII->getOperand(OpI).getReg():0, 1968f0fd8f6SDimitry Andric PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg():0; 1978f0fd8f6SDimitry Andric if (PredI != PredJ) 1988f0fd8f6SDimitry Andric return false; 1998f0fd8f6SDimitry Andric if (SUJ->isSucc(SUI)) { 2008f0fd8f6SDimitry Andric for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) { 2018f0fd8f6SDimitry Andric const SDep &Dep = SUJ->Succs[i]; 2028f0fd8f6SDimitry Andric if (Dep.getSUnit() != SUI) 2038f0fd8f6SDimitry Andric continue; 2048f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Anti) 2058f0fd8f6SDimitry Andric continue; 2068f0fd8f6SDimitry Andric if (Dep.getKind() == SDep::Output) 2078f0fd8f6SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 2088f0fd8f6SDimitry Andric continue; 2098f0fd8f6SDimitry Andric return false; 2108f0fd8f6SDimitry Andric } 2118f0fd8f6SDimitry Andric } 2128f0fd8f6SDimitry Andric 2138f0fd8f6SDimitry Andric bool ARDef = TII->definesAddressRegister(MII) || 2148f0fd8f6SDimitry Andric TII->definesAddressRegister(MIJ); 2158f0fd8f6SDimitry Andric bool ARUse = TII->usesAddressRegister(MII) || 2168f0fd8f6SDimitry Andric TII->usesAddressRegister(MIJ); 2178f0fd8f6SDimitry Andric if (ARDef && ARUse) 2188f0fd8f6SDimitry Andric return false; 2198f0fd8f6SDimitry Andric 2208f0fd8f6SDimitry Andric return true; 2218f0fd8f6SDimitry Andric } 2228f0fd8f6SDimitry Andric 2238f0fd8f6SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependece between SUI 2248f0fd8f6SDimitry Andric // and SUJ. 2258f0fd8f6SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 2268f0fd8f6SDimitry Andric return false; 2278f0fd8f6SDimitry Andric } 2288f0fd8f6SDimitry Andric 2298f0fd8f6SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 2308f0fd8f6SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), AMDGPU::OpName::last); 2318f0fd8f6SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 2328f0fd8f6SDimitry Andric } 2338f0fd8f6SDimitry Andric 2348f0fd8f6SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr *MI, 2358f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 2368f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 2378f0fd8f6SDimitry Andric bool &isTransSlot) { 2388f0fd8f6SDimitry Andric isTransSlot = TII->isTransOnly(MI); 2398f0fd8f6SDimitry Andric assert (!isTransSlot || VLIW5); 2408f0fd8f6SDimitry Andric 2418f0fd8f6SDimitry Andric // Is the dst reg sequence legal ? 2428f0fd8f6SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 2438f0fd8f6SDimitry Andric if (getSlot(MI) <= getSlot(CurrentPacketMIs.back())) { 2448f0fd8f6SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 2458f0fd8f6SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 2468f0fd8f6SDimitry Andric isTransSlot = true; 2478f0fd8f6SDimitry Andric DEBUG(dbgs() << "Considering as Trans Inst :"; MI->dump();); 2488f0fd8f6SDimitry Andric } 2498f0fd8f6SDimitry Andric else 2508f0fd8f6SDimitry Andric return false; 2518f0fd8f6SDimitry Andric } 2528f0fd8f6SDimitry Andric } 2538f0fd8f6SDimitry Andric 2548f0fd8f6SDimitry Andric // Are the Constants limitations met ? 2558f0fd8f6SDimitry Andric CurrentPacketMIs.push_back(MI); 2568f0fd8f6SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 2578f0fd8f6SDimitry Andric DEBUG( 2588f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2598f0fd8f6SDimitry Andric MI->dump(); 2608f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2618f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2628f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2638f0fd8f6SDimitry Andric dbgs() << "\n"; 2648f0fd8f6SDimitry Andric } 2658f0fd8f6SDimitry Andric dbgs() << "because of Consts read limitations\n"; 2668f0fd8f6SDimitry Andric ); 2678f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2688f0fd8f6SDimitry Andric return false; 2698f0fd8f6SDimitry Andric } 2708f0fd8f6SDimitry Andric 2718f0fd8f6SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 2728f0fd8f6SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 2738f0fd8f6SDimitry Andric PV, BS, isTransSlot)) { 2748f0fd8f6SDimitry Andric DEBUG( 2758f0fd8f6SDimitry Andric dbgs() << "Couldn't pack :\n"; 2768f0fd8f6SDimitry Andric MI->dump(); 2778f0fd8f6SDimitry Andric dbgs() << "with the following packets :\n"; 2788f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 2798f0fd8f6SDimitry Andric CurrentPacketMIs[i]->dump(); 2808f0fd8f6SDimitry Andric dbgs() << "\n"; 2818f0fd8f6SDimitry Andric } 2828f0fd8f6SDimitry Andric dbgs() << "because of Read port limitations\n"; 2838f0fd8f6SDimitry Andric ); 2848f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2858f0fd8f6SDimitry Andric return false; 2868f0fd8f6SDimitry Andric } 2878f0fd8f6SDimitry Andric 2888f0fd8f6SDimitry Andric // We cannot read LDS source registrs from the Trans slot. 2898f0fd8f6SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 2908f0fd8f6SDimitry Andric return false; 2918f0fd8f6SDimitry Andric 2928f0fd8f6SDimitry Andric CurrentPacketMIs.pop_back(); 2938f0fd8f6SDimitry Andric return true; 2948f0fd8f6SDimitry Andric } 2958f0fd8f6SDimitry Andric 2968f0fd8f6SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr *MI) override { 2978f0fd8f6SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 2988f0fd8f6SDimitry Andric CurrentPacketMIs.empty() ? MI : CurrentPacketMIs.front(); 2998f0fd8f6SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 3008f0fd8f6SDimitry Andric getPreviousVector(FirstInBundle); 3018f0fd8f6SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 3028f0fd8f6SDimitry Andric bool isTransSlot; 3038f0fd8f6SDimitry Andric 3048f0fd8f6SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 3058f0fd8f6SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 3068f0fd8f6SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 3078f0fd8f6SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 3088f0fd8f6SDimitry Andric AMDGPU::OpName::bank_swizzle); 3098f0fd8f6SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 3108f0fd8f6SDimitry Andric } 3118f0fd8f6SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 3128f0fd8f6SDimitry Andric AMDGPU::OpName::bank_swizzle); 3138f0fd8f6SDimitry Andric MI->getOperand(Op).setImm(BS.back()); 3148f0fd8f6SDimitry Andric if (!CurrentPacketMIs.empty()) 3158f0fd8f6SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 3168f0fd8f6SDimitry Andric substitutePV(MI, PV); 3178f0fd8f6SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 3188f0fd8f6SDimitry Andric if (isTransSlot) { 3198f0fd8f6SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 3208f0fd8f6SDimitry Andric } 3218f0fd8f6SDimitry Andric return It; 3228f0fd8f6SDimitry Andric } 3238f0fd8f6SDimitry Andric endPacket(MI->getParent(), MI); 3248f0fd8f6SDimitry Andric if (TII->isTransOnly(MI)) 3258f0fd8f6SDimitry Andric return MI; 3268f0fd8f6SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 3278f0fd8f6SDimitry Andric } 3288f0fd8f6SDimitry Andric }; 3298f0fd8f6SDimitry Andric 3308f0fd8f6SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 3318f0fd8f6SDimitry Andric const TargetInstrInfo *TII = Fn.getSubtarget().getInstrInfo(); 3328f0fd8f6SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 3338f0fd8f6SDimitry Andric 3348f0fd8f6SDimitry Andric // Instantiate the packetizer. 3358f0fd8f6SDimitry Andric R600PacketizerList Packetizer(Fn, MLI); 3368f0fd8f6SDimitry Andric 3378f0fd8f6SDimitry Andric // DFA state table should not be empty. 3388f0fd8f6SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 3398f0fd8f6SDimitry 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) { 3788f0fd8f6SDimitry 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 3958f0fd8f6SDimitry 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 4068f0fd8f6SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer(TargetMachine &tm) { 4078f0fd8f6SDimitry Andric return new R600Packetizer(tm); 4088f0fd8f6SDimitry Andric } 409