1*0b57cec5SDimitry Andric //===----- R600Packetizer.cpp - VLIW packetizer ---------------------------===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric /// \file 10*0b57cec5SDimitry Andric /// This pass implements instructions packetization for R600. It unsets isLast 11*0b57cec5SDimitry Andric /// bit of instructions inside a bundle and substitutes src register with 12*0b57cec5SDimitry Andric /// PreviousVector when applicable. 13*0b57cec5SDimitry Andric // 14*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "AMDGPU.h" 17*0b57cec5SDimitry Andric #include "AMDGPUSubtarget.h" 18*0b57cec5SDimitry Andric #include "R600InstrInfo.h" 19*0b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/DFAPacketizer.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineDominators.h" 22*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 23*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h" 24*0b57cec5SDimitry Andric #include "llvm/CodeGen/Passes.h" 25*0b57cec5SDimitry Andric #include "llvm/CodeGen/ScheduleDAG.h" 26*0b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 27*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric using namespace llvm; 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric #define DEBUG_TYPE "packets" 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric namespace { 34*0b57cec5SDimitry Andric 35*0b57cec5SDimitry Andric class R600Packetizer : public MachineFunctionPass { 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric public: 38*0b57cec5SDimitry Andric static char ID; 39*0b57cec5SDimitry Andric R600Packetizer() : MachineFunctionPass(ID) {} 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 42*0b57cec5SDimitry Andric AU.setPreservesCFG(); 43*0b57cec5SDimitry Andric AU.addRequired<MachineDominatorTree>(); 44*0b57cec5SDimitry Andric AU.addPreserved<MachineDominatorTree>(); 45*0b57cec5SDimitry Andric AU.addRequired<MachineLoopInfo>(); 46*0b57cec5SDimitry Andric AU.addPreserved<MachineLoopInfo>(); 47*0b57cec5SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 48*0b57cec5SDimitry Andric } 49*0b57cec5SDimitry Andric 50*0b57cec5SDimitry Andric StringRef getPassName() const override { return "R600 Packetizer"; } 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &Fn) override; 53*0b57cec5SDimitry Andric }; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric class R600PacketizerList : public VLIWPacketizerList { 56*0b57cec5SDimitry Andric private: 57*0b57cec5SDimitry Andric const R600InstrInfo *TII; 58*0b57cec5SDimitry Andric const R600RegisterInfo &TRI; 59*0b57cec5SDimitry Andric bool VLIW5; 60*0b57cec5SDimitry Andric bool ConsideredInstUsesAlreadyWrittenVectorElement; 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric unsigned getSlot(const MachineInstr &MI) const { 63*0b57cec5SDimitry Andric return TRI.getHWRegChan(MI.getOperand(0).getReg()); 64*0b57cec5SDimitry Andric } 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric /// \returns register to PV chan mapping for bundle/single instructions that 67*0b57cec5SDimitry Andric /// immediately precedes I. 68*0b57cec5SDimitry Andric DenseMap<unsigned, unsigned> getPreviousVector(MachineBasicBlock::iterator I) 69*0b57cec5SDimitry Andric const { 70*0b57cec5SDimitry Andric DenseMap<unsigned, unsigned> Result; 71*0b57cec5SDimitry Andric I--; 72*0b57cec5SDimitry Andric if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle()) 73*0b57cec5SDimitry Andric return Result; 74*0b57cec5SDimitry Andric MachineBasicBlock::instr_iterator BI = I.getInstrIterator(); 75*0b57cec5SDimitry Andric if (I->isBundle()) 76*0b57cec5SDimitry Andric BI++; 77*0b57cec5SDimitry Andric int LastDstChan = -1; 78*0b57cec5SDimitry Andric do { 79*0b57cec5SDimitry Andric bool isTrans = false; 80*0b57cec5SDimitry Andric int BISlot = getSlot(*BI); 81*0b57cec5SDimitry Andric if (LastDstChan >= BISlot) 82*0b57cec5SDimitry Andric isTrans = true; 83*0b57cec5SDimitry Andric LastDstChan = BISlot; 84*0b57cec5SDimitry Andric if (TII->isPredicated(*BI)) 85*0b57cec5SDimitry Andric continue; 86*0b57cec5SDimitry Andric int OperandIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::write); 87*0b57cec5SDimitry Andric if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm() == 0) 88*0b57cec5SDimitry Andric continue; 89*0b57cec5SDimitry Andric int DstIdx = TII->getOperandIdx(BI->getOpcode(), R600::OpName::dst); 90*0b57cec5SDimitry Andric if (DstIdx == -1) { 91*0b57cec5SDimitry Andric continue; 92*0b57cec5SDimitry Andric } 93*0b57cec5SDimitry Andric unsigned Dst = BI->getOperand(DstIdx).getReg(); 94*0b57cec5SDimitry Andric if (isTrans || TII->isTransOnly(*BI)) { 95*0b57cec5SDimitry Andric Result[Dst] = R600::PS; 96*0b57cec5SDimitry Andric continue; 97*0b57cec5SDimitry Andric } 98*0b57cec5SDimitry Andric if (BI->getOpcode() == R600::DOT4_r600 || 99*0b57cec5SDimitry Andric BI->getOpcode() == R600::DOT4_eg) { 100*0b57cec5SDimitry Andric Result[Dst] = R600::PV_X; 101*0b57cec5SDimitry Andric continue; 102*0b57cec5SDimitry Andric } 103*0b57cec5SDimitry Andric if (Dst == R600::OQAP) { 104*0b57cec5SDimitry Andric continue; 105*0b57cec5SDimitry Andric } 106*0b57cec5SDimitry Andric unsigned PVReg = 0; 107*0b57cec5SDimitry Andric switch (TRI.getHWRegChan(Dst)) { 108*0b57cec5SDimitry Andric case 0: 109*0b57cec5SDimitry Andric PVReg = R600::PV_X; 110*0b57cec5SDimitry Andric break; 111*0b57cec5SDimitry Andric case 1: 112*0b57cec5SDimitry Andric PVReg = R600::PV_Y; 113*0b57cec5SDimitry Andric break; 114*0b57cec5SDimitry Andric case 2: 115*0b57cec5SDimitry Andric PVReg = R600::PV_Z; 116*0b57cec5SDimitry Andric break; 117*0b57cec5SDimitry Andric case 3: 118*0b57cec5SDimitry Andric PVReg = R600::PV_W; 119*0b57cec5SDimitry Andric break; 120*0b57cec5SDimitry Andric default: 121*0b57cec5SDimitry Andric llvm_unreachable("Invalid Chan"); 122*0b57cec5SDimitry Andric } 123*0b57cec5SDimitry Andric Result[Dst] = PVReg; 124*0b57cec5SDimitry Andric } while ((++BI)->isBundledWithPred()); 125*0b57cec5SDimitry Andric return Result; 126*0b57cec5SDimitry Andric } 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric void substitutePV(MachineInstr &MI, const DenseMap<unsigned, unsigned> &PVs) 129*0b57cec5SDimitry Andric const { 130*0b57cec5SDimitry Andric unsigned Ops[] = { 131*0b57cec5SDimitry Andric R600::OpName::src0, 132*0b57cec5SDimitry Andric R600::OpName::src1, 133*0b57cec5SDimitry Andric R600::OpName::src2 134*0b57cec5SDimitry Andric }; 135*0b57cec5SDimitry Andric for (unsigned i = 0; i < 3; i++) { 136*0b57cec5SDimitry Andric int OperandIdx = TII->getOperandIdx(MI.getOpcode(), Ops[i]); 137*0b57cec5SDimitry Andric if (OperandIdx < 0) 138*0b57cec5SDimitry Andric continue; 139*0b57cec5SDimitry Andric unsigned Src = MI.getOperand(OperandIdx).getReg(); 140*0b57cec5SDimitry Andric const DenseMap<unsigned, unsigned>::const_iterator It = PVs.find(Src); 141*0b57cec5SDimitry Andric if (It != PVs.end()) 142*0b57cec5SDimitry Andric MI.getOperand(OperandIdx).setReg(It->second); 143*0b57cec5SDimitry Andric } 144*0b57cec5SDimitry Andric } 145*0b57cec5SDimitry Andric public: 146*0b57cec5SDimitry Andric // Ctor. 147*0b57cec5SDimitry Andric R600PacketizerList(MachineFunction &MF, const R600Subtarget &ST, 148*0b57cec5SDimitry Andric MachineLoopInfo &MLI) 149*0b57cec5SDimitry Andric : VLIWPacketizerList(MF, MLI, nullptr), 150*0b57cec5SDimitry Andric TII(ST.getInstrInfo()), 151*0b57cec5SDimitry Andric TRI(TII->getRegisterInfo()) { 152*0b57cec5SDimitry Andric VLIW5 = !ST.hasCaymanISA(); 153*0b57cec5SDimitry Andric } 154*0b57cec5SDimitry Andric 155*0b57cec5SDimitry Andric // initPacketizerState - initialize some internal flags. 156*0b57cec5SDimitry Andric void initPacketizerState() override { 157*0b57cec5SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = false; 158*0b57cec5SDimitry Andric } 159*0b57cec5SDimitry Andric 160*0b57cec5SDimitry Andric // ignorePseudoInstruction - Ignore bundling of pseudo instructions. 161*0b57cec5SDimitry Andric bool ignorePseudoInstruction(const MachineInstr &MI, 162*0b57cec5SDimitry Andric const MachineBasicBlock *MBB) override { 163*0b57cec5SDimitry Andric return false; 164*0b57cec5SDimitry Andric } 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric // isSoloInstruction - return true if instruction MI can not be packetized 167*0b57cec5SDimitry Andric // with any other instruction, which means that MI itself is a packet. 168*0b57cec5SDimitry Andric bool isSoloInstruction(const MachineInstr &MI) override { 169*0b57cec5SDimitry Andric if (TII->isVector(MI)) 170*0b57cec5SDimitry Andric return true; 171*0b57cec5SDimitry Andric if (!TII->isALUInstr(MI.getOpcode())) 172*0b57cec5SDimitry Andric return true; 173*0b57cec5SDimitry Andric if (MI.getOpcode() == R600::GROUP_BARRIER) 174*0b57cec5SDimitry Andric return true; 175*0b57cec5SDimitry Andric // XXX: This can be removed once the packetizer properly handles all the 176*0b57cec5SDimitry Andric // LDS instruction group restrictions. 177*0b57cec5SDimitry Andric return TII->isLDSInstr(MI.getOpcode()); 178*0b57cec5SDimitry Andric } 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ 181*0b57cec5SDimitry Andric // together. 182*0b57cec5SDimitry Andric bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) override { 183*0b57cec5SDimitry Andric MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr(); 184*0b57cec5SDimitry Andric if (getSlot(*MII) == getSlot(*MIJ)) 185*0b57cec5SDimitry Andric ConsideredInstUsesAlreadyWrittenVectorElement = true; 186*0b57cec5SDimitry Andric // Does MII and MIJ share the same pred_sel ? 187*0b57cec5SDimitry Andric int OpI = TII->getOperandIdx(MII->getOpcode(), R600::OpName::pred_sel), 188*0b57cec5SDimitry Andric OpJ = TII->getOperandIdx(MIJ->getOpcode(), R600::OpName::pred_sel); 189*0b57cec5SDimitry Andric Register PredI = (OpI > -1)?MII->getOperand(OpI).getReg() : Register(), 190*0b57cec5SDimitry Andric PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg() : Register(); 191*0b57cec5SDimitry Andric if (PredI != PredJ) 192*0b57cec5SDimitry Andric return false; 193*0b57cec5SDimitry Andric if (SUJ->isSucc(SUI)) { 194*0b57cec5SDimitry Andric for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) { 195*0b57cec5SDimitry Andric const SDep &Dep = SUJ->Succs[i]; 196*0b57cec5SDimitry Andric if (Dep.getSUnit() != SUI) 197*0b57cec5SDimitry Andric continue; 198*0b57cec5SDimitry Andric if (Dep.getKind() == SDep::Anti) 199*0b57cec5SDimitry Andric continue; 200*0b57cec5SDimitry Andric if (Dep.getKind() == SDep::Output) 201*0b57cec5SDimitry Andric if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg()) 202*0b57cec5SDimitry Andric continue; 203*0b57cec5SDimitry Andric return false; 204*0b57cec5SDimitry Andric } 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric bool ARDef = 208*0b57cec5SDimitry Andric TII->definesAddressRegister(*MII) || TII->definesAddressRegister(*MIJ); 209*0b57cec5SDimitry Andric bool ARUse = 210*0b57cec5SDimitry Andric TII->usesAddressRegister(*MII) || TII->usesAddressRegister(*MIJ); 211*0b57cec5SDimitry Andric 212*0b57cec5SDimitry Andric return !ARDef || !ARUse; 213*0b57cec5SDimitry Andric } 214*0b57cec5SDimitry Andric 215*0b57cec5SDimitry Andric // isLegalToPruneDependencies - Is it legal to prune dependece between SUI 216*0b57cec5SDimitry Andric // and SUJ. 217*0b57cec5SDimitry Andric bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) override { 218*0b57cec5SDimitry Andric return false; 219*0b57cec5SDimitry Andric } 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric void setIsLastBit(MachineInstr *MI, unsigned Bit) const { 222*0b57cec5SDimitry Andric unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), R600::OpName::last); 223*0b57cec5SDimitry Andric MI->getOperand(LastOp).setImm(Bit); 224*0b57cec5SDimitry Andric } 225*0b57cec5SDimitry Andric 226*0b57cec5SDimitry Andric bool isBundlableWithCurrentPMI(MachineInstr &MI, 227*0b57cec5SDimitry Andric const DenseMap<unsigned, unsigned> &PV, 228*0b57cec5SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> &BS, 229*0b57cec5SDimitry Andric bool &isTransSlot) { 230*0b57cec5SDimitry Andric isTransSlot = TII->isTransOnly(MI); 231*0b57cec5SDimitry Andric assert (!isTransSlot || VLIW5); 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric // Is the dst reg sequence legal ? 234*0b57cec5SDimitry Andric if (!isTransSlot && !CurrentPacketMIs.empty()) { 235*0b57cec5SDimitry Andric if (getSlot(MI) <= getSlot(*CurrentPacketMIs.back())) { 236*0b57cec5SDimitry Andric if (ConsideredInstUsesAlreadyWrittenVectorElement && 237*0b57cec5SDimitry Andric !TII->isVectorOnly(MI) && VLIW5) { 238*0b57cec5SDimitry Andric isTransSlot = true; 239*0b57cec5SDimitry Andric LLVM_DEBUG({ 240*0b57cec5SDimitry Andric dbgs() << "Considering as Trans Inst :"; 241*0b57cec5SDimitry Andric MI.dump(); 242*0b57cec5SDimitry Andric }); 243*0b57cec5SDimitry Andric } 244*0b57cec5SDimitry Andric else 245*0b57cec5SDimitry Andric return false; 246*0b57cec5SDimitry Andric } 247*0b57cec5SDimitry Andric } 248*0b57cec5SDimitry Andric 249*0b57cec5SDimitry Andric // Are the Constants limitations met ? 250*0b57cec5SDimitry Andric CurrentPacketMIs.push_back(&MI); 251*0b57cec5SDimitry Andric if (!TII->fitsConstReadLimitations(CurrentPacketMIs)) { 252*0b57cec5SDimitry Andric LLVM_DEBUG({ 253*0b57cec5SDimitry Andric dbgs() << "Couldn't pack :\n"; 254*0b57cec5SDimitry Andric MI.dump(); 255*0b57cec5SDimitry Andric dbgs() << "with the following packets :\n"; 256*0b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 257*0b57cec5SDimitry Andric CurrentPacketMIs[i]->dump(); 258*0b57cec5SDimitry Andric dbgs() << "\n"; 259*0b57cec5SDimitry Andric } 260*0b57cec5SDimitry Andric dbgs() << "because of Consts read limitations\n"; 261*0b57cec5SDimitry Andric }); 262*0b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 263*0b57cec5SDimitry Andric return false; 264*0b57cec5SDimitry Andric } 265*0b57cec5SDimitry Andric 266*0b57cec5SDimitry Andric // Is there a BankSwizzle set that meet Read Port limitations ? 267*0b57cec5SDimitry Andric if (!TII->fitsReadPortLimitations(CurrentPacketMIs, 268*0b57cec5SDimitry Andric PV, BS, isTransSlot)) { 269*0b57cec5SDimitry Andric LLVM_DEBUG({ 270*0b57cec5SDimitry Andric dbgs() << "Couldn't pack :\n"; 271*0b57cec5SDimitry Andric MI.dump(); 272*0b57cec5SDimitry Andric dbgs() << "with the following packets :\n"; 273*0b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) { 274*0b57cec5SDimitry Andric CurrentPacketMIs[i]->dump(); 275*0b57cec5SDimitry Andric dbgs() << "\n"; 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric dbgs() << "because of Read port limitations\n"; 278*0b57cec5SDimitry Andric }); 279*0b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 280*0b57cec5SDimitry Andric return false; 281*0b57cec5SDimitry Andric } 282*0b57cec5SDimitry Andric 283*0b57cec5SDimitry Andric // We cannot read LDS source registers from the Trans slot. 284*0b57cec5SDimitry Andric if (isTransSlot && TII->readsLDSSrcReg(MI)) 285*0b57cec5SDimitry Andric return false; 286*0b57cec5SDimitry Andric 287*0b57cec5SDimitry Andric CurrentPacketMIs.pop_back(); 288*0b57cec5SDimitry Andric return true; 289*0b57cec5SDimitry Andric } 290*0b57cec5SDimitry Andric 291*0b57cec5SDimitry Andric MachineBasicBlock::iterator addToPacket(MachineInstr &MI) override { 292*0b57cec5SDimitry Andric MachineBasicBlock::iterator FirstInBundle = 293*0b57cec5SDimitry Andric CurrentPacketMIs.empty() ? &MI : CurrentPacketMIs.front(); 294*0b57cec5SDimitry Andric const DenseMap<unsigned, unsigned> &PV = 295*0b57cec5SDimitry Andric getPreviousVector(FirstInBundle); 296*0b57cec5SDimitry Andric std::vector<R600InstrInfo::BankSwizzle> BS; 297*0b57cec5SDimitry Andric bool isTransSlot; 298*0b57cec5SDimitry Andric 299*0b57cec5SDimitry Andric if (isBundlableWithCurrentPMI(MI, PV, BS, isTransSlot)) { 300*0b57cec5SDimitry Andric for (unsigned i = 0, e = CurrentPacketMIs.size(); i < e; i++) { 301*0b57cec5SDimitry Andric MachineInstr *MI = CurrentPacketMIs[i]; 302*0b57cec5SDimitry Andric unsigned Op = TII->getOperandIdx(MI->getOpcode(), 303*0b57cec5SDimitry Andric R600::OpName::bank_swizzle); 304*0b57cec5SDimitry Andric MI->getOperand(Op).setImm(BS[i]); 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric unsigned Op = 307*0b57cec5SDimitry Andric TII->getOperandIdx(MI.getOpcode(), R600::OpName::bank_swizzle); 308*0b57cec5SDimitry Andric MI.getOperand(Op).setImm(BS.back()); 309*0b57cec5SDimitry Andric if (!CurrentPacketMIs.empty()) 310*0b57cec5SDimitry Andric setIsLastBit(CurrentPacketMIs.back(), 0); 311*0b57cec5SDimitry Andric substitutePV(MI, PV); 312*0b57cec5SDimitry Andric MachineBasicBlock::iterator It = VLIWPacketizerList::addToPacket(MI); 313*0b57cec5SDimitry Andric if (isTransSlot) { 314*0b57cec5SDimitry Andric endPacket(std::next(It)->getParent(), std::next(It)); 315*0b57cec5SDimitry Andric } 316*0b57cec5SDimitry Andric return It; 317*0b57cec5SDimitry Andric } 318*0b57cec5SDimitry Andric endPacket(MI.getParent(), MI); 319*0b57cec5SDimitry Andric if (TII->isTransOnly(MI)) 320*0b57cec5SDimitry Andric return MI; 321*0b57cec5SDimitry Andric return VLIWPacketizerList::addToPacket(MI); 322*0b57cec5SDimitry Andric } 323*0b57cec5SDimitry Andric }; 324*0b57cec5SDimitry Andric 325*0b57cec5SDimitry Andric bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) { 326*0b57cec5SDimitry Andric const R600Subtarget &ST = Fn.getSubtarget<R600Subtarget>(); 327*0b57cec5SDimitry Andric const R600InstrInfo *TII = ST.getInstrInfo(); 328*0b57cec5SDimitry Andric 329*0b57cec5SDimitry Andric MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>(); 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric // Instantiate the packetizer. 332*0b57cec5SDimitry Andric R600PacketizerList Packetizer(Fn, ST, MLI); 333*0b57cec5SDimitry Andric 334*0b57cec5SDimitry Andric // DFA state table should not be empty. 335*0b57cec5SDimitry Andric assert(Packetizer.getResourceTracker() && "Empty DFA table!"); 336*0b57cec5SDimitry Andric assert(Packetizer.getResourceTracker()->getInstrItins()); 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric if (Packetizer.getResourceTracker()->getInstrItins()->isEmpty()) 339*0b57cec5SDimitry Andric return false; 340*0b57cec5SDimitry Andric 341*0b57cec5SDimitry Andric // 342*0b57cec5SDimitry Andric // Loop over all basic blocks and remove KILL pseudo-instructions 343*0b57cec5SDimitry Andric // These instructions confuse the dependence analysis. Consider: 344*0b57cec5SDimitry Andric // D0 = ... (Insn 0) 345*0b57cec5SDimitry Andric // R0 = KILL R0, D0 (Insn 1) 346*0b57cec5SDimitry Andric // R0 = ... (Insn 2) 347*0b57cec5SDimitry Andric // Here, Insn 1 will result in the dependence graph not emitting an output 348*0b57cec5SDimitry Andric // dependence between Insn 0 and Insn 2. This can lead to incorrect 349*0b57cec5SDimitry Andric // packetization 350*0b57cec5SDimitry Andric // 351*0b57cec5SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 352*0b57cec5SDimitry Andric MBB != MBBe; ++MBB) { 353*0b57cec5SDimitry Andric MachineBasicBlock::iterator End = MBB->end(); 354*0b57cec5SDimitry Andric MachineBasicBlock::iterator MI = MBB->begin(); 355*0b57cec5SDimitry Andric while (MI != End) { 356*0b57cec5SDimitry Andric if (MI->isKill() || MI->getOpcode() == R600::IMPLICIT_DEF || 357*0b57cec5SDimitry Andric (MI->getOpcode() == R600::CF_ALU && !MI->getOperand(8).getImm())) { 358*0b57cec5SDimitry Andric MachineBasicBlock::iterator DeleteMI = MI; 359*0b57cec5SDimitry Andric ++MI; 360*0b57cec5SDimitry Andric MBB->erase(DeleteMI); 361*0b57cec5SDimitry Andric End = MBB->end(); 362*0b57cec5SDimitry Andric continue; 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric ++MI; 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric // Loop over all of the basic blocks. 369*0b57cec5SDimitry Andric for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end(); 370*0b57cec5SDimitry Andric MBB != MBBe; ++MBB) { 371*0b57cec5SDimitry Andric // Find scheduling regions and schedule / packetize each region. 372*0b57cec5SDimitry Andric unsigned RemainingCount = MBB->size(); 373*0b57cec5SDimitry Andric for(MachineBasicBlock::iterator RegionEnd = MBB->end(); 374*0b57cec5SDimitry Andric RegionEnd != MBB->begin();) { 375*0b57cec5SDimitry Andric // The next region starts above the previous region. Look backward in the 376*0b57cec5SDimitry Andric // instruction stream until we find the nearest boundary. 377*0b57cec5SDimitry Andric MachineBasicBlock::iterator I = RegionEnd; 378*0b57cec5SDimitry Andric for(;I != MBB->begin(); --I, --RemainingCount) { 379*0b57cec5SDimitry Andric if (TII->isSchedulingBoundary(*std::prev(I), &*MBB, Fn)) 380*0b57cec5SDimitry Andric break; 381*0b57cec5SDimitry Andric } 382*0b57cec5SDimitry Andric I = MBB->begin(); 383*0b57cec5SDimitry Andric 384*0b57cec5SDimitry Andric // Skip empty scheduling regions. 385*0b57cec5SDimitry Andric if (I == RegionEnd) { 386*0b57cec5SDimitry Andric RegionEnd = std::prev(RegionEnd); 387*0b57cec5SDimitry Andric --RemainingCount; 388*0b57cec5SDimitry Andric continue; 389*0b57cec5SDimitry Andric } 390*0b57cec5SDimitry Andric // Skip regions with one instruction. 391*0b57cec5SDimitry Andric if (I == std::prev(RegionEnd)) { 392*0b57cec5SDimitry Andric RegionEnd = std::prev(RegionEnd); 393*0b57cec5SDimitry Andric continue; 394*0b57cec5SDimitry Andric } 395*0b57cec5SDimitry Andric 396*0b57cec5SDimitry Andric Packetizer.PacketizeMIs(&*MBB, &*I, RegionEnd); 397*0b57cec5SDimitry Andric RegionEnd = I; 398*0b57cec5SDimitry Andric } 399*0b57cec5SDimitry Andric } 400*0b57cec5SDimitry Andric 401*0b57cec5SDimitry Andric return true; 402*0b57cec5SDimitry Andric 403*0b57cec5SDimitry Andric } 404*0b57cec5SDimitry Andric 405*0b57cec5SDimitry Andric } // end anonymous namespace 406*0b57cec5SDimitry Andric 407*0b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(R600Packetizer, DEBUG_TYPE, 408*0b57cec5SDimitry Andric "R600 Packetizer", false, false) 409*0b57cec5SDimitry Andric INITIALIZE_PASS_END(R600Packetizer, DEBUG_TYPE, 410*0b57cec5SDimitry Andric "R600 Packetizer", false, false) 411*0b57cec5SDimitry Andric 412*0b57cec5SDimitry Andric char R600Packetizer::ID = 0; 413*0b57cec5SDimitry Andric 414*0b57cec5SDimitry Andric char &llvm::R600PacketizerID = R600Packetizer::ID; 415*0b57cec5SDimitry Andric 416*0b57cec5SDimitry Andric llvm::FunctionPass *llvm::createR600Packetizer() { 417*0b57cec5SDimitry Andric return new R600Packetizer(); 418*0b57cec5SDimitry Andric } 419