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