]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/llvm/lib/Target/R600/R600InstrInfo.cpp
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / llvm / lib / Target / R600 / R600InstrInfo.cpp
1 //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
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 /// \brief R600 Implementation of TargetInstrInfo.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "R600InstrInfo.h"
16 #include "AMDGPU.h"
17 #include "AMDGPUSubtarget.h"
18 #include "AMDGPUTargetMachine.h"
19 #include "R600Defines.h"
20 #include "R600MachineFunctionInfo.h"
21 #include "R600RegisterInfo.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25
26 #define GET_INSTRINFO_CTOR
27 #include "AMDGPUGenDFAPacketizer.inc"
28
29 using namespace llvm;
30
31 R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm)
32   : AMDGPUInstrInfo(tm),
33     RI(tm, *this),
34     ST(tm.getSubtarget<AMDGPUSubtarget>())
35   { }
36
37 const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const {
38   return RI;
39 }
40
41 bool R600InstrInfo::isTrig(const MachineInstr &MI) const {
42   return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG;
43 }
44
45 bool R600InstrInfo::isVector(const MachineInstr &MI) const {
46   return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
47 }
48
49 void
50 R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
51                            MachineBasicBlock::iterator MI, DebugLoc DL,
52                            unsigned DestReg, unsigned SrcReg,
53                            bool KillSrc) const {
54   if (AMDGPU::R600_Reg128RegClass.contains(DestReg)
55       && AMDGPU::R600_Reg128RegClass.contains(SrcReg)) {
56     for (unsigned I = 0; I < 4; I++) {
57       unsigned SubRegIndex = RI.getSubRegFromChannel(I);
58       buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
59                               RI.getSubReg(DestReg, SubRegIndex),
60                               RI.getSubReg(SrcReg, SubRegIndex))
61                               .addReg(DestReg,
62                                       RegState::Define | RegState::Implicit);
63     }
64   } else {
65
66     // We can't copy vec4 registers
67     assert(!AMDGPU::R600_Reg128RegClass.contains(DestReg)
68            && !AMDGPU::R600_Reg128RegClass.contains(SrcReg));
69
70     MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
71                                                   DestReg, SrcReg);
72     NewMI->getOperand(getOperandIdx(*NewMI, R600Operands::SRC0))
73                                     .setIsKill(KillSrc);
74   }
75 }
76
77 MachineInstr * R600InstrInfo::getMovImmInstr(MachineFunction *MF,
78                                              unsigned DstReg, int64_t Imm) const {
79   MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::MOV), DebugLoc());
80   MachineInstrBuilder MIB(*MF, MI);
81   MIB.addReg(DstReg, RegState::Define);
82   MIB.addReg(AMDGPU::ALU_LITERAL_X);
83   MIB.addImm(Imm);
84   MIB.addReg(0); // PREDICATE_BIT
85
86   return MI;
87 }
88
89 unsigned R600InstrInfo::getIEQOpcode() const {
90   return AMDGPU::SETE_INT;
91 }
92
93 bool R600InstrInfo::isMov(unsigned Opcode) const {
94
95
96   switch(Opcode) {
97   default: return false;
98   case AMDGPU::MOV:
99   case AMDGPU::MOV_IMM_F32:
100   case AMDGPU::MOV_IMM_I32:
101     return true;
102   }
103 }
104
105 // Some instructions act as place holders to emulate operations that the GPU
106 // hardware does automatically. This function can be used to check if
107 // an opcode falls into this category.
108 bool R600InstrInfo::isPlaceHolderOpcode(unsigned Opcode) const {
109   switch (Opcode) {
110   default: return false;
111   case AMDGPU::RETURN:
112     return true;
113   }
114 }
115
116 bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
117   switch(Opcode) {
118     default: return false;
119     case AMDGPU::DOT4_r600_pseudo:
120     case AMDGPU::DOT4_eg_pseudo:
121       return true;
122   }
123 }
124
125 bool R600InstrInfo::isCubeOp(unsigned Opcode) const {
126   switch(Opcode) {
127     default: return false;
128     case AMDGPU::CUBE_r600_pseudo:
129     case AMDGPU::CUBE_r600_real:
130     case AMDGPU::CUBE_eg_pseudo:
131     case AMDGPU::CUBE_eg_real:
132       return true;
133   }
134 }
135
136 bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
137   unsigned TargetFlags = get(Opcode).TSFlags;
138
139   return ((TargetFlags & R600_InstFlag::OP1) |
140           (TargetFlags & R600_InstFlag::OP2) |
141           (TargetFlags & R600_InstFlag::OP3));
142 }
143
144 bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
145   return (get(Opcode).TSFlags & R600_InstFlag::TRANS_ONLY);
146 }
147
148 bool R600InstrInfo::isTransOnly(const MachineInstr *MI) const {
149   return isTransOnly(MI->getOpcode());
150 }
151
152 bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
153   return ST.hasVertexCache() && IS_VTX(get(Opcode));
154 }
155
156 bool R600InstrInfo::usesVertexCache(const MachineInstr *MI) const {
157   const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
158   return MFI->ShaderType != ShaderType::COMPUTE && usesVertexCache(MI->getOpcode());
159 }
160
161 bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
162   return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
163 }
164
165 bool R600InstrInfo::usesTextureCache(const MachineInstr *MI) const {
166   const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
167   return (MFI->ShaderType == ShaderType::COMPUTE && usesVertexCache(MI->getOpcode())) ||
168          usesTextureCache(MI->getOpcode());
169 }
170
171 bool
172 R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
173     const {
174   assert (Consts.size() <= 12 && "Too many operands in instructions group");
175   unsigned Pair1 = 0, Pair2 = 0;
176   for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
177     unsigned ReadConstHalf = Consts[i] & 2;
178     unsigned ReadConstIndex = Consts[i] & (~3);
179     unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
180     if (!Pair1) {
181       Pair1 = ReadHalfConst;
182       continue;
183     }
184     if (Pair1 == ReadHalfConst)
185       continue;
186     if (!Pair2) {
187       Pair2 = ReadHalfConst;
188       continue;
189     }
190     if (Pair2 != ReadHalfConst)
191       return false;
192   }
193   return true;
194 }
195
196 bool
197 R600InstrInfo::canBundle(const std::vector<MachineInstr *> &MIs) const {
198   std::vector<unsigned> Consts;
199   for (unsigned i = 0, n = MIs.size(); i < n; i++) {
200     const MachineInstr *MI = MIs[i];
201
202     const R600Operands::Ops OpTable[3][2] = {
203       {R600Operands::SRC0, R600Operands::SRC0_SEL},
204       {R600Operands::SRC1, R600Operands::SRC1_SEL},
205       {R600Operands::SRC2, R600Operands::SRC2_SEL},
206     };
207
208     if (!isALUInstr(MI->getOpcode()))
209       continue;
210
211     for (unsigned j = 0; j < 3; j++) {
212       int SrcIdx = getOperandIdx(MI->getOpcode(), OpTable[j][0]);
213       if (SrcIdx < 0)
214         break;
215       unsigned Reg = MI->getOperand(SrcIdx).getReg();
216       if (Reg == AMDGPU::ALU_CONST) {
217         unsigned Const = MI->getOperand(
218             getOperandIdx(MI->getOpcode(), OpTable[j][1])).getImm();
219         Consts.push_back(Const);
220         continue;
221       }
222       if (AMDGPU::R600_KC0RegClass.contains(Reg) ||
223           AMDGPU::R600_KC1RegClass.contains(Reg)) {
224         unsigned Index = RI.getEncodingValue(Reg) & 0xff;
225         unsigned Chan = RI.getHWRegChan(Reg);
226         Consts.push_back((Index << 2) | Chan);
227         continue;
228       }
229     }
230   }
231   return fitsConstReadLimitations(Consts);
232 }
233
234 DFAPacketizer *R600InstrInfo::CreateTargetScheduleState(const TargetMachine *TM,
235     const ScheduleDAG *DAG) const {
236   const InstrItineraryData *II = TM->getInstrItineraryData();
237   return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II);
238 }
239
240 static bool
241 isPredicateSetter(unsigned Opcode) {
242   switch (Opcode) {
243   case AMDGPU::PRED_X:
244     return true;
245   default:
246     return false;
247   }
248 }
249
250 static MachineInstr *
251 findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
252                              MachineBasicBlock::iterator I) {
253   while (I != MBB.begin()) {
254     --I;
255     MachineInstr *MI = I;
256     if (isPredicateSetter(MI->getOpcode()))
257       return MI;
258   }
259
260   return NULL;
261 }
262
263 static
264 bool isJump(unsigned Opcode) {
265   return Opcode == AMDGPU::JUMP || Opcode == AMDGPU::JUMP_COND;
266 }
267
268 bool
269 R600InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
270                              MachineBasicBlock *&TBB,
271                              MachineBasicBlock *&FBB,
272                              SmallVectorImpl<MachineOperand> &Cond,
273                              bool AllowModify) const {
274   // Most of the following comes from the ARM implementation of AnalyzeBranch
275
276   // If the block has no terminators, it just falls into the block after it.
277   MachineBasicBlock::iterator I = MBB.end();
278   if (I == MBB.begin())
279     return false;
280   --I;
281   while (I->isDebugValue()) {
282     if (I == MBB.begin())
283       return false;
284     --I;
285   }
286   if (!isJump(static_cast<MachineInstr *>(I)->getOpcode())) {
287     return false;
288   }
289
290   // Get the last instruction in the block.
291   MachineInstr *LastInst = I;
292
293   // If there is only one terminator instruction, process it.
294   unsigned LastOpc = LastInst->getOpcode();
295   if (I == MBB.begin() ||
296           !isJump(static_cast<MachineInstr *>(--I)->getOpcode())) {
297     if (LastOpc == AMDGPU::JUMP) {
298       TBB = LastInst->getOperand(0).getMBB();
299       return false;
300     } else if (LastOpc == AMDGPU::JUMP_COND) {
301       MachineInstr *predSet = I;
302       while (!isPredicateSetter(predSet->getOpcode())) {
303         predSet = --I;
304       }
305       TBB = LastInst->getOperand(0).getMBB();
306       Cond.push_back(predSet->getOperand(1));
307       Cond.push_back(predSet->getOperand(2));
308       Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
309       return false;
310     }
311     return true;  // Can't handle indirect branch.
312   }
313
314   // Get the instruction before it if it is a terminator.
315   MachineInstr *SecondLastInst = I;
316   unsigned SecondLastOpc = SecondLastInst->getOpcode();
317
318   // If the block ends with a B and a Bcc, handle it.
319   if (SecondLastOpc == AMDGPU::JUMP_COND && LastOpc == AMDGPU::JUMP) {
320     MachineInstr *predSet = --I;
321     while (!isPredicateSetter(predSet->getOpcode())) {
322       predSet = --I;
323     }
324     TBB = SecondLastInst->getOperand(0).getMBB();
325     FBB = LastInst->getOperand(0).getMBB();
326     Cond.push_back(predSet->getOperand(1));
327     Cond.push_back(predSet->getOperand(2));
328     Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
329     return false;
330   }
331
332   // Otherwise, can't handle this.
333   return true;
334 }
335
336 int R600InstrInfo::getBranchInstr(const MachineOperand &op) const {
337   const MachineInstr *MI = op.getParent();
338
339   switch (MI->getDesc().OpInfo->RegClass) {
340   default: // FIXME: fallthrough??
341   case AMDGPU::GPRI32RegClassID: return AMDGPU::BRANCH_COND_i32;
342   case AMDGPU::GPRF32RegClassID: return AMDGPU::BRANCH_COND_f32;
343   };
344 }
345
346 unsigned
347 R600InstrInfo::InsertBranch(MachineBasicBlock &MBB,
348                             MachineBasicBlock *TBB,
349                             MachineBasicBlock *FBB,
350                             const SmallVectorImpl<MachineOperand> &Cond,
351                             DebugLoc DL) const {
352   assert(TBB && "InsertBranch must not be told to insert a fallthrough");
353
354   if (FBB == 0) {
355     if (Cond.empty()) {
356       BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(TBB);
357       return 1;
358     } else {
359       MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
360       assert(PredSet && "No previous predicate !");
361       addFlag(PredSet, 0, MO_FLAG_PUSH);
362       PredSet->getOperand(2).setImm(Cond[1].getImm());
363
364       BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
365              .addMBB(TBB)
366              .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
367       return 1;
368     }
369   } else {
370     MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
371     assert(PredSet && "No previous predicate !");
372     addFlag(PredSet, 0, MO_FLAG_PUSH);
373     PredSet->getOperand(2).setImm(Cond[1].getImm());
374     BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
375             .addMBB(TBB)
376             .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
377     BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(FBB);
378     return 2;
379   }
380 }
381
382 unsigned
383 R600InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
384
385   // Note : we leave PRED* instructions there.
386   // They may be needed when predicating instructions.
387
388   MachineBasicBlock::iterator I = MBB.end();
389
390   if (I == MBB.begin()) {
391     return 0;
392   }
393   --I;
394   switch (I->getOpcode()) {
395   default:
396     return 0;
397   case AMDGPU::JUMP_COND: {
398     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
399     clearFlag(predSet, 0, MO_FLAG_PUSH);
400     I->eraseFromParent();
401     break;
402   }
403   case AMDGPU::JUMP:
404     I->eraseFromParent();
405     break;
406   }
407   I = MBB.end();
408
409   if (I == MBB.begin()) {
410     return 1;
411   }
412   --I;
413   switch (I->getOpcode()) {
414     // FIXME: only one case??
415   default:
416     return 1;
417   case AMDGPU::JUMP_COND: {
418     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
419     clearFlag(predSet, 0, MO_FLAG_PUSH);
420     I->eraseFromParent();
421     break;
422   }
423   case AMDGPU::JUMP:
424     I->eraseFromParent();
425     break;
426   }
427   return 2;
428 }
429
430 bool
431 R600InstrInfo::isPredicated(const MachineInstr *MI) const {
432   int idx = MI->findFirstPredOperandIdx();
433   if (idx < 0)
434     return false;
435
436   unsigned Reg = MI->getOperand(idx).getReg();
437   switch (Reg) {
438   default: return false;
439   case AMDGPU::PRED_SEL_ONE:
440   case AMDGPU::PRED_SEL_ZERO:
441   case AMDGPU::PREDICATE_BIT:
442     return true;
443   }
444 }
445
446 bool
447 R600InstrInfo::isPredicable(MachineInstr *MI) const {
448   // XXX: KILL* instructions can be predicated, but they must be the last
449   // instruction in a clause, so this means any instructions after them cannot
450   // be predicated.  Until we have proper support for instruction clauses in the
451   // backend, we will mark KILL* instructions as unpredicable.
452
453   if (MI->getOpcode() == AMDGPU::KILLGT) {
454     return false;
455   } else if (isVector(*MI)) {
456     return false;
457   } else {
458     return AMDGPUInstrInfo::isPredicable(MI);
459   }
460 }
461
462
463 bool
464 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
465                                    unsigned NumCyles,
466                                    unsigned ExtraPredCycles,
467                                    const BranchProbability &Probability) const{
468   return true;
469 }
470
471 bool
472 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
473                                    unsigned NumTCycles,
474                                    unsigned ExtraTCycles,
475                                    MachineBasicBlock &FMBB,
476                                    unsigned NumFCycles,
477                                    unsigned ExtraFCycles,
478                                    const BranchProbability &Probability) const {
479   return true;
480 }
481
482 bool
483 R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
484                                          unsigned NumCyles,
485                                          const BranchProbability &Probability)
486                                          const {
487   return true;
488 }
489
490 bool
491 R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
492                                          MachineBasicBlock &FMBB) const {
493   return false;
494 }
495
496
497 bool
498 R600InstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
499   MachineOperand &MO = Cond[1];
500   switch (MO.getImm()) {
501   case OPCODE_IS_ZERO_INT:
502     MO.setImm(OPCODE_IS_NOT_ZERO_INT);
503     break;
504   case OPCODE_IS_NOT_ZERO_INT:
505     MO.setImm(OPCODE_IS_ZERO_INT);
506     break;
507   case OPCODE_IS_ZERO:
508     MO.setImm(OPCODE_IS_NOT_ZERO);
509     break;
510   case OPCODE_IS_NOT_ZERO:
511     MO.setImm(OPCODE_IS_ZERO);
512     break;
513   default:
514     return true;
515   }
516
517   MachineOperand &MO2 = Cond[2];
518   switch (MO2.getReg()) {
519   case AMDGPU::PRED_SEL_ZERO:
520     MO2.setReg(AMDGPU::PRED_SEL_ONE);
521     break;
522   case AMDGPU::PRED_SEL_ONE:
523     MO2.setReg(AMDGPU::PRED_SEL_ZERO);
524     break;
525   default:
526     return true;
527   }
528   return false;
529 }
530
531 bool
532 R600InstrInfo::DefinesPredicate(MachineInstr *MI,
533                                 std::vector<MachineOperand> &Pred) const {
534   return isPredicateSetter(MI->getOpcode());
535 }
536
537
538 bool
539 R600InstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
540                        const SmallVectorImpl<MachineOperand> &Pred2) const {
541   return false;
542 }
543
544
545 bool
546 R600InstrInfo::PredicateInstruction(MachineInstr *MI,
547                       const SmallVectorImpl<MachineOperand> &Pred) const {
548   int PIdx = MI->findFirstPredOperandIdx();
549
550   if (PIdx != -1) {
551     MachineOperand &PMO = MI->getOperand(PIdx);
552     PMO.setReg(Pred[2].getReg());
553     MachineInstrBuilder MIB(*MI->getParent()->getParent(), MI);
554     MIB.addReg(AMDGPU::PREDICATE_BIT, RegState::Implicit);
555     return true;
556   }
557
558   return false;
559 }
560
561 unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
562                                             const MachineInstr *MI,
563                                             unsigned *PredCost) const {
564   if (PredCost)
565     *PredCost = 2;
566   return 2;
567 }
568
569 int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
570   const MachineRegisterInfo &MRI = MF.getRegInfo();
571   const MachineFrameInfo *MFI = MF.getFrameInfo();
572   int Offset = 0;
573
574   if (MFI->getNumObjects() == 0) {
575     return -1;
576   }
577
578   if (MRI.livein_empty()) {
579     return 0;
580   }
581
582   for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
583                                             LE = MRI.livein_end();
584                                             LI != LE; ++LI) {
585     Offset = std::max(Offset,
586                       GET_REG_INDEX(RI.getEncodingValue(LI->first)));
587   }
588
589   return Offset + 1;
590 }
591
592 int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
593   int Offset = 0;
594   const MachineFrameInfo *MFI = MF.getFrameInfo();
595
596   // Variable sized objects are not supported
597   assert(!MFI->hasVarSizedObjects());
598
599   if (MFI->getNumObjects() == 0) {
600     return -1;
601   }
602
603   Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1);
604
605   return getIndirectIndexBegin(MF) + Offset;
606 }
607
608 std::vector<unsigned> R600InstrInfo::getIndirectReservedRegs(
609                                              const MachineFunction &MF) const {
610   const AMDGPUFrameLowering *TFL =
611                  static_cast<const AMDGPUFrameLowering*>(TM.getFrameLowering());
612   std::vector<unsigned> Regs;
613
614   unsigned StackWidth = TFL->getStackWidth(MF);
615   int End = getIndirectIndexEnd(MF);
616
617   if (End == -1) {
618     return Regs;
619   }
620
621   for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
622     unsigned SuperReg = AMDGPU::R600_Reg128RegClass.getRegister(Index);
623     Regs.push_back(SuperReg);
624     for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
625       unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
626       Regs.push_back(Reg);
627     }
628   }
629   return Regs;
630 }
631
632 unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
633                                                  unsigned Channel) const {
634   // XXX: Remove when we support a stack width > 2
635   assert(Channel == 0);
636   return RegIndex;
637 }
638
639 const TargetRegisterClass * R600InstrInfo::getIndirectAddrStoreRegClass(
640                                                      unsigned SourceReg) const {
641   return &AMDGPU::R600_TReg32RegClass;
642 }
643
644 const TargetRegisterClass *R600InstrInfo::getIndirectAddrLoadRegClass() const {
645   return &AMDGPU::TRegMemRegClass;
646 }
647
648 MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
649                                        MachineBasicBlock::iterator I,
650                                        unsigned ValueReg, unsigned Address,
651                                        unsigned OffsetReg) const {
652   unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
653   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
654                                                AMDGPU::AR_X, OffsetReg);
655   setImmOperand(MOVA, R600Operands::WRITE, 0);
656
657   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
658                                       AddrReg, ValueReg)
659                                       .addReg(AMDGPU::AR_X, RegState::Implicit);
660   setImmOperand(Mov, R600Operands::DST_REL, 1);
661   return Mov;
662 }
663
664 MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
665                                        MachineBasicBlock::iterator I,
666                                        unsigned ValueReg, unsigned Address,
667                                        unsigned OffsetReg) const {
668   unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
669   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
670                                                        AMDGPU::AR_X,
671                                                        OffsetReg);
672   setImmOperand(MOVA, R600Operands::WRITE, 0);
673   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
674                                       ValueReg,
675                                       AddrReg)
676                                       .addReg(AMDGPU::AR_X, RegState::Implicit);
677   setImmOperand(Mov, R600Operands::SRC0_REL, 1);
678
679   return Mov;
680 }
681
682 const TargetRegisterClass *R600InstrInfo::getSuperIndirectRegClass() const {
683   return &AMDGPU::IndirectRegRegClass;
684 }
685
686 unsigned R600InstrInfo::getMaxAlusPerClause() const {
687   return 115;
688 }
689
690 MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
691                                                   MachineBasicBlock::iterator I,
692                                                   unsigned Opcode,
693                                                   unsigned DstReg,
694                                                   unsigned Src0Reg,
695                                                   unsigned Src1Reg) const {
696   MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
697     DstReg);           // $dst
698
699   if (Src1Reg) {
700     MIB.addImm(0)     // $update_exec_mask
701        .addImm(0);    // $update_predicate
702   }
703   MIB.addImm(1)        // $write
704      .addImm(0)        // $omod
705      .addImm(0)        // $dst_rel
706      .addImm(0)        // $dst_clamp
707      .addReg(Src0Reg)  // $src0
708      .addImm(0)        // $src0_neg
709      .addImm(0)        // $src0_rel
710      .addImm(0)        // $src0_abs
711      .addImm(-1);       // $src0_sel
712
713   if (Src1Reg) {
714     MIB.addReg(Src1Reg) // $src1
715        .addImm(0)       // $src1_neg
716        .addImm(0)       // $src1_rel
717        .addImm(0)       // $src1_abs
718        .addImm(-1);      // $src1_sel
719   }
720
721   //XXX: The r600g finalizer expects this to be 1, once we've moved the
722   //scheduling to the backend, we can change the default to 0.
723   MIB.addImm(1)        // $last
724       .addReg(AMDGPU::PRED_SEL_OFF) // $pred_sel
725       .addImm(0)         // $literal
726       .addImm(0);        // $bank_swizzle
727
728   return MIB;
729 }
730
731 MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
732                                          MachineBasicBlock::iterator I,
733                                          unsigned DstReg,
734                                          uint64_t Imm) const {
735   MachineInstr *MovImm = buildDefaultInstruction(BB, I, AMDGPU::MOV, DstReg,
736                                                   AMDGPU::ALU_LITERAL_X);
737   setImmOperand(MovImm, R600Operands::IMM, Imm);
738   return MovImm;
739 }
740
741 int R600InstrInfo::getOperandIdx(const MachineInstr &MI,
742                                  R600Operands::Ops Op) const {
743   return getOperandIdx(MI.getOpcode(), Op);
744 }
745
746 int R600InstrInfo::getOperandIdx(unsigned Opcode,
747                                  R600Operands::Ops Op) const {
748   unsigned TargetFlags = get(Opcode).TSFlags;
749   unsigned OpTableIdx;
750
751   if (!HAS_NATIVE_OPERANDS(TargetFlags)) {
752     switch (Op) {
753     case R600Operands::DST: return 0;
754     case R600Operands::SRC0: return 1;
755     case R600Operands::SRC1: return 2;
756     case R600Operands::SRC2: return 3;
757     default:
758       assert(!"Unknown operand type for instruction");
759       return -1;
760     }
761   }
762
763   if (TargetFlags & R600_InstFlag::OP1) {
764     OpTableIdx = 0;
765   } else if (TargetFlags & R600_InstFlag::OP2) {
766     OpTableIdx = 1;
767   } else {
768     assert((TargetFlags & R600_InstFlag::OP3) && "OP1, OP2, or OP3 not defined "
769                                                  "for this instruction");
770     OpTableIdx = 2;
771   }
772
773   return R600Operands::ALUOpTable[OpTableIdx][Op];
774 }
775
776 void R600InstrInfo::setImmOperand(MachineInstr *MI, R600Operands::Ops Op,
777                                   int64_t Imm) const {
778   int Idx = getOperandIdx(*MI, Op);
779   assert(Idx != -1 && "Operand not supported for this instruction.");
780   assert(MI->getOperand(Idx).isImm());
781   MI->getOperand(Idx).setImm(Imm);
782 }
783
784 //===----------------------------------------------------------------------===//
785 // Instruction flag getters/setters
786 //===----------------------------------------------------------------------===//
787
788 bool R600InstrInfo::hasFlagOperand(const MachineInstr &MI) const {
789   return GET_FLAG_OPERAND_IDX(get(MI.getOpcode()).TSFlags) != 0;
790 }
791
792 MachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI, unsigned SrcIdx,
793                                          unsigned Flag) const {
794   unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
795   int FlagIndex = 0;
796   if (Flag != 0) {
797     // If we pass something other than the default value of Flag to this
798     // function, it means we are want to set a flag on an instruction
799     // that uses native encoding.
800     assert(HAS_NATIVE_OPERANDS(TargetFlags));
801     bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
802     switch (Flag) {
803     case MO_FLAG_CLAMP:
804       FlagIndex = getOperandIdx(*MI, R600Operands::CLAMP);
805       break;
806     case MO_FLAG_MASK:
807       FlagIndex = getOperandIdx(*MI, R600Operands::WRITE);
808       break;
809     case MO_FLAG_NOT_LAST:
810     case MO_FLAG_LAST:
811       FlagIndex = getOperandIdx(*MI, R600Operands::LAST);
812       break;
813     case MO_FLAG_NEG:
814       switch (SrcIdx) {
815       case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_NEG); break;
816       case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_NEG); break;
817       case 2: FlagIndex = getOperandIdx(*MI, R600Operands::SRC2_NEG); break;
818       }
819       break;
820
821     case MO_FLAG_ABS:
822       assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
823                        "instructions.");
824       (void)IsOP3;
825       switch (SrcIdx) {
826       case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_ABS); break;
827       case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_ABS); break;
828       }
829       break;
830
831     default:
832       FlagIndex = -1;
833       break;
834     }
835     assert(FlagIndex != -1 && "Flag not supported for this instruction");
836   } else {
837       FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
838       assert(FlagIndex != 0 &&
839          "Instruction flags not supported for this instruction");
840   }
841
842   MachineOperand &FlagOp = MI->getOperand(FlagIndex);
843   assert(FlagOp.isImm());
844   return FlagOp;
845 }
846
847 void R600InstrInfo::addFlag(MachineInstr *MI, unsigned Operand,
848                             unsigned Flag) const {
849   unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
850   if (Flag == 0) {
851     return;
852   }
853   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
854     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
855     if (Flag == MO_FLAG_NOT_LAST) {
856       clearFlag(MI, Operand, MO_FLAG_LAST);
857     } else if (Flag == MO_FLAG_MASK) {
858       clearFlag(MI, Operand, Flag);
859     } else {
860       FlagOp.setImm(1);
861     }
862   } else {
863       MachineOperand &FlagOp = getFlagOp(MI, Operand);
864       FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
865   }
866 }
867
868 void R600InstrInfo::clearFlag(MachineInstr *MI, unsigned Operand,
869                               unsigned Flag) const {
870   unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
871   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
872     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
873     FlagOp.setImm(0);
874   } else {
875     MachineOperand &FlagOp = getFlagOp(MI);
876     unsigned InstFlags = FlagOp.getImm();
877     InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
878     FlagOp.setImm(InstFlags);
879   }
880 }