xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600Packetizer.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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