R600: Packetize instructions
[oota-llvm.git] / lib / Target / R600 / R600Packetizer.cpp
1 //===----- R600Packetizer.cpp - VLIW packetizer ---------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file
11 /// This pass implements instructions packetization for R600. It unsets isLast
12 /// bit of instructions inside a bundle and substitutes src register with
13 /// PreviousVector when applicable.
14 //
15 //===----------------------------------------------------------------------===//
16
17 #ifndef R600PACKETIZER_CPP
18 #define R600PACKETIZER_CPP
19
20 #define DEBUG_TYPE "packets"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/CodeGen/DFAPacketizer.h"
24 #include "llvm/CodeGen/Passes.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineDominators.h"
27 #include "llvm/CodeGen/MachineLoopInfo.h"
28 #include "llvm/CodeGen/ScheduleDAG.h"
29 #include "AMDGPU.h"
30 #include "R600InstrInfo.h"
31
32 namespace llvm {
33
34 class R600Packetizer : public MachineFunctionPass {
35
36 public:
37   static char ID;
38   R600Packetizer(const TargetMachine &TM) : MachineFunctionPass(ID) {}
39
40   void getAnalysisUsage(AnalysisUsage &AU) const {
41     AU.setPreservesCFG();
42     AU.addRequired<MachineDominatorTree>();
43     AU.addPreserved<MachineDominatorTree>();
44     AU.addRequired<MachineLoopInfo>();
45     AU.addPreserved<MachineLoopInfo>();
46     MachineFunctionPass::getAnalysisUsage(AU);
47   }
48
49   const char *getPassName() const {
50     return "R600 Packetizer";
51   }
52
53   bool runOnMachineFunction(MachineFunction &Fn);
54 };
55 char R600Packetizer::ID = 0;
56
57 class R600PacketizerList : public VLIWPacketizerList {
58
59 private:
60   const R600InstrInfo *TII;
61   const R600RegisterInfo &TRI;
62
63   enum BankSwizzle {
64     ALU_VEC_012 = 0,
65     ALU_VEC_021,
66     ALU_VEC_120,
67     ALU_VEC_102,
68     ALU_VEC_201,
69     ALU_VEC_210
70   };
71
72   unsigned getSlot(const MachineInstr *MI) const {
73     return TRI.getHWRegChan(MI->getOperand(0).getReg());
74   }
75
76   std::vector<unsigned> getPreviousVector(MachineBasicBlock::iterator I) const {
77     std::vector<unsigned> Result;
78     I--;
79     if (!TII->isALUInstr(I->getOpcode()) && !I->isBundle())
80       return Result;
81     MachineBasicBlock::instr_iterator BI = I.getInstrIterator();
82     if (I->isBundle())
83       BI++;
84     while (BI->isBundledWithPred() && !TII->isPredicated(BI)) {
85       int OperandIdx = TII->getOperandIdx(BI->getOpcode(), R600Operands::WRITE);
86       if (OperandIdx > -1 && BI->getOperand(OperandIdx).getImm())
87         Result.push_back(BI->getOperand(0).getReg());
88       BI++;
89     }
90     return Result;
91   }
92
93   void substitutePV(MachineInstr *MI, const std::vector<unsigned> &PV) const {
94     R600Operands::Ops Ops[] = {
95       R600Operands::SRC0,
96       R600Operands::SRC1,
97       R600Operands::SRC2
98     };
99     for (unsigned i = 0; i < 3; i++) {
100       int OperandIdx = TII->getOperandIdx(MI->getOpcode(), Ops[i]);
101       if (OperandIdx < 0)
102         continue;
103       unsigned Src = MI->getOperand(OperandIdx).getReg();
104       for (unsigned j = 0, e = PV.size(); j < e; j++) {
105         if (Src == PV[j]) {
106           unsigned Chan = TRI.getHWRegChan(Src);
107           unsigned PVReg;
108           switch (Chan) {
109           case 0:
110             PVReg = AMDGPU::PV_X;
111             break;
112           case 1:
113             PVReg = AMDGPU::PV_Y;
114             break;
115           case 2:
116             PVReg = AMDGPU::PV_Z;
117             break;
118           case 3:
119             PVReg = AMDGPU::PV_W;
120             break;
121           default:
122             llvm_unreachable("Invalid Chan");
123           }
124           MI->getOperand(OperandIdx).setReg(PVReg);
125           break;
126         }
127       }
128     }
129   }
130 public:
131   // Ctor.
132   R600PacketizerList(MachineFunction &MF, MachineLoopInfo &MLI,
133                         MachineDominatorTree &MDT)
134   : VLIWPacketizerList(MF, MLI, MDT, true),
135     TII (static_cast<const R600InstrInfo *>(MF.getTarget().getInstrInfo())),
136     TRI(TII->getRegisterInfo()) { }
137
138   // initPacketizerState - initialize some internal flags.
139   void initPacketizerState() { }
140
141   // ignorePseudoInstruction - Ignore bundling of pseudo instructions.
142   bool ignorePseudoInstruction(MachineInstr *MI, MachineBasicBlock *MBB) {
143     return false;
144   }
145
146   // isSoloInstruction - return true if instruction MI can not be packetized
147   // with any other instruction, which means that MI itself is a packet.
148   bool isSoloInstruction(MachineInstr *MI) {
149     if (TII->isVector(*MI))
150       return true;
151     if (!TII->isALUInstr(MI->getOpcode()))
152       return true;
153     if (TII->get(MI->getOpcode()).TSFlags & R600_InstFlag::TRANS_ONLY)
154       return true;
155     if (TII->isTransOnly(MI))
156       return true;
157     return false;
158   }
159
160   // isLegalToPacketizeTogether - Is it legal to packetize SUI and SUJ
161   // together.
162   bool isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
163     MachineInstr *MII = SUI->getInstr(), *MIJ = SUJ->getInstr();
164     if (getSlot(MII) <= getSlot(MIJ))
165       return false;
166     // Does MII and MIJ share the same pred_sel ?
167     int OpI = TII->getOperandIdx(MII->getOpcode(), R600Operands::PRED_SEL),
168         OpJ = TII->getOperandIdx(MIJ->getOpcode(), R600Operands::PRED_SEL);
169     unsigned PredI = (OpI > -1)?MII->getOperand(OpI).getReg():0,
170         PredJ = (OpJ > -1)?MIJ->getOperand(OpJ).getReg():0;
171     if (PredI != PredJ)
172       return false;
173     if (SUJ->isSucc(SUI)) {
174       for (unsigned i = 0, e = SUJ->Succs.size(); i < e; ++i) {
175         const SDep &Dep = SUJ->Succs[i];
176         if (Dep.getSUnit() != SUI)
177           continue;
178         if (Dep.getKind() == SDep::Anti)
179           continue;
180         if (Dep.getKind() == SDep::Output)
181           if (MII->getOperand(0).getReg() != MIJ->getOperand(0).getReg())
182             continue;
183         return false;
184       }
185     }
186     return true;
187   }
188
189   // isLegalToPruneDependencies - Is it legal to prune dependece between SUI
190   // and SUJ.
191   bool isLegalToPruneDependencies(SUnit *SUI, SUnit *SUJ) {return false;}
192
193   void setIsLastBit(MachineInstr *MI, unsigned Bit) const {
194     unsigned LastOp = TII->getOperandIdx(MI->getOpcode(), R600Operands::LAST);
195     MI->getOperand(LastOp).setImm(Bit);
196   }
197
198   MachineBasicBlock::iterator addToPacket(MachineInstr *MI) {
199     CurrentPacketMIs.push_back(MI);
200     bool FitsConstLimits = TII->canBundle(CurrentPacketMIs);
201     DEBUG(
202       if (!FitsConstLimits) {
203         dbgs() << "Couldn't pack :\n";
204         MI->dump();
205         dbgs() << "with the following packets :\n";
206         for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
207           CurrentPacketMIs[i]->dump();
208           dbgs() << "\n";
209         }
210         dbgs() << "because of Consts read limitations\n";
211       });
212     const std::vector<unsigned> &PV = getPreviousVector(MI);
213     bool FitsReadPortLimits = fitsReadPortLimitation(CurrentPacketMIs, PV);
214     DEBUG(
215       if (!FitsReadPortLimits) {
216         dbgs() << "Couldn't pack :\n";
217         MI->dump();
218         dbgs() << "with the following packets :\n";
219         for (unsigned i = 0, e = CurrentPacketMIs.size() - 1; i < e; i++) {
220           CurrentPacketMIs[i]->dump();
221           dbgs() << "\n";
222         }
223         dbgs() << "because of Read port limitations\n";
224       });
225     bool isBundlable = FitsConstLimits && FitsReadPortLimits;
226     CurrentPacketMIs.pop_back();
227     if (!isBundlable) {
228       endPacket(MI->getParent(), MI);
229       substitutePV(MI, getPreviousVector(MI));
230       return VLIWPacketizerList::addToPacket(MI);
231     }
232     if (!CurrentPacketMIs.empty())
233       setIsLastBit(CurrentPacketMIs.back(), 0);
234     substitutePV(MI, PV);
235     return VLIWPacketizerList::addToPacket(MI);
236   }
237 private:
238   std::vector<std::pair<int, unsigned> >
239   ExtractSrcs(const MachineInstr *MI, const std::vector<unsigned> &PV) const {
240     R600Operands::Ops Ops[] = {
241       R600Operands::SRC0,
242       R600Operands::SRC1,
243       R600Operands::SRC2
244     };
245     std::vector<std::pair<int, unsigned> > Result;
246     for (unsigned i = 0; i < 3; i++) {
247       int OperandIdx = TII->getOperandIdx(MI->getOpcode(), Ops[i]);
248       if (OperandIdx < 0){
249         Result.push_back(std::pair<int, unsigned>(-1,0));
250         continue;
251       }
252       unsigned Src = MI->getOperand(OperandIdx).getReg();
253       if (std::find(PV.begin(), PV.end(), Src) != PV.end()) {
254         Result.push_back(std::pair<int, unsigned>(-1,0));
255         continue;
256       }
257       unsigned Reg = TRI.getEncodingValue(Src) & 0xff;
258       if (Reg > 127) {
259         Result.push_back(std::pair<int, unsigned>(-1,0));
260         continue;
261       }
262       unsigned Chan = TRI.getHWRegChan(Src);
263       Result.push_back(std::pair<int, unsigned>(Reg, Chan));
264     }
265     return Result;
266   }
267
268   std::vector<std::pair<int, unsigned> >
269   Swizzle(std::vector<std::pair<int, unsigned> > Src,
270   BankSwizzle Swz) const {
271     switch (Swz) {
272     case ALU_VEC_012:
273       break;
274     case ALU_VEC_021:
275       std::swap(Src[1], Src[2]);
276       break;
277     case ALU_VEC_102:
278       std::swap(Src[0], Src[1]);
279       break;
280     case ALU_VEC_120:
281       std::swap(Src[0], Src[1]);
282       std::swap(Src[0], Src[2]);
283       break;
284     case ALU_VEC_201:
285       std::swap(Src[0], Src[2]);
286       std::swap(Src[0], Src[1]);
287       break;
288     case ALU_VEC_210:
289       std::swap(Src[0], Src[2]);
290       break;
291     }
292     return Src;
293   }
294
295   bool isLegal(const std::vector<MachineInstr *> &IG,
296       const std::vector<BankSwizzle> &Swz,
297       const std::vector<unsigned> &PV) const {
298     assert (Swz.size() == IG.size());
299     int Vector[4][3];
300     memset(Vector, -1, sizeof(Vector));
301     for (unsigned i = 0, e = IG.size(); i < e; i++) {
302       const std::vector<std::pair<int, unsigned> > &Srcs =
303           Swizzle(ExtractSrcs(IG[i], PV), Swz[i]);
304       for (unsigned j = 0; j < 3; j++) {
305         const std::pair<int, unsigned> &Src = Srcs[j];
306         if (Src.first < 0)
307           continue;
308         if (Vector[Src.second][j] < 0)
309           Vector[Src.second][j] = Src.first;
310         if (Vector[Src.second][j] != Src.first)
311           return false;
312       }
313     }
314     return true;
315   }
316
317   bool recursiveFitsFPLimitation(
318   std::vector<MachineInstr *> IG,
319   const std::vector<unsigned> &PV,
320   std::vector<BankSwizzle> &SwzCandidate,
321   std::vector<MachineInstr *> CurrentlyChecked)
322       const {
323     if (!isLegal(CurrentlyChecked, SwzCandidate, PV))
324       return false;
325     if (IG.size() == CurrentlyChecked.size()) {
326       return true;
327     }
328     BankSwizzle AvailableSwizzle[] = {
329       ALU_VEC_012,
330       ALU_VEC_021,
331       ALU_VEC_120,
332       ALU_VEC_102,
333       ALU_VEC_201,
334       ALU_VEC_210
335     };
336     CurrentlyChecked.push_back(IG[CurrentlyChecked.size()]);
337     for (unsigned i = 0; i < 6; i++) {
338       SwzCandidate.push_back(AvailableSwizzle[i]);
339       if (recursiveFitsFPLimitation(IG, PV, SwzCandidate, CurrentlyChecked))
340         return true;
341       SwzCandidate.pop_back();
342     }
343     return false;
344   }
345
346   bool fitsReadPortLimitation(
347   std::vector<MachineInstr *> IG,
348   const std::vector<unsigned> &PV)
349       const {
350     //Todo : support shared src0 - src1 operand
351     std::vector<BankSwizzle> SwzCandidate;
352     bool Result = recursiveFitsFPLimitation(IG, PV, SwzCandidate,
353         std::vector<MachineInstr *>());
354     if (!Result)
355       return false;
356     for (unsigned i = 0, e = IG.size(); i < e; i++) {
357       MachineInstr *MI = IG[i];
358       unsigned Op = TII->getOperandIdx(MI->getOpcode(),
359           R600Operands::BANK_SWIZZLE);
360       MI->getOperand(Op).setImm(SwzCandidate[i]);
361     }
362     return true;
363   }
364 };
365
366 bool R600Packetizer::runOnMachineFunction(MachineFunction &Fn) {
367   const TargetInstrInfo *TII = Fn.getTarget().getInstrInfo();
368   MachineLoopInfo &MLI = getAnalysis<MachineLoopInfo>();
369   MachineDominatorTree &MDT = getAnalysis<MachineDominatorTree>();
370
371   // Instantiate the packetizer.
372   R600PacketizerList Packetizer(Fn, MLI, MDT);
373
374   // DFA state table should not be empty.
375   assert(Packetizer.getResourceTracker() && "Empty DFA table!");
376
377   //
378   // Loop over all basic blocks and remove KILL pseudo-instructions
379   // These instructions confuse the dependence analysis. Consider:
380   // D0 = ...   (Insn 0)
381   // R0 = KILL R0, D0 (Insn 1)
382   // R0 = ... (Insn 2)
383   // Here, Insn 1 will result in the dependence graph not emitting an output
384   // dependence between Insn 0 and Insn 2. This can lead to incorrect
385   // packetization
386   //
387   for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
388        MBB != MBBe; ++MBB) {
389     MachineBasicBlock::iterator End = MBB->end();
390     MachineBasicBlock::iterator MI = MBB->begin();
391     while (MI != End) {
392       if (MI->isKill()) {
393         MachineBasicBlock::iterator DeleteMI = MI;
394         ++MI;
395         MBB->erase(DeleteMI);
396         End = MBB->end();
397         continue;
398       }
399       ++MI;
400     }
401   }
402
403   // Loop over all of the basic blocks.
404   for (MachineFunction::iterator MBB = Fn.begin(), MBBe = Fn.end();
405        MBB != MBBe; ++MBB) {
406     // Find scheduling regions and schedule / packetize each region.
407     unsigned RemainingCount = MBB->size();
408     for(MachineBasicBlock::iterator RegionEnd = MBB->end();
409         RegionEnd != MBB->begin();) {
410       // The next region starts above the previous region. Look backward in the
411       // instruction stream until we find the nearest boundary.
412       MachineBasicBlock::iterator I = RegionEnd;
413       for(;I != MBB->begin(); --I, --RemainingCount) {
414         if (TII->isSchedulingBoundary(llvm::prior(I), MBB, Fn))
415           break;
416       }
417       I = MBB->begin();
418
419       // Skip empty scheduling regions.
420       if (I == RegionEnd) {
421         RegionEnd = llvm::prior(RegionEnd);
422         --RemainingCount;
423         continue;
424       }
425       // Skip regions with one instruction.
426       if (I == llvm::prior(RegionEnd)) {
427         RegionEnd = llvm::prior(RegionEnd);
428         continue;
429       }
430
431       Packetizer.PacketizeMIs(MBB, I, RegionEnd);
432       RegionEnd = I;
433     }
434   }
435
436   return true;
437
438 }
439
440 }
441
442 llvm::FunctionPass *llvm::createR600Packetizer(TargetMachine &tm) {
443   return new R600Packetizer(tm);
444 }
445
446 #endif // R600PACKETIZER_CPP