xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600InstrInfo.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
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 /// R600 Implementation of TargetInstrInfo.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #include "R600InstrInfo.h"
15*0b57cec5SDimitry Andric #include "AMDGPU.h"
16*0b57cec5SDimitry Andric #include "AMDGPUInstrInfo.h"
17*0b57cec5SDimitry Andric #include "AMDGPUSubtarget.h"
18*0b57cec5SDimitry Andric #include "R600Defines.h"
19*0b57cec5SDimitry Andric #include "R600FrameLowering.h"
20*0b57cec5SDimitry Andric #include "R600RegisterInfo.h"
21*0b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
22*0b57cec5SDimitry Andric #include "Utils/AMDGPUBaseInfo.h"
23*0b57cec5SDimitry Andric #include "llvm/ADT/BitVector.h"
24*0b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
25*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
26*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
27*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
28*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
29*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
30*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
31*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
32*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
33*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
34*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
35*0b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
36*0b57cec5SDimitry Andric #include <algorithm>
37*0b57cec5SDimitry Andric #include <cassert>
38*0b57cec5SDimitry Andric #include <cstdint>
39*0b57cec5SDimitry Andric #include <cstring>
40*0b57cec5SDimitry Andric #include <iterator>
41*0b57cec5SDimitry Andric #include <utility>
42*0b57cec5SDimitry Andric #include <vector>
43*0b57cec5SDimitry Andric 
44*0b57cec5SDimitry Andric using namespace llvm;
45*0b57cec5SDimitry Andric 
46*0b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
47*0b57cec5SDimitry Andric #include "R600GenDFAPacketizer.inc"
48*0b57cec5SDimitry Andric 
49*0b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
50*0b57cec5SDimitry Andric #define GET_INSTRMAP_INFO
51*0b57cec5SDimitry Andric #define GET_INSTRINFO_NAMED_OPS
52*0b57cec5SDimitry Andric #include "R600GenInstrInfo.inc"
53*0b57cec5SDimitry Andric 
54*0b57cec5SDimitry Andric R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)
55*0b57cec5SDimitry Andric   : R600GenInstrInfo(-1, -1), RI(), ST(ST) {}
56*0b57cec5SDimitry Andric 
57*0b57cec5SDimitry Andric bool R600InstrInfo::isVector(const MachineInstr &MI) const {
58*0b57cec5SDimitry Andric   return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
59*0b57cec5SDimitry Andric }
60*0b57cec5SDimitry Andric 
61*0b57cec5SDimitry Andric void R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
62*0b57cec5SDimitry Andric                                 MachineBasicBlock::iterator MI,
63*0b57cec5SDimitry Andric                                 const DebugLoc &DL, unsigned DestReg,
64*0b57cec5SDimitry Andric                                 unsigned SrcReg, bool KillSrc) const {
65*0b57cec5SDimitry Andric   unsigned VectorComponents = 0;
66*0b57cec5SDimitry Andric   if ((R600::R600_Reg128RegClass.contains(DestReg) ||
67*0b57cec5SDimitry Andric       R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&
68*0b57cec5SDimitry Andric       (R600::R600_Reg128RegClass.contains(SrcReg) ||
69*0b57cec5SDimitry Andric        R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {
70*0b57cec5SDimitry Andric     VectorComponents = 4;
71*0b57cec5SDimitry Andric   } else if((R600::R600_Reg64RegClass.contains(DestReg) ||
72*0b57cec5SDimitry Andric             R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&
73*0b57cec5SDimitry Andric             (R600::R600_Reg64RegClass.contains(SrcReg) ||
74*0b57cec5SDimitry Andric              R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {
75*0b57cec5SDimitry Andric     VectorComponents = 2;
76*0b57cec5SDimitry Andric   }
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric   if (VectorComponents > 0) {
79*0b57cec5SDimitry Andric     for (unsigned I = 0; I < VectorComponents; I++) {
80*0b57cec5SDimitry Andric       unsigned SubRegIndex = AMDGPURegisterInfo::getSubRegFromChannel(I);
81*0b57cec5SDimitry Andric       buildDefaultInstruction(MBB, MI, R600::MOV,
82*0b57cec5SDimitry Andric                               RI.getSubReg(DestReg, SubRegIndex),
83*0b57cec5SDimitry Andric                               RI.getSubReg(SrcReg, SubRegIndex))
84*0b57cec5SDimitry Andric                               .addReg(DestReg,
85*0b57cec5SDimitry Andric                                       RegState::Define | RegState::Implicit);
86*0b57cec5SDimitry Andric     }
87*0b57cec5SDimitry Andric   } else {
88*0b57cec5SDimitry Andric     MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, R600::MOV,
89*0b57cec5SDimitry Andric                                                   DestReg, SrcReg);
90*0b57cec5SDimitry Andric     NewMI->getOperand(getOperandIdx(*NewMI, R600::OpName::src0))
91*0b57cec5SDimitry Andric                                     .setIsKill(KillSrc);
92*0b57cec5SDimitry Andric   }
93*0b57cec5SDimitry Andric }
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric /// \returns true if \p MBBI can be moved into a new basic.
96*0b57cec5SDimitry Andric bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
97*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator MBBI) const {
98*0b57cec5SDimitry Andric   for (MachineInstr::const_mop_iterator I = MBBI->operands_begin(),
99*0b57cec5SDimitry Andric                                         E = MBBI->operands_end(); I != E; ++I) {
100*0b57cec5SDimitry Andric     if (I->isReg() && !TargetRegisterInfo::isVirtualRegister(I->getReg()) &&
101*0b57cec5SDimitry Andric         I->isUse() && RI.isPhysRegLiveAcrossClauses(I->getReg()))
102*0b57cec5SDimitry Andric       return false;
103*0b57cec5SDimitry Andric   }
104*0b57cec5SDimitry Andric   return true;
105*0b57cec5SDimitry Andric }
106*0b57cec5SDimitry Andric 
107*0b57cec5SDimitry Andric bool R600InstrInfo::isMov(unsigned Opcode) const {
108*0b57cec5SDimitry Andric   switch(Opcode) {
109*0b57cec5SDimitry Andric   default:
110*0b57cec5SDimitry Andric     return false;
111*0b57cec5SDimitry Andric   case R600::MOV:
112*0b57cec5SDimitry Andric   case R600::MOV_IMM_F32:
113*0b57cec5SDimitry Andric   case R600::MOV_IMM_I32:
114*0b57cec5SDimitry Andric     return true;
115*0b57cec5SDimitry Andric   }
116*0b57cec5SDimitry Andric }
117*0b57cec5SDimitry Andric 
118*0b57cec5SDimitry Andric bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
119*0b57cec5SDimitry Andric   return false;
120*0b57cec5SDimitry Andric }
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric bool R600InstrInfo::isCubeOp(unsigned Opcode) const {
123*0b57cec5SDimitry Andric   switch(Opcode) {
124*0b57cec5SDimitry Andric     default: return false;
125*0b57cec5SDimitry Andric     case R600::CUBE_r600_pseudo:
126*0b57cec5SDimitry Andric     case R600::CUBE_r600_real:
127*0b57cec5SDimitry Andric     case R600::CUBE_eg_pseudo:
128*0b57cec5SDimitry Andric     case R600::CUBE_eg_real:
129*0b57cec5SDimitry Andric       return true;
130*0b57cec5SDimitry Andric   }
131*0b57cec5SDimitry Andric }
132*0b57cec5SDimitry Andric 
133*0b57cec5SDimitry Andric bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
134*0b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric   return (TargetFlags & R600_InstFlag::ALU_INST);
137*0b57cec5SDimitry Andric }
138*0b57cec5SDimitry Andric 
139*0b57cec5SDimitry Andric bool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {
140*0b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric   return ((TargetFlags & R600_InstFlag::OP1) |
143*0b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::OP2) |
144*0b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::OP3));
145*0b57cec5SDimitry Andric }
146*0b57cec5SDimitry Andric 
147*0b57cec5SDimitry Andric bool R600InstrInfo::isLDSInstr(unsigned Opcode) const {
148*0b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric   return ((TargetFlags & R600_InstFlag::LDS_1A) |
151*0b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::LDS_1A1D) |
152*0b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::LDS_1A2D));
153*0b57cec5SDimitry Andric }
154*0b57cec5SDimitry Andric 
155*0b57cec5SDimitry Andric bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {
156*0b57cec5SDimitry Andric   return isLDSInstr(Opcode) && getOperandIdx(Opcode, R600::OpName::dst) != -1;
157*0b57cec5SDimitry Andric }
158*0b57cec5SDimitry Andric 
159*0b57cec5SDimitry Andric bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {
160*0b57cec5SDimitry Andric   if (isALUInstr(MI.getOpcode()))
161*0b57cec5SDimitry Andric     return true;
162*0b57cec5SDimitry Andric   if (isVector(MI) || isCubeOp(MI.getOpcode()))
163*0b57cec5SDimitry Andric     return true;
164*0b57cec5SDimitry Andric   switch (MI.getOpcode()) {
165*0b57cec5SDimitry Andric   case R600::PRED_X:
166*0b57cec5SDimitry Andric   case R600::INTERP_PAIR_XY:
167*0b57cec5SDimitry Andric   case R600::INTERP_PAIR_ZW:
168*0b57cec5SDimitry Andric   case R600::INTERP_VEC_LOAD:
169*0b57cec5SDimitry Andric   case R600::COPY:
170*0b57cec5SDimitry Andric   case R600::DOT_4:
171*0b57cec5SDimitry Andric     return true;
172*0b57cec5SDimitry Andric   default:
173*0b57cec5SDimitry Andric     return false;
174*0b57cec5SDimitry Andric   }
175*0b57cec5SDimitry Andric }
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
178*0b57cec5SDimitry Andric   if (ST.hasCaymanISA())
179*0b57cec5SDimitry Andric     return false;
180*0b57cec5SDimitry Andric   return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
181*0b57cec5SDimitry Andric }
182*0b57cec5SDimitry Andric 
183*0b57cec5SDimitry Andric bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {
184*0b57cec5SDimitry Andric   return isTransOnly(MI.getOpcode());
185*0b57cec5SDimitry Andric }
186*0b57cec5SDimitry Andric 
187*0b57cec5SDimitry Andric bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {
188*0b57cec5SDimitry Andric   return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
189*0b57cec5SDimitry Andric }
190*0b57cec5SDimitry Andric 
191*0b57cec5SDimitry Andric bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {
192*0b57cec5SDimitry Andric   return isVectorOnly(MI.getOpcode());
193*0b57cec5SDimitry Andric }
194*0b57cec5SDimitry Andric 
195*0b57cec5SDimitry Andric bool R600InstrInfo::isExport(unsigned Opcode) const {
196*0b57cec5SDimitry Andric   return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);
197*0b57cec5SDimitry Andric }
198*0b57cec5SDimitry Andric 
199*0b57cec5SDimitry Andric bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
200*0b57cec5SDimitry Andric   return ST.hasVertexCache() && IS_VTX(get(Opcode));
201*0b57cec5SDimitry Andric }
202*0b57cec5SDimitry Andric 
203*0b57cec5SDimitry Andric bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {
204*0b57cec5SDimitry Andric   const MachineFunction *MF = MI.getParent()->getParent();
205*0b57cec5SDimitry Andric   return !AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
206*0b57cec5SDimitry Andric          usesVertexCache(MI.getOpcode());
207*0b57cec5SDimitry Andric }
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
210*0b57cec5SDimitry Andric   return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
211*0b57cec5SDimitry Andric }
212*0b57cec5SDimitry Andric 
213*0b57cec5SDimitry Andric bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {
214*0b57cec5SDimitry Andric   const MachineFunction *MF = MI.getParent()->getParent();
215*0b57cec5SDimitry Andric   return (AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
216*0b57cec5SDimitry Andric           usesVertexCache(MI.getOpcode())) ||
217*0b57cec5SDimitry Andric           usesTextureCache(MI.getOpcode());
218*0b57cec5SDimitry Andric }
219*0b57cec5SDimitry Andric 
220*0b57cec5SDimitry Andric bool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {
221*0b57cec5SDimitry Andric   switch (Opcode) {
222*0b57cec5SDimitry Andric   case R600::KILLGT:
223*0b57cec5SDimitry Andric   case R600::GROUP_BARRIER:
224*0b57cec5SDimitry Andric     return true;
225*0b57cec5SDimitry Andric   default:
226*0b57cec5SDimitry Andric     return false;
227*0b57cec5SDimitry Andric   }
228*0b57cec5SDimitry Andric }
229*0b57cec5SDimitry Andric 
230*0b57cec5SDimitry Andric bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {
231*0b57cec5SDimitry Andric   return MI.findRegisterUseOperandIdx(R600::AR_X, false, &RI) != -1;
232*0b57cec5SDimitry Andric }
233*0b57cec5SDimitry Andric 
234*0b57cec5SDimitry Andric bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {
235*0b57cec5SDimitry Andric   return MI.findRegisterDefOperandIdx(R600::AR_X, false, false, &RI) != -1;
236*0b57cec5SDimitry Andric }
237*0b57cec5SDimitry Andric 
238*0b57cec5SDimitry Andric bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {
239*0b57cec5SDimitry Andric   if (!isALUInstr(MI.getOpcode())) {
240*0b57cec5SDimitry Andric     return false;
241*0b57cec5SDimitry Andric   }
242*0b57cec5SDimitry Andric   for (MachineInstr::const_mop_iterator I = MI.operands_begin(),
243*0b57cec5SDimitry Andric                                         E = MI.operands_end();
244*0b57cec5SDimitry Andric        I != E; ++I) {
245*0b57cec5SDimitry Andric     if (!I->isReg() || !I->isUse() ||
246*0b57cec5SDimitry Andric         TargetRegisterInfo::isVirtualRegister(I->getReg()))
247*0b57cec5SDimitry Andric       continue;
248*0b57cec5SDimitry Andric 
249*0b57cec5SDimitry Andric     if (R600::R600_LDS_SRC_REGRegClass.contains(I->getReg()))
250*0b57cec5SDimitry Andric       return true;
251*0b57cec5SDimitry Andric   }
252*0b57cec5SDimitry Andric   return false;
253*0b57cec5SDimitry Andric }
254*0b57cec5SDimitry Andric 
255*0b57cec5SDimitry Andric int R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {
256*0b57cec5SDimitry Andric   static const unsigned SrcSelTable[][2] = {
257*0b57cec5SDimitry Andric     {R600::OpName::src0, R600::OpName::src0_sel},
258*0b57cec5SDimitry Andric     {R600::OpName::src1, R600::OpName::src1_sel},
259*0b57cec5SDimitry Andric     {R600::OpName::src2, R600::OpName::src2_sel},
260*0b57cec5SDimitry Andric     {R600::OpName::src0_X, R600::OpName::src0_sel_X},
261*0b57cec5SDimitry Andric     {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
262*0b57cec5SDimitry Andric     {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
263*0b57cec5SDimitry Andric     {R600::OpName::src0_W, R600::OpName::src0_sel_W},
264*0b57cec5SDimitry Andric     {R600::OpName::src1_X, R600::OpName::src1_sel_X},
265*0b57cec5SDimitry Andric     {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
266*0b57cec5SDimitry Andric     {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
267*0b57cec5SDimitry Andric     {R600::OpName::src1_W, R600::OpName::src1_sel_W}
268*0b57cec5SDimitry Andric   };
269*0b57cec5SDimitry Andric 
270*0b57cec5SDimitry Andric   for (const auto &Row : SrcSelTable) {
271*0b57cec5SDimitry Andric     if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
272*0b57cec5SDimitry Andric       return getOperandIdx(Opcode, Row[1]);
273*0b57cec5SDimitry Andric     }
274*0b57cec5SDimitry Andric   }
275*0b57cec5SDimitry Andric   return -1;
276*0b57cec5SDimitry Andric }
277*0b57cec5SDimitry Andric 
278*0b57cec5SDimitry Andric SmallVector<std::pair<MachineOperand *, int64_t>, 3>
279*0b57cec5SDimitry Andric R600InstrInfo::getSrcs(MachineInstr &MI) const {
280*0b57cec5SDimitry Andric   SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
281*0b57cec5SDimitry Andric 
282*0b57cec5SDimitry Andric   if (MI.getOpcode() == R600::DOT_4) {
283*0b57cec5SDimitry Andric     static const unsigned OpTable[8][2] = {
284*0b57cec5SDimitry Andric       {R600::OpName::src0_X, R600::OpName::src0_sel_X},
285*0b57cec5SDimitry Andric       {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
286*0b57cec5SDimitry Andric       {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
287*0b57cec5SDimitry Andric       {R600::OpName::src0_W, R600::OpName::src0_sel_W},
288*0b57cec5SDimitry Andric       {R600::OpName::src1_X, R600::OpName::src1_sel_X},
289*0b57cec5SDimitry Andric       {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
290*0b57cec5SDimitry Andric       {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
291*0b57cec5SDimitry Andric       {R600::OpName::src1_W, R600::OpName::src1_sel_W},
292*0b57cec5SDimitry Andric     };
293*0b57cec5SDimitry Andric 
294*0b57cec5SDimitry Andric     for (unsigned j = 0; j < 8; j++) {
295*0b57cec5SDimitry Andric       MachineOperand &MO =
296*0b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][0]));
297*0b57cec5SDimitry Andric       unsigned Reg = MO.getReg();
298*0b57cec5SDimitry Andric       if (Reg == R600::ALU_CONST) {
299*0b57cec5SDimitry Andric         MachineOperand &Sel =
300*0b57cec5SDimitry Andric             MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
301*0b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Sel.getImm()));
302*0b57cec5SDimitry Andric         continue;
303*0b57cec5SDimitry Andric       }
304*0b57cec5SDimitry Andric 
305*0b57cec5SDimitry Andric     }
306*0b57cec5SDimitry Andric     return Result;
307*0b57cec5SDimitry Andric   }
308*0b57cec5SDimitry Andric 
309*0b57cec5SDimitry Andric   static const unsigned OpTable[3][2] = {
310*0b57cec5SDimitry Andric     {R600::OpName::src0, R600::OpName::src0_sel},
311*0b57cec5SDimitry Andric     {R600::OpName::src1, R600::OpName::src1_sel},
312*0b57cec5SDimitry Andric     {R600::OpName::src2, R600::OpName::src2_sel},
313*0b57cec5SDimitry Andric   };
314*0b57cec5SDimitry Andric 
315*0b57cec5SDimitry Andric   for (unsigned j = 0; j < 3; j++) {
316*0b57cec5SDimitry Andric     int SrcIdx = getOperandIdx(MI.getOpcode(), OpTable[j][0]);
317*0b57cec5SDimitry Andric     if (SrcIdx < 0)
318*0b57cec5SDimitry Andric       break;
319*0b57cec5SDimitry Andric     MachineOperand &MO = MI.getOperand(SrcIdx);
320*0b57cec5SDimitry Andric     unsigned Reg = MO.getReg();
321*0b57cec5SDimitry Andric     if (Reg == R600::ALU_CONST) {
322*0b57cec5SDimitry Andric       MachineOperand &Sel =
323*0b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
324*0b57cec5SDimitry Andric       Result.push_back(std::make_pair(&MO, Sel.getImm()));
325*0b57cec5SDimitry Andric       continue;
326*0b57cec5SDimitry Andric     }
327*0b57cec5SDimitry Andric     if (Reg == R600::ALU_LITERAL_X) {
328*0b57cec5SDimitry Andric       MachineOperand &Operand =
329*0b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
330*0b57cec5SDimitry Andric       if (Operand.isImm()) {
331*0b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Operand.getImm()));
332*0b57cec5SDimitry Andric         continue;
333*0b57cec5SDimitry Andric       }
334*0b57cec5SDimitry Andric       assert(Operand.isGlobal());
335*0b57cec5SDimitry Andric     }
336*0b57cec5SDimitry Andric     Result.push_back(std::make_pair(&MO, 0));
337*0b57cec5SDimitry Andric   }
338*0b57cec5SDimitry Andric   return Result;
339*0b57cec5SDimitry Andric }
340*0b57cec5SDimitry Andric 
341*0b57cec5SDimitry Andric std::vector<std::pair<int, unsigned>>
342*0b57cec5SDimitry Andric R600InstrInfo::ExtractSrcs(MachineInstr &MI,
343*0b57cec5SDimitry Andric                            const DenseMap<unsigned, unsigned> &PV,
344*0b57cec5SDimitry Andric                            unsigned &ConstCount) const {
345*0b57cec5SDimitry Andric   ConstCount = 0;
346*0b57cec5SDimitry Andric   const std::pair<int, unsigned> DummyPair(-1, 0);
347*0b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> Result;
348*0b57cec5SDimitry Andric   unsigned i = 0;
349*0b57cec5SDimitry Andric   for (const auto &Src : getSrcs(MI)) {
350*0b57cec5SDimitry Andric     ++i;
351*0b57cec5SDimitry Andric     unsigned Reg = Src.first->getReg();
352*0b57cec5SDimitry Andric     int Index = RI.getEncodingValue(Reg) & 0xff;
353*0b57cec5SDimitry Andric     if (Reg == R600::OQAP) {
354*0b57cec5SDimitry Andric       Result.push_back(std::make_pair(Index, 0U));
355*0b57cec5SDimitry Andric     }
356*0b57cec5SDimitry Andric     if (PV.find(Reg) != PV.end()) {
357*0b57cec5SDimitry Andric       // 255 is used to tells its a PS/PV reg
358*0b57cec5SDimitry Andric       Result.push_back(std::make_pair(255, 0U));
359*0b57cec5SDimitry Andric       continue;
360*0b57cec5SDimitry Andric     }
361*0b57cec5SDimitry Andric     if (Index > 127) {
362*0b57cec5SDimitry Andric       ConstCount++;
363*0b57cec5SDimitry Andric       Result.push_back(DummyPair);
364*0b57cec5SDimitry Andric       continue;
365*0b57cec5SDimitry Andric     }
366*0b57cec5SDimitry Andric     unsigned Chan = RI.getHWRegChan(Reg);
367*0b57cec5SDimitry Andric     Result.push_back(std::make_pair(Index, Chan));
368*0b57cec5SDimitry Andric   }
369*0b57cec5SDimitry Andric   for (; i < 3; ++i)
370*0b57cec5SDimitry Andric     Result.push_back(DummyPair);
371*0b57cec5SDimitry Andric   return Result;
372*0b57cec5SDimitry Andric }
373*0b57cec5SDimitry Andric 
374*0b57cec5SDimitry Andric static std::vector<std::pair<int, unsigned>>
375*0b57cec5SDimitry Andric Swizzle(std::vector<std::pair<int, unsigned>> Src,
376*0b57cec5SDimitry Andric         R600InstrInfo::BankSwizzle Swz) {
377*0b57cec5SDimitry Andric   if (Src[0] == Src[1])
378*0b57cec5SDimitry Andric     Src[1].first = -1;
379*0b57cec5SDimitry Andric   switch (Swz) {
380*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210:
381*0b57cec5SDimitry Andric     break;
382*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122:
383*0b57cec5SDimitry Andric     std::swap(Src[1], Src[2]);
384*0b57cec5SDimitry Andric     break;
385*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221:
386*0b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
387*0b57cec5SDimitry Andric     break;
388*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212:
389*0b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
390*0b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
391*0b57cec5SDimitry Andric     break;
392*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_201:
393*0b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
394*0b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
395*0b57cec5SDimitry Andric     break;
396*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_210:
397*0b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
398*0b57cec5SDimitry Andric     break;
399*0b57cec5SDimitry Andric   }
400*0b57cec5SDimitry Andric   return Src;
401*0b57cec5SDimitry Andric }
402*0b57cec5SDimitry Andric 
403*0b57cec5SDimitry Andric static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
404*0b57cec5SDimitry Andric   assert(Op < 3 && "Out of range swizzle index");
405*0b57cec5SDimitry Andric   switch (Swz) {
406*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210: {
407*0b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 0};
408*0b57cec5SDimitry Andric     return Cycles[Op];
409*0b57cec5SDimitry Andric   }
410*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122: {
411*0b57cec5SDimitry Andric     unsigned Cycles[3] = { 1, 2, 2};
412*0b57cec5SDimitry Andric     return Cycles[Op];
413*0b57cec5SDimitry Andric   }
414*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212: {
415*0b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 2};
416*0b57cec5SDimitry Andric     return Cycles[Op];
417*0b57cec5SDimitry Andric   }
418*0b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221: {
419*0b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 2, 1};
420*0b57cec5SDimitry Andric     return Cycles[Op];
421*0b57cec5SDimitry Andric   }
422*0b57cec5SDimitry Andric   default:
423*0b57cec5SDimitry Andric     llvm_unreachable("Wrong Swizzle for Trans Slot");
424*0b57cec5SDimitry Andric   }
425*0b57cec5SDimitry Andric }
426*0b57cec5SDimitry Andric 
427*0b57cec5SDimitry Andric /// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
428*0b57cec5SDimitry Andric /// in the same Instruction Group while meeting read port limitations given a
429*0b57cec5SDimitry Andric /// Swz swizzle sequence.
430*0b57cec5SDimitry Andric unsigned  R600InstrInfo::isLegalUpTo(
431*0b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
432*0b57cec5SDimitry Andric     const std::vector<R600InstrInfo::BankSwizzle> &Swz,
433*0b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
434*0b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
435*0b57cec5SDimitry Andric   int Vector[4][3];
436*0b57cec5SDimitry Andric   memset(Vector, -1, sizeof(Vector));
437*0b57cec5SDimitry Andric   for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
438*0b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &Srcs =
439*0b57cec5SDimitry Andric         Swizzle(IGSrcs[i], Swz[i]);
440*0b57cec5SDimitry Andric     for (unsigned j = 0; j < 3; j++) {
441*0b57cec5SDimitry Andric       const std::pair<int, unsigned> &Src = Srcs[j];
442*0b57cec5SDimitry Andric       if (Src.first < 0 || Src.first == 255)
443*0b57cec5SDimitry Andric         continue;
444*0b57cec5SDimitry Andric       if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
445*0b57cec5SDimitry Andric         if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
446*0b57cec5SDimitry Andric             Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
447*0b57cec5SDimitry Andric             // The value from output queue A (denoted by register OQAP) can
448*0b57cec5SDimitry Andric             // only be fetched during the first cycle.
449*0b57cec5SDimitry Andric             return false;
450*0b57cec5SDimitry Andric         }
451*0b57cec5SDimitry Andric         // OQAP does not count towards the normal read port restrictions
452*0b57cec5SDimitry Andric         continue;
453*0b57cec5SDimitry Andric       }
454*0b57cec5SDimitry Andric       if (Vector[Src.second][j] < 0)
455*0b57cec5SDimitry Andric         Vector[Src.second][j] = Src.first;
456*0b57cec5SDimitry Andric       if (Vector[Src.second][j] != Src.first)
457*0b57cec5SDimitry Andric         return i;
458*0b57cec5SDimitry Andric     }
459*0b57cec5SDimitry Andric   }
460*0b57cec5SDimitry Andric   // Now check Trans Alu
461*0b57cec5SDimitry Andric   for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
462*0b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransSrcs[i];
463*0b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
464*0b57cec5SDimitry Andric     if (Src.first < 0)
465*0b57cec5SDimitry Andric       continue;
466*0b57cec5SDimitry Andric     if (Src.first == 255)
467*0b57cec5SDimitry Andric       continue;
468*0b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] < 0)
469*0b57cec5SDimitry Andric       Vector[Src.second][Cycle] = Src.first;
470*0b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] != Src.first)
471*0b57cec5SDimitry Andric       return IGSrcs.size() - 1;
472*0b57cec5SDimitry Andric   }
473*0b57cec5SDimitry Andric   return IGSrcs.size();
474*0b57cec5SDimitry Andric }
475*0b57cec5SDimitry Andric 
476*0b57cec5SDimitry Andric /// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
477*0b57cec5SDimitry Andric /// (in lexicographic term) swizzle sequence assuming that all swizzles after
478*0b57cec5SDimitry Andric /// Idx can be skipped
479*0b57cec5SDimitry Andric static bool
480*0b57cec5SDimitry Andric NextPossibleSolution(
481*0b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
482*0b57cec5SDimitry Andric     unsigned Idx) {
483*0b57cec5SDimitry Andric   assert(Idx < SwzCandidate.size());
484*0b57cec5SDimitry Andric   int ResetIdx = Idx;
485*0b57cec5SDimitry Andric   while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
486*0b57cec5SDimitry Andric     ResetIdx --;
487*0b57cec5SDimitry Andric   for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
488*0b57cec5SDimitry Andric     SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
489*0b57cec5SDimitry Andric   }
490*0b57cec5SDimitry Andric   if (ResetIdx == -1)
491*0b57cec5SDimitry Andric     return false;
492*0b57cec5SDimitry Andric   int NextSwizzle = SwzCandidate[ResetIdx] + 1;
493*0b57cec5SDimitry Andric   SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
494*0b57cec5SDimitry Andric   return true;
495*0b57cec5SDimitry Andric }
496*0b57cec5SDimitry Andric 
497*0b57cec5SDimitry Andric /// Enumerate all possible Swizzle sequence to find one that can meet all
498*0b57cec5SDimitry Andric /// read port requirements.
499*0b57cec5SDimitry Andric bool R600InstrInfo::FindSwizzleForVectorSlot(
500*0b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
501*0b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
502*0b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
503*0b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
504*0b57cec5SDimitry Andric   unsigned ValidUpTo = 0;
505*0b57cec5SDimitry Andric   do {
506*0b57cec5SDimitry Andric     ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
507*0b57cec5SDimitry Andric     if (ValidUpTo == IGSrcs.size())
508*0b57cec5SDimitry Andric       return true;
509*0b57cec5SDimitry Andric   } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
510*0b57cec5SDimitry Andric   return false;
511*0b57cec5SDimitry Andric }
512*0b57cec5SDimitry Andric 
513*0b57cec5SDimitry Andric /// Instructions in Trans slot can't read gpr at cycle 0 if they also read
514*0b57cec5SDimitry Andric /// a const, and can't read a gpr at cycle 1 if they read 2 const.
515*0b57cec5SDimitry Andric static bool
516*0b57cec5SDimitry Andric isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
517*0b57cec5SDimitry Andric                   const std::vector<std::pair<int, unsigned>> &TransOps,
518*0b57cec5SDimitry Andric                   unsigned ConstCount) {
519*0b57cec5SDimitry Andric   // TransALU can't read 3 constants
520*0b57cec5SDimitry Andric   if (ConstCount > 2)
521*0b57cec5SDimitry Andric     return false;
522*0b57cec5SDimitry Andric   for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
523*0b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransOps[i];
524*0b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
525*0b57cec5SDimitry Andric     if (Src.first < 0)
526*0b57cec5SDimitry Andric       continue;
527*0b57cec5SDimitry Andric     if (ConstCount > 0 && Cycle == 0)
528*0b57cec5SDimitry Andric       return false;
529*0b57cec5SDimitry Andric     if (ConstCount > 1 && Cycle == 1)
530*0b57cec5SDimitry Andric       return false;
531*0b57cec5SDimitry Andric   }
532*0b57cec5SDimitry Andric   return true;
533*0b57cec5SDimitry Andric }
534*0b57cec5SDimitry Andric 
535*0b57cec5SDimitry Andric bool
536*0b57cec5SDimitry Andric R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
537*0b57cec5SDimitry Andric                                        const DenseMap<unsigned, unsigned> &PV,
538*0b57cec5SDimitry Andric                                        std::vector<BankSwizzle> &ValidSwizzle,
539*0b57cec5SDimitry Andric                                        bool isLastAluTrans)
540*0b57cec5SDimitry Andric     const {
541*0b57cec5SDimitry Andric   //Todo : support shared src0 - src1 operand
542*0b57cec5SDimitry Andric 
543*0b57cec5SDimitry Andric   std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
544*0b57cec5SDimitry Andric   ValidSwizzle.clear();
545*0b57cec5SDimitry Andric   unsigned ConstCount;
546*0b57cec5SDimitry Andric   BankSwizzle TransBS = ALU_VEC_012_SCL_210;
547*0b57cec5SDimitry Andric   for (unsigned i = 0, e = IG.size(); i < e; ++i) {
548*0b57cec5SDimitry Andric     IGSrcs.push_back(ExtractSrcs(*IG[i], PV, ConstCount));
549*0b57cec5SDimitry Andric     unsigned Op = getOperandIdx(IG[i]->getOpcode(),
550*0b57cec5SDimitry Andric         R600::OpName::bank_swizzle);
551*0b57cec5SDimitry Andric     ValidSwizzle.push_back( (R600InstrInfo::BankSwizzle)
552*0b57cec5SDimitry Andric         IG[i]->getOperand(Op).getImm());
553*0b57cec5SDimitry Andric   }
554*0b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> TransOps;
555*0b57cec5SDimitry Andric   if (!isLastAluTrans)
556*0b57cec5SDimitry Andric     return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
557*0b57cec5SDimitry Andric 
558*0b57cec5SDimitry Andric   TransOps = std::move(IGSrcs.back());
559*0b57cec5SDimitry Andric   IGSrcs.pop_back();
560*0b57cec5SDimitry Andric   ValidSwizzle.pop_back();
561*0b57cec5SDimitry Andric 
562*0b57cec5SDimitry Andric   static const R600InstrInfo::BankSwizzle TransSwz[] = {
563*0b57cec5SDimitry Andric     ALU_VEC_012_SCL_210,
564*0b57cec5SDimitry Andric     ALU_VEC_021_SCL_122,
565*0b57cec5SDimitry Andric     ALU_VEC_120_SCL_212,
566*0b57cec5SDimitry Andric     ALU_VEC_102_SCL_221
567*0b57cec5SDimitry Andric   };
568*0b57cec5SDimitry Andric   for (unsigned i = 0; i < 4; i++) {
569*0b57cec5SDimitry Andric     TransBS = TransSwz[i];
570*0b57cec5SDimitry Andric     if (!isConstCompatible(TransBS, TransOps, ConstCount))
571*0b57cec5SDimitry Andric       continue;
572*0b57cec5SDimitry Andric     bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
573*0b57cec5SDimitry Andric         TransBS);
574*0b57cec5SDimitry Andric     if (Result) {
575*0b57cec5SDimitry Andric       ValidSwizzle.push_back(TransBS);
576*0b57cec5SDimitry Andric       return true;
577*0b57cec5SDimitry Andric     }
578*0b57cec5SDimitry Andric   }
579*0b57cec5SDimitry Andric 
580*0b57cec5SDimitry Andric   return false;
581*0b57cec5SDimitry Andric }
582*0b57cec5SDimitry Andric 
583*0b57cec5SDimitry Andric bool
584*0b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
585*0b57cec5SDimitry Andric     const {
586*0b57cec5SDimitry Andric   assert (Consts.size() <= 12 && "Too many operands in instructions group");
587*0b57cec5SDimitry Andric   unsigned Pair1 = 0, Pair2 = 0;
588*0b57cec5SDimitry Andric   for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
589*0b57cec5SDimitry Andric     unsigned ReadConstHalf = Consts[i] & 2;
590*0b57cec5SDimitry Andric     unsigned ReadConstIndex = Consts[i] & (~3);
591*0b57cec5SDimitry Andric     unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
592*0b57cec5SDimitry Andric     if (!Pair1) {
593*0b57cec5SDimitry Andric       Pair1 = ReadHalfConst;
594*0b57cec5SDimitry Andric       continue;
595*0b57cec5SDimitry Andric     }
596*0b57cec5SDimitry Andric     if (Pair1 == ReadHalfConst)
597*0b57cec5SDimitry Andric       continue;
598*0b57cec5SDimitry Andric     if (!Pair2) {
599*0b57cec5SDimitry Andric       Pair2 = ReadHalfConst;
600*0b57cec5SDimitry Andric       continue;
601*0b57cec5SDimitry Andric     }
602*0b57cec5SDimitry Andric     if (Pair2 != ReadHalfConst)
603*0b57cec5SDimitry Andric       return false;
604*0b57cec5SDimitry Andric   }
605*0b57cec5SDimitry Andric   return true;
606*0b57cec5SDimitry Andric }
607*0b57cec5SDimitry Andric 
608*0b57cec5SDimitry Andric bool
609*0b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
610*0b57cec5SDimitry Andric     const {
611*0b57cec5SDimitry Andric   std::vector<unsigned> Consts;
612*0b57cec5SDimitry Andric   SmallSet<int64_t, 4> Literals;
613*0b57cec5SDimitry Andric   for (unsigned i = 0, n = MIs.size(); i < n; i++) {
614*0b57cec5SDimitry Andric     MachineInstr &MI = *MIs[i];
615*0b57cec5SDimitry Andric     if (!isALUInstr(MI.getOpcode()))
616*0b57cec5SDimitry Andric       continue;
617*0b57cec5SDimitry Andric 
618*0b57cec5SDimitry Andric     for (const auto &Src : getSrcs(MI)) {
619*0b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_LITERAL_X)
620*0b57cec5SDimitry Andric         Literals.insert(Src.second);
621*0b57cec5SDimitry Andric       if (Literals.size() > 4)
622*0b57cec5SDimitry Andric         return false;
623*0b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_CONST)
624*0b57cec5SDimitry Andric         Consts.push_back(Src.second);
625*0b57cec5SDimitry Andric       if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
626*0b57cec5SDimitry Andric           R600::R600_KC1RegClass.contains(Src.first->getReg())) {
627*0b57cec5SDimitry Andric         unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
628*0b57cec5SDimitry Andric         unsigned Chan = RI.getHWRegChan(Src.first->getReg());
629*0b57cec5SDimitry Andric         Consts.push_back((Index << 2) | Chan);
630*0b57cec5SDimitry Andric       }
631*0b57cec5SDimitry Andric     }
632*0b57cec5SDimitry Andric   }
633*0b57cec5SDimitry Andric   return fitsConstReadLimitations(Consts);
634*0b57cec5SDimitry Andric }
635*0b57cec5SDimitry Andric 
636*0b57cec5SDimitry Andric DFAPacketizer *
637*0b57cec5SDimitry Andric R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
638*0b57cec5SDimitry Andric   const InstrItineraryData *II = STI.getInstrItineraryData();
639*0b57cec5SDimitry Andric   return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
640*0b57cec5SDimitry Andric }
641*0b57cec5SDimitry Andric 
642*0b57cec5SDimitry Andric static bool
643*0b57cec5SDimitry Andric isPredicateSetter(unsigned Opcode) {
644*0b57cec5SDimitry Andric   switch (Opcode) {
645*0b57cec5SDimitry Andric   case R600::PRED_X:
646*0b57cec5SDimitry Andric     return true;
647*0b57cec5SDimitry Andric   default:
648*0b57cec5SDimitry Andric     return false;
649*0b57cec5SDimitry Andric   }
650*0b57cec5SDimitry Andric }
651*0b57cec5SDimitry Andric 
652*0b57cec5SDimitry Andric static MachineInstr *
653*0b57cec5SDimitry Andric findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
654*0b57cec5SDimitry Andric                              MachineBasicBlock::iterator I) {
655*0b57cec5SDimitry Andric   while (I != MBB.begin()) {
656*0b57cec5SDimitry Andric     --I;
657*0b57cec5SDimitry Andric     MachineInstr &MI = *I;
658*0b57cec5SDimitry Andric     if (isPredicateSetter(MI.getOpcode()))
659*0b57cec5SDimitry Andric       return &MI;
660*0b57cec5SDimitry Andric   }
661*0b57cec5SDimitry Andric 
662*0b57cec5SDimitry Andric   return nullptr;
663*0b57cec5SDimitry Andric }
664*0b57cec5SDimitry Andric 
665*0b57cec5SDimitry Andric static
666*0b57cec5SDimitry Andric bool isJump(unsigned Opcode) {
667*0b57cec5SDimitry Andric   return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
668*0b57cec5SDimitry Andric }
669*0b57cec5SDimitry Andric 
670*0b57cec5SDimitry Andric static bool isBranch(unsigned Opcode) {
671*0b57cec5SDimitry Andric   return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
672*0b57cec5SDimitry Andric       Opcode == R600::BRANCH_COND_f32;
673*0b57cec5SDimitry Andric }
674*0b57cec5SDimitry Andric 
675*0b57cec5SDimitry Andric bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
676*0b57cec5SDimitry Andric                                   MachineBasicBlock *&TBB,
677*0b57cec5SDimitry Andric                                   MachineBasicBlock *&FBB,
678*0b57cec5SDimitry Andric                                   SmallVectorImpl<MachineOperand> &Cond,
679*0b57cec5SDimitry Andric                                   bool AllowModify) const {
680*0b57cec5SDimitry Andric   // Most of the following comes from the ARM implementation of AnalyzeBranch
681*0b57cec5SDimitry Andric 
682*0b57cec5SDimitry Andric   // If the block has no terminators, it just falls into the block after it.
683*0b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
684*0b57cec5SDimitry Andric   if (I == MBB.end())
685*0b57cec5SDimitry Andric     return false;
686*0b57cec5SDimitry Andric 
687*0b57cec5SDimitry Andric   // R600::BRANCH* instructions are only available after isel and are not
688*0b57cec5SDimitry Andric   // handled
689*0b57cec5SDimitry Andric   if (isBranch(I->getOpcode()))
690*0b57cec5SDimitry Andric     return true;
691*0b57cec5SDimitry Andric   if (!isJump(I->getOpcode())) {
692*0b57cec5SDimitry Andric     return false;
693*0b57cec5SDimitry Andric   }
694*0b57cec5SDimitry Andric 
695*0b57cec5SDimitry Andric   // Remove successive JUMP
696*0b57cec5SDimitry Andric   while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
697*0b57cec5SDimitry Andric       MachineBasicBlock::iterator PriorI = std::prev(I);
698*0b57cec5SDimitry Andric       if (AllowModify)
699*0b57cec5SDimitry Andric         I->removeFromParent();
700*0b57cec5SDimitry Andric       I = PriorI;
701*0b57cec5SDimitry Andric   }
702*0b57cec5SDimitry Andric   MachineInstr &LastInst = *I;
703*0b57cec5SDimitry Andric 
704*0b57cec5SDimitry Andric   // If there is only one terminator instruction, process it.
705*0b57cec5SDimitry Andric   unsigned LastOpc = LastInst.getOpcode();
706*0b57cec5SDimitry Andric   if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
707*0b57cec5SDimitry Andric     if (LastOpc == R600::JUMP) {
708*0b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
709*0b57cec5SDimitry Andric       return false;
710*0b57cec5SDimitry Andric     } else if (LastOpc == R600::JUMP_COND) {
711*0b57cec5SDimitry Andric       auto predSet = I;
712*0b57cec5SDimitry Andric       while (!isPredicateSetter(predSet->getOpcode())) {
713*0b57cec5SDimitry Andric         predSet = --I;
714*0b57cec5SDimitry Andric       }
715*0b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
716*0b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(1));
717*0b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(2));
718*0b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
719*0b57cec5SDimitry Andric       return false;
720*0b57cec5SDimitry Andric     }
721*0b57cec5SDimitry Andric     return true;  // Can't handle indirect branch.
722*0b57cec5SDimitry Andric   }
723*0b57cec5SDimitry Andric 
724*0b57cec5SDimitry Andric   // Get the instruction before it if it is a terminator.
725*0b57cec5SDimitry Andric   MachineInstr &SecondLastInst = *I;
726*0b57cec5SDimitry Andric   unsigned SecondLastOpc = SecondLastInst.getOpcode();
727*0b57cec5SDimitry Andric 
728*0b57cec5SDimitry Andric   // If the block ends with a B and a Bcc, handle it.
729*0b57cec5SDimitry Andric   if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
730*0b57cec5SDimitry Andric     auto predSet = --I;
731*0b57cec5SDimitry Andric     while (!isPredicateSetter(predSet->getOpcode())) {
732*0b57cec5SDimitry Andric       predSet = --I;
733*0b57cec5SDimitry Andric     }
734*0b57cec5SDimitry Andric     TBB = SecondLastInst.getOperand(0).getMBB();
735*0b57cec5SDimitry Andric     FBB = LastInst.getOperand(0).getMBB();
736*0b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(1));
737*0b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(2));
738*0b57cec5SDimitry Andric     Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
739*0b57cec5SDimitry Andric     return false;
740*0b57cec5SDimitry Andric   }
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric   // Otherwise, can't handle this.
743*0b57cec5SDimitry Andric   return true;
744*0b57cec5SDimitry Andric }
745*0b57cec5SDimitry Andric 
746*0b57cec5SDimitry Andric static
747*0b57cec5SDimitry Andric MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
748*0b57cec5SDimitry Andric   for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
749*0b57cec5SDimitry Andric       It != E; ++It) {
750*0b57cec5SDimitry Andric     if (It->getOpcode() == R600::CF_ALU ||
751*0b57cec5SDimitry Andric         It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
752*0b57cec5SDimitry Andric       return It.getReverse();
753*0b57cec5SDimitry Andric   }
754*0b57cec5SDimitry Andric   return MBB.end();
755*0b57cec5SDimitry Andric }
756*0b57cec5SDimitry Andric 
757*0b57cec5SDimitry Andric unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,
758*0b57cec5SDimitry Andric                                      MachineBasicBlock *TBB,
759*0b57cec5SDimitry Andric                                      MachineBasicBlock *FBB,
760*0b57cec5SDimitry Andric                                      ArrayRef<MachineOperand> Cond,
761*0b57cec5SDimitry Andric                                      const DebugLoc &DL,
762*0b57cec5SDimitry Andric                                      int *BytesAdded) const {
763*0b57cec5SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
764*0b57cec5SDimitry Andric   assert(!BytesAdded && "code size not handled");
765*0b57cec5SDimitry Andric 
766*0b57cec5SDimitry Andric   if (!FBB) {
767*0b57cec5SDimitry Andric     if (Cond.empty()) {
768*0b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
769*0b57cec5SDimitry Andric       return 1;
770*0b57cec5SDimitry Andric     } else {
771*0b57cec5SDimitry Andric       MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
772*0b57cec5SDimitry Andric       assert(PredSet && "No previous predicate !");
773*0b57cec5SDimitry Andric       addFlag(*PredSet, 0, MO_FLAG_PUSH);
774*0b57cec5SDimitry Andric       PredSet->getOperand(2).setImm(Cond[1].getImm());
775*0b57cec5SDimitry Andric 
776*0b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP_COND))
777*0b57cec5SDimitry Andric              .addMBB(TBB)
778*0b57cec5SDimitry Andric              .addReg(R600::PREDICATE_BIT, RegState::Kill);
779*0b57cec5SDimitry Andric       MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
780*0b57cec5SDimitry Andric       if (CfAlu == MBB.end())
781*0b57cec5SDimitry Andric         return 1;
782*0b57cec5SDimitry Andric       assert (CfAlu->getOpcode() == R600::CF_ALU);
783*0b57cec5SDimitry Andric       CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
784*0b57cec5SDimitry Andric       return 1;
785*0b57cec5SDimitry Andric     }
786*0b57cec5SDimitry Andric   } else {
787*0b57cec5SDimitry Andric     MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
788*0b57cec5SDimitry Andric     assert(PredSet && "No previous predicate !");
789*0b57cec5SDimitry Andric     addFlag(*PredSet, 0, MO_FLAG_PUSH);
790*0b57cec5SDimitry Andric     PredSet->getOperand(2).setImm(Cond[1].getImm());
791*0b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP_COND))
792*0b57cec5SDimitry Andric             .addMBB(TBB)
793*0b57cec5SDimitry Andric             .addReg(R600::PREDICATE_BIT, RegState::Kill);
794*0b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
795*0b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
796*0b57cec5SDimitry Andric     if (CfAlu == MBB.end())
797*0b57cec5SDimitry Andric       return 2;
798*0b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU);
799*0b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
800*0b57cec5SDimitry Andric     return 2;
801*0b57cec5SDimitry Andric   }
802*0b57cec5SDimitry Andric }
803*0b57cec5SDimitry Andric 
804*0b57cec5SDimitry Andric unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,
805*0b57cec5SDimitry Andric                                      int *BytesRemoved) const {
806*0b57cec5SDimitry Andric   assert(!BytesRemoved && "code size not handled");
807*0b57cec5SDimitry Andric 
808*0b57cec5SDimitry Andric   // Note : we leave PRED* instructions there.
809*0b57cec5SDimitry Andric   // They may be needed when predicating instructions.
810*0b57cec5SDimitry Andric 
811*0b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
812*0b57cec5SDimitry Andric 
813*0b57cec5SDimitry Andric   if (I == MBB.begin()) {
814*0b57cec5SDimitry Andric     return 0;
815*0b57cec5SDimitry Andric   }
816*0b57cec5SDimitry Andric   --I;
817*0b57cec5SDimitry Andric   switch (I->getOpcode()) {
818*0b57cec5SDimitry Andric   default:
819*0b57cec5SDimitry Andric     return 0;
820*0b57cec5SDimitry Andric   case R600::JUMP_COND: {
821*0b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
822*0b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
823*0b57cec5SDimitry Andric     I->eraseFromParent();
824*0b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
825*0b57cec5SDimitry Andric     if (CfAlu == MBB.end())
826*0b57cec5SDimitry Andric       break;
827*0b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
828*0b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
829*0b57cec5SDimitry Andric     break;
830*0b57cec5SDimitry Andric   }
831*0b57cec5SDimitry Andric   case R600::JUMP:
832*0b57cec5SDimitry Andric     I->eraseFromParent();
833*0b57cec5SDimitry Andric     break;
834*0b57cec5SDimitry Andric   }
835*0b57cec5SDimitry Andric   I = MBB.end();
836*0b57cec5SDimitry Andric 
837*0b57cec5SDimitry Andric   if (I == MBB.begin()) {
838*0b57cec5SDimitry Andric     return 1;
839*0b57cec5SDimitry Andric   }
840*0b57cec5SDimitry Andric   --I;
841*0b57cec5SDimitry Andric   switch (I->getOpcode()) {
842*0b57cec5SDimitry Andric     // FIXME: only one case??
843*0b57cec5SDimitry Andric   default:
844*0b57cec5SDimitry Andric     return 1;
845*0b57cec5SDimitry Andric   case R600::JUMP_COND: {
846*0b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
847*0b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
848*0b57cec5SDimitry Andric     I->eraseFromParent();
849*0b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
850*0b57cec5SDimitry Andric     if (CfAlu == MBB.end())
851*0b57cec5SDimitry Andric       break;
852*0b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
853*0b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
854*0b57cec5SDimitry Andric     break;
855*0b57cec5SDimitry Andric   }
856*0b57cec5SDimitry Andric   case R600::JUMP:
857*0b57cec5SDimitry Andric     I->eraseFromParent();
858*0b57cec5SDimitry Andric     break;
859*0b57cec5SDimitry Andric   }
860*0b57cec5SDimitry Andric   return 2;
861*0b57cec5SDimitry Andric }
862*0b57cec5SDimitry Andric 
863*0b57cec5SDimitry Andric bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
864*0b57cec5SDimitry Andric   int idx = MI.findFirstPredOperandIdx();
865*0b57cec5SDimitry Andric   if (idx < 0)
866*0b57cec5SDimitry Andric     return false;
867*0b57cec5SDimitry Andric 
868*0b57cec5SDimitry Andric   unsigned Reg = MI.getOperand(idx).getReg();
869*0b57cec5SDimitry Andric   switch (Reg) {
870*0b57cec5SDimitry Andric   default: return false;
871*0b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
872*0b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
873*0b57cec5SDimitry Andric   case R600::PREDICATE_BIT:
874*0b57cec5SDimitry Andric     return true;
875*0b57cec5SDimitry Andric   }
876*0b57cec5SDimitry Andric }
877*0b57cec5SDimitry Andric 
878*0b57cec5SDimitry Andric bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {
879*0b57cec5SDimitry Andric   // XXX: KILL* instructions can be predicated, but they must be the last
880*0b57cec5SDimitry Andric   // instruction in a clause, so this means any instructions after them cannot
881*0b57cec5SDimitry Andric   // be predicated.  Until we have proper support for instruction clauses in the
882*0b57cec5SDimitry Andric   // backend, we will mark KILL* instructions as unpredicable.
883*0b57cec5SDimitry Andric 
884*0b57cec5SDimitry Andric   if (MI.getOpcode() == R600::KILLGT) {
885*0b57cec5SDimitry Andric     return false;
886*0b57cec5SDimitry Andric   } else if (MI.getOpcode() == R600::CF_ALU) {
887*0b57cec5SDimitry Andric     // If the clause start in the middle of MBB then the MBB has more
888*0b57cec5SDimitry Andric     // than a single clause, unable to predicate several clauses.
889*0b57cec5SDimitry Andric     if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
890*0b57cec5SDimitry Andric       return false;
891*0b57cec5SDimitry Andric     // TODO: We don't support KC merging atm
892*0b57cec5SDimitry Andric     return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
893*0b57cec5SDimitry Andric   } else if (isVector(MI)) {
894*0b57cec5SDimitry Andric     return false;
895*0b57cec5SDimitry Andric   } else {
896*0b57cec5SDimitry Andric     return TargetInstrInfo::isPredicable(MI);
897*0b57cec5SDimitry Andric   }
898*0b57cec5SDimitry Andric }
899*0b57cec5SDimitry Andric 
900*0b57cec5SDimitry Andric bool
901*0b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
902*0b57cec5SDimitry Andric                                    unsigned NumCycles,
903*0b57cec5SDimitry Andric                                    unsigned ExtraPredCycles,
904*0b57cec5SDimitry Andric                                    BranchProbability Probability) const{
905*0b57cec5SDimitry Andric   return true;
906*0b57cec5SDimitry Andric }
907*0b57cec5SDimitry Andric 
908*0b57cec5SDimitry Andric bool
909*0b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
910*0b57cec5SDimitry Andric                                    unsigned NumTCycles,
911*0b57cec5SDimitry Andric                                    unsigned ExtraTCycles,
912*0b57cec5SDimitry Andric                                    MachineBasicBlock &FMBB,
913*0b57cec5SDimitry Andric                                    unsigned NumFCycles,
914*0b57cec5SDimitry Andric                                    unsigned ExtraFCycles,
915*0b57cec5SDimitry Andric                                    BranchProbability Probability) const {
916*0b57cec5SDimitry Andric   return true;
917*0b57cec5SDimitry Andric }
918*0b57cec5SDimitry Andric 
919*0b57cec5SDimitry Andric bool
920*0b57cec5SDimitry Andric R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
921*0b57cec5SDimitry Andric                                          unsigned NumCycles,
922*0b57cec5SDimitry Andric                                          BranchProbability Probability)
923*0b57cec5SDimitry Andric                                          const {
924*0b57cec5SDimitry Andric   return true;
925*0b57cec5SDimitry Andric }
926*0b57cec5SDimitry Andric 
927*0b57cec5SDimitry Andric bool
928*0b57cec5SDimitry Andric R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
929*0b57cec5SDimitry Andric                                          MachineBasicBlock &FMBB) const {
930*0b57cec5SDimitry Andric   return false;
931*0b57cec5SDimitry Andric }
932*0b57cec5SDimitry Andric 
933*0b57cec5SDimitry Andric bool
934*0b57cec5SDimitry Andric R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
935*0b57cec5SDimitry Andric   MachineOperand &MO = Cond[1];
936*0b57cec5SDimitry Andric   switch (MO.getImm()) {
937*0b57cec5SDimitry Andric   case R600::PRED_SETE_INT:
938*0b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE_INT);
939*0b57cec5SDimitry Andric     break;
940*0b57cec5SDimitry Andric   case R600::PRED_SETNE_INT:
941*0b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE_INT);
942*0b57cec5SDimitry Andric     break;
943*0b57cec5SDimitry Andric   case R600::PRED_SETE:
944*0b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE);
945*0b57cec5SDimitry Andric     break;
946*0b57cec5SDimitry Andric   case R600::PRED_SETNE:
947*0b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE);
948*0b57cec5SDimitry Andric     break;
949*0b57cec5SDimitry Andric   default:
950*0b57cec5SDimitry Andric     return true;
951*0b57cec5SDimitry Andric   }
952*0b57cec5SDimitry Andric 
953*0b57cec5SDimitry Andric   MachineOperand &MO2 = Cond[2];
954*0b57cec5SDimitry Andric   switch (MO2.getReg()) {
955*0b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
956*0b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ONE);
957*0b57cec5SDimitry Andric     break;
958*0b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
959*0b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ZERO);
960*0b57cec5SDimitry Andric     break;
961*0b57cec5SDimitry Andric   default:
962*0b57cec5SDimitry Andric     return true;
963*0b57cec5SDimitry Andric   }
964*0b57cec5SDimitry Andric   return false;
965*0b57cec5SDimitry Andric }
966*0b57cec5SDimitry Andric 
967*0b57cec5SDimitry Andric bool R600InstrInfo::DefinesPredicate(MachineInstr &MI,
968*0b57cec5SDimitry Andric                                      std::vector<MachineOperand> &Pred) const {
969*0b57cec5SDimitry Andric   return isPredicateSetter(MI.getOpcode());
970*0b57cec5SDimitry Andric }
971*0b57cec5SDimitry Andric 
972*0b57cec5SDimitry Andric bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,
973*0b57cec5SDimitry Andric                                          ArrayRef<MachineOperand> Pred) const {
974*0b57cec5SDimitry Andric   int PIdx = MI.findFirstPredOperandIdx();
975*0b57cec5SDimitry Andric 
976*0b57cec5SDimitry Andric   if (MI.getOpcode() == R600::CF_ALU) {
977*0b57cec5SDimitry Andric     MI.getOperand(8).setImm(0);
978*0b57cec5SDimitry Andric     return true;
979*0b57cec5SDimitry Andric   }
980*0b57cec5SDimitry Andric 
981*0b57cec5SDimitry Andric   if (MI.getOpcode() == R600::DOT_4) {
982*0b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
983*0b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
984*0b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
985*0b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
986*0b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
987*0b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
988*0b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
989*0b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
990*0b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
991*0b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
992*0b57cec5SDimitry Andric     return true;
993*0b57cec5SDimitry Andric   }
994*0b57cec5SDimitry Andric 
995*0b57cec5SDimitry Andric   if (PIdx != -1) {
996*0b57cec5SDimitry Andric     MachineOperand &PMO = MI.getOperand(PIdx);
997*0b57cec5SDimitry Andric     PMO.setReg(Pred[2].getReg());
998*0b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
999*0b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
1000*0b57cec5SDimitry Andric     return true;
1001*0b57cec5SDimitry Andric   }
1002*0b57cec5SDimitry Andric 
1003*0b57cec5SDimitry Andric   return false;
1004*0b57cec5SDimitry Andric }
1005*0b57cec5SDimitry Andric 
1006*0b57cec5SDimitry Andric unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
1007*0b57cec5SDimitry Andric   return 2;
1008*0b57cec5SDimitry Andric }
1009*0b57cec5SDimitry Andric 
1010*0b57cec5SDimitry Andric unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
1011*0b57cec5SDimitry Andric                                             const MachineInstr &,
1012*0b57cec5SDimitry Andric                                             unsigned *PredCost) const {
1013*0b57cec5SDimitry Andric   if (PredCost)
1014*0b57cec5SDimitry Andric     *PredCost = 2;
1015*0b57cec5SDimitry Andric   return 2;
1016*0b57cec5SDimitry Andric }
1017*0b57cec5SDimitry Andric 
1018*0b57cec5SDimitry Andric unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
1019*0b57cec5SDimitry Andric                                                    unsigned Channel) const {
1020*0b57cec5SDimitry Andric   assert(Channel == 0);
1021*0b57cec5SDimitry Andric   return RegIndex;
1022*0b57cec5SDimitry Andric }
1023*0b57cec5SDimitry Andric 
1024*0b57cec5SDimitry Andric bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
1025*0b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1026*0b57cec5SDimitry Andric   default: {
1027*0b57cec5SDimitry Andric     MachineBasicBlock *MBB = MI.getParent();
1028*0b57cec5SDimitry Andric     int OffsetOpIdx =
1029*0b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
1030*0b57cec5SDimitry Andric     // addr is a custom operand with multiple MI operands, and only the
1031*0b57cec5SDimitry Andric     // first MI operand is given a name.
1032*0b57cec5SDimitry Andric     int RegOpIdx = OffsetOpIdx + 1;
1033*0b57cec5SDimitry Andric     int ChanOpIdx =
1034*0b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
1035*0b57cec5SDimitry Andric     if (isRegisterLoad(MI)) {
1036*0b57cec5SDimitry Andric       int DstOpIdx =
1037*0b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
1038*0b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1039*0b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1040*0b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1041*0b57cec5SDimitry Andric       unsigned OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1042*0b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1043*0b57cec5SDimitry Andric         buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
1044*0b57cec5SDimitry Andric                       getIndirectAddrRegClass()->getRegister(Address));
1045*0b57cec5SDimitry Andric       } else {
1046*0b57cec5SDimitry Andric         buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
1047*0b57cec5SDimitry Andric                           OffsetReg);
1048*0b57cec5SDimitry Andric       }
1049*0b57cec5SDimitry Andric     } else if (isRegisterStore(MI)) {
1050*0b57cec5SDimitry Andric       int ValOpIdx =
1051*0b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
1052*0b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
1053*0b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
1054*0b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
1055*0b57cec5SDimitry Andric       unsigned OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
1056*0b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
1057*0b57cec5SDimitry Andric         buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
1058*0b57cec5SDimitry Andric                       MI.getOperand(ValOpIdx).getReg());
1059*0b57cec5SDimitry Andric       } else {
1060*0b57cec5SDimitry Andric         buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
1061*0b57cec5SDimitry Andric                            calculateIndirectAddress(RegIndex, Channel),
1062*0b57cec5SDimitry Andric                            OffsetReg);
1063*0b57cec5SDimitry Andric       }
1064*0b57cec5SDimitry Andric     } else {
1065*0b57cec5SDimitry Andric       return false;
1066*0b57cec5SDimitry Andric     }
1067*0b57cec5SDimitry Andric 
1068*0b57cec5SDimitry Andric     MBB->erase(MI);
1069*0b57cec5SDimitry Andric     return true;
1070*0b57cec5SDimitry Andric   }
1071*0b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V2:
1072*0b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V4:
1073*0b57cec5SDimitry Andric     buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
1074*0b57cec5SDimitry Andric                       RI.getHWRegIndex(MI.getOperand(1).getReg()), //  Address
1075*0b57cec5SDimitry Andric                       MI.getOperand(2).getReg(),
1076*0b57cec5SDimitry Andric                       RI.getHWRegChan(MI.getOperand(1).getReg()));
1077*0b57cec5SDimitry Andric     break;
1078*0b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V2:
1079*0b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V4:
1080*0b57cec5SDimitry Andric     buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
1081*0b57cec5SDimitry Andric                        RI.getHWRegIndex(MI.getOperand(1).getReg()),   // Address
1082*0b57cec5SDimitry Andric                        MI.getOperand(3).getReg(),                     // Offset
1083*0b57cec5SDimitry Andric                        RI.getHWRegChan(MI.getOperand(1).getReg()));   // Channel
1084*0b57cec5SDimitry Andric     break;
1085*0b57cec5SDimitry Andric   }
1086*0b57cec5SDimitry Andric   MI.eraseFromParent();
1087*0b57cec5SDimitry Andric   return true;
1088*0b57cec5SDimitry Andric }
1089*0b57cec5SDimitry Andric 
1090*0b57cec5SDimitry Andric void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,
1091*0b57cec5SDimitry Andric                                              const MachineFunction &MF,
1092*0b57cec5SDimitry Andric                                              const R600RegisterInfo &TRI) const {
1093*0b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1094*0b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
1095*0b57cec5SDimitry Andric 
1096*0b57cec5SDimitry Andric   unsigned StackWidth = TFL->getStackWidth(MF);
1097*0b57cec5SDimitry Andric   int End = getIndirectIndexEnd(MF);
1098*0b57cec5SDimitry Andric 
1099*0b57cec5SDimitry Andric   if (End == -1)
1100*0b57cec5SDimitry Andric     return;
1101*0b57cec5SDimitry Andric 
1102*0b57cec5SDimitry Andric   for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1103*0b57cec5SDimitry Andric     for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1104*0b57cec5SDimitry Andric       unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1105*0b57cec5SDimitry Andric       TRI.reserveRegisterTuples(Reserved, Reg);
1106*0b57cec5SDimitry Andric     }
1107*0b57cec5SDimitry Andric   }
1108*0b57cec5SDimitry Andric }
1109*0b57cec5SDimitry Andric 
1110*0b57cec5SDimitry Andric const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
1111*0b57cec5SDimitry Andric   return &R600::R600_TReg32_XRegClass;
1112*0b57cec5SDimitry Andric }
1113*0b57cec5SDimitry Andric 
1114*0b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1115*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
1116*0b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
1117*0b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
1118*0b57cec5SDimitry Andric   return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
1119*0b57cec5SDimitry Andric }
1120*0b57cec5SDimitry Andric 
1121*0b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1122*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
1123*0b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
1124*0b57cec5SDimitry Andric                                        unsigned OffsetReg,
1125*0b57cec5SDimitry Andric                                        unsigned AddrChan) const {
1126*0b57cec5SDimitry Andric   unsigned AddrReg;
1127*0b57cec5SDimitry Andric   switch (AddrChan) {
1128*0b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
1129*0b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1130*0b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1131*0b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1132*0b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1133*0b57cec5SDimitry Andric   }
1134*0b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1135*0b57cec5SDimitry Andric                                                R600::AR_X, OffsetReg);
1136*0b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
1137*0b57cec5SDimitry Andric 
1138*0b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1139*0b57cec5SDimitry Andric                                       AddrReg, ValueReg)
1140*0b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
1141*0b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
1142*0b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::dst_rel, 1);
1143*0b57cec5SDimitry Andric   return Mov;
1144*0b57cec5SDimitry Andric }
1145*0b57cec5SDimitry Andric 
1146*0b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1147*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
1148*0b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
1149*0b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
1150*0b57cec5SDimitry Andric   return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
1151*0b57cec5SDimitry Andric }
1152*0b57cec5SDimitry Andric 
1153*0b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1154*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
1155*0b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
1156*0b57cec5SDimitry Andric                                        unsigned OffsetReg,
1157*0b57cec5SDimitry Andric                                        unsigned AddrChan) const {
1158*0b57cec5SDimitry Andric   unsigned AddrReg;
1159*0b57cec5SDimitry Andric   switch (AddrChan) {
1160*0b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
1161*0b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
1162*0b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
1163*0b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
1164*0b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
1165*0b57cec5SDimitry Andric   }
1166*0b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
1167*0b57cec5SDimitry Andric                                                        R600::AR_X,
1168*0b57cec5SDimitry Andric                                                        OffsetReg);
1169*0b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
1170*0b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
1171*0b57cec5SDimitry Andric                                       ValueReg,
1172*0b57cec5SDimitry Andric                                       AddrReg)
1173*0b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
1174*0b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
1175*0b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::src0_rel, 1);
1176*0b57cec5SDimitry Andric 
1177*0b57cec5SDimitry Andric   return Mov;
1178*0b57cec5SDimitry Andric }
1179*0b57cec5SDimitry Andric 
1180*0b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
1181*0b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
1182*0b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1183*0b57cec5SDimitry Andric   int Offset = -1;
1184*0b57cec5SDimitry Andric 
1185*0b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
1186*0b57cec5SDimitry Andric     return -1;
1187*0b57cec5SDimitry Andric   }
1188*0b57cec5SDimitry Andric 
1189*0b57cec5SDimitry Andric   if (MRI.livein_empty()) {
1190*0b57cec5SDimitry Andric     return 0;
1191*0b57cec5SDimitry Andric   }
1192*0b57cec5SDimitry Andric 
1193*0b57cec5SDimitry Andric   const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
1194*0b57cec5SDimitry Andric   for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1195*0b57cec5SDimitry Andric     unsigned Reg = LI.first;
1196*0b57cec5SDimitry Andric     if (TargetRegisterInfo::isVirtualRegister(Reg) ||
1197*0b57cec5SDimitry Andric         !IndirectRC->contains(Reg))
1198*0b57cec5SDimitry Andric       continue;
1199*0b57cec5SDimitry Andric 
1200*0b57cec5SDimitry Andric     unsigned RegIndex;
1201*0b57cec5SDimitry Andric     unsigned RegEnd;
1202*0b57cec5SDimitry Andric     for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
1203*0b57cec5SDimitry Andric                                                           ++RegIndex) {
1204*0b57cec5SDimitry Andric       if (IndirectRC->getRegister(RegIndex) == Reg)
1205*0b57cec5SDimitry Andric         break;
1206*0b57cec5SDimitry Andric     }
1207*0b57cec5SDimitry Andric     Offset = std::max(Offset, (int)RegIndex);
1208*0b57cec5SDimitry Andric   }
1209*0b57cec5SDimitry Andric 
1210*0b57cec5SDimitry Andric   return Offset + 1;
1211*0b57cec5SDimitry Andric }
1212*0b57cec5SDimitry Andric 
1213*0b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
1214*0b57cec5SDimitry Andric   int Offset = 0;
1215*0b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
1216*0b57cec5SDimitry Andric 
1217*0b57cec5SDimitry Andric   // Variable sized objects are not supported
1218*0b57cec5SDimitry Andric   if (MFI.hasVarSizedObjects()) {
1219*0b57cec5SDimitry Andric     return -1;
1220*0b57cec5SDimitry Andric   }
1221*0b57cec5SDimitry Andric 
1222*0b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
1223*0b57cec5SDimitry Andric     return -1;
1224*0b57cec5SDimitry Andric   }
1225*0b57cec5SDimitry Andric 
1226*0b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
1227*0b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
1228*0b57cec5SDimitry Andric 
1229*0b57cec5SDimitry Andric   unsigned IgnoredFrameReg;
1230*0b57cec5SDimitry Andric   Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg);
1231*0b57cec5SDimitry Andric 
1232*0b57cec5SDimitry Andric   return getIndirectIndexBegin(MF) + Offset;
1233*0b57cec5SDimitry Andric }
1234*0b57cec5SDimitry Andric 
1235*0b57cec5SDimitry Andric unsigned R600InstrInfo::getMaxAlusPerClause() const {
1236*0b57cec5SDimitry Andric   return 115;
1237*0b57cec5SDimitry Andric }
1238*0b57cec5SDimitry Andric 
1239*0b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
1240*0b57cec5SDimitry Andric                                                   MachineBasicBlock::iterator I,
1241*0b57cec5SDimitry Andric                                                   unsigned Opcode,
1242*0b57cec5SDimitry Andric                                                   unsigned DstReg,
1243*0b57cec5SDimitry Andric                                                   unsigned Src0Reg,
1244*0b57cec5SDimitry Andric                                                   unsigned Src1Reg) const {
1245*0b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
1246*0b57cec5SDimitry Andric     DstReg);           // $dst
1247*0b57cec5SDimitry Andric 
1248*0b57cec5SDimitry Andric   if (Src1Reg) {
1249*0b57cec5SDimitry Andric     MIB.addImm(0)     // $update_exec_mask
1250*0b57cec5SDimitry Andric        .addImm(0);    // $update_predicate
1251*0b57cec5SDimitry Andric   }
1252*0b57cec5SDimitry Andric   MIB.addImm(1)        // $write
1253*0b57cec5SDimitry Andric      .addImm(0)        // $omod
1254*0b57cec5SDimitry Andric      .addImm(0)        // $dst_rel
1255*0b57cec5SDimitry Andric      .addImm(0)        // $dst_clamp
1256*0b57cec5SDimitry Andric      .addReg(Src0Reg)  // $src0
1257*0b57cec5SDimitry Andric      .addImm(0)        // $src0_neg
1258*0b57cec5SDimitry Andric      .addImm(0)        // $src0_rel
1259*0b57cec5SDimitry Andric      .addImm(0)        // $src0_abs
1260*0b57cec5SDimitry Andric      .addImm(-1);       // $src0_sel
1261*0b57cec5SDimitry Andric 
1262*0b57cec5SDimitry Andric   if (Src1Reg) {
1263*0b57cec5SDimitry Andric     MIB.addReg(Src1Reg) // $src1
1264*0b57cec5SDimitry Andric        .addImm(0)       // $src1_neg
1265*0b57cec5SDimitry Andric        .addImm(0)       // $src1_rel
1266*0b57cec5SDimitry Andric        .addImm(0)       // $src1_abs
1267*0b57cec5SDimitry Andric        .addImm(-1);      // $src1_sel
1268*0b57cec5SDimitry Andric   }
1269*0b57cec5SDimitry Andric 
1270*0b57cec5SDimitry Andric   //XXX: The r600g finalizer expects this to be 1, once we've moved the
1271*0b57cec5SDimitry Andric   //scheduling to the backend, we can change the default to 0.
1272*0b57cec5SDimitry Andric   MIB.addImm(1)        // $last
1273*0b57cec5SDimitry Andric       .addReg(R600::PRED_SEL_OFF) // $pred_sel
1274*0b57cec5SDimitry Andric       .addImm(0)         // $literal
1275*0b57cec5SDimitry Andric       .addImm(0);        // $bank_swizzle
1276*0b57cec5SDimitry Andric 
1277*0b57cec5SDimitry Andric   return MIB;
1278*0b57cec5SDimitry Andric }
1279*0b57cec5SDimitry Andric 
1280*0b57cec5SDimitry Andric #define OPERAND_CASE(Label) \
1281*0b57cec5SDimitry Andric   case Label: { \
1282*0b57cec5SDimitry Andric     static const unsigned Ops[] = \
1283*0b57cec5SDimitry Andric     { \
1284*0b57cec5SDimitry Andric       Label##_X, \
1285*0b57cec5SDimitry Andric       Label##_Y, \
1286*0b57cec5SDimitry Andric       Label##_Z, \
1287*0b57cec5SDimitry Andric       Label##_W \
1288*0b57cec5SDimitry Andric     }; \
1289*0b57cec5SDimitry Andric     return Ops[Slot]; \
1290*0b57cec5SDimitry Andric   }
1291*0b57cec5SDimitry Andric 
1292*0b57cec5SDimitry Andric static unsigned getSlotedOps(unsigned  Op, unsigned Slot) {
1293*0b57cec5SDimitry Andric   switch (Op) {
1294*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_exec_mask)
1295*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_pred)
1296*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::write)
1297*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::omod)
1298*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::dst_rel)
1299*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::clamp)
1300*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0)
1301*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_neg)
1302*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_rel)
1303*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_abs)
1304*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_sel)
1305*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1)
1306*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_neg)
1307*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_rel)
1308*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_abs)
1309*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_sel)
1310*0b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::pred_sel)
1311*0b57cec5SDimitry Andric   default:
1312*0b57cec5SDimitry Andric     llvm_unreachable("Wrong Operand");
1313*0b57cec5SDimitry Andric   }
1314*0b57cec5SDimitry Andric }
1315*0b57cec5SDimitry Andric 
1316*0b57cec5SDimitry Andric #undef OPERAND_CASE
1317*0b57cec5SDimitry Andric 
1318*0b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
1319*0b57cec5SDimitry Andric     MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
1320*0b57cec5SDimitry Andric     const {
1321*0b57cec5SDimitry Andric   assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
1322*0b57cec5SDimitry Andric   unsigned Opcode;
1323*0b57cec5SDimitry Andric   if (ST.getGeneration() <= AMDGPUSubtarget::R700)
1324*0b57cec5SDimitry Andric     Opcode = R600::DOT4_r600;
1325*0b57cec5SDimitry Andric   else
1326*0b57cec5SDimitry Andric     Opcode = R600::DOT4_eg;
1327*0b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MI;
1328*0b57cec5SDimitry Andric   MachineOperand &Src0 = MI->getOperand(
1329*0b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
1330*0b57cec5SDimitry Andric   MachineOperand &Src1 = MI->getOperand(
1331*0b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
1332*0b57cec5SDimitry Andric   MachineInstr *MIB = buildDefaultInstruction(
1333*0b57cec5SDimitry Andric       MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
1334*0b57cec5SDimitry Andric   static const unsigned  Operands[14] = {
1335*0b57cec5SDimitry Andric     R600::OpName::update_exec_mask,
1336*0b57cec5SDimitry Andric     R600::OpName::update_pred,
1337*0b57cec5SDimitry Andric     R600::OpName::write,
1338*0b57cec5SDimitry Andric     R600::OpName::omod,
1339*0b57cec5SDimitry Andric     R600::OpName::dst_rel,
1340*0b57cec5SDimitry Andric     R600::OpName::clamp,
1341*0b57cec5SDimitry Andric     R600::OpName::src0_neg,
1342*0b57cec5SDimitry Andric     R600::OpName::src0_rel,
1343*0b57cec5SDimitry Andric     R600::OpName::src0_abs,
1344*0b57cec5SDimitry Andric     R600::OpName::src0_sel,
1345*0b57cec5SDimitry Andric     R600::OpName::src1_neg,
1346*0b57cec5SDimitry Andric     R600::OpName::src1_rel,
1347*0b57cec5SDimitry Andric     R600::OpName::src1_abs,
1348*0b57cec5SDimitry Andric     R600::OpName::src1_sel,
1349*0b57cec5SDimitry Andric   };
1350*0b57cec5SDimitry Andric 
1351*0b57cec5SDimitry Andric   MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1352*0b57cec5SDimitry Andric       getSlotedOps(R600::OpName::pred_sel, Slot)));
1353*0b57cec5SDimitry Andric   MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
1354*0b57cec5SDimitry Andric       .setReg(MO.getReg());
1355*0b57cec5SDimitry Andric 
1356*0b57cec5SDimitry Andric   for (unsigned i = 0; i < 14; i++) {
1357*0b57cec5SDimitry Andric     MachineOperand &MO = MI->getOperand(
1358*0b57cec5SDimitry Andric         getOperandIdx(MI->getOpcode(), getSlotedOps(Operands[i], Slot)));
1359*0b57cec5SDimitry Andric     assert (MO.isImm());
1360*0b57cec5SDimitry Andric     setImmOperand(*MIB, Operands[i], MO.getImm());
1361*0b57cec5SDimitry Andric   }
1362*0b57cec5SDimitry Andric   MIB->getOperand(20).setImm(0);
1363*0b57cec5SDimitry Andric   return MIB;
1364*0b57cec5SDimitry Andric }
1365*0b57cec5SDimitry Andric 
1366*0b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
1367*0b57cec5SDimitry Andric                                          MachineBasicBlock::iterator I,
1368*0b57cec5SDimitry Andric                                          unsigned DstReg,
1369*0b57cec5SDimitry Andric                                          uint64_t Imm) const {
1370*0b57cec5SDimitry Andric   MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
1371*0b57cec5SDimitry Andric                                                   R600::ALU_LITERAL_X);
1372*0b57cec5SDimitry Andric   setImmOperand(*MovImm, R600::OpName::literal, Imm);
1373*0b57cec5SDimitry Andric   return MovImm;
1374*0b57cec5SDimitry Andric }
1375*0b57cec5SDimitry Andric 
1376*0b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
1377*0b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
1378*0b57cec5SDimitry Andric                                        unsigned DstReg, unsigned SrcReg) const {
1379*0b57cec5SDimitry Andric   return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
1380*0b57cec5SDimitry Andric }
1381*0b57cec5SDimitry Andric 
1382*0b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1383*0b57cec5SDimitry Andric   return getOperandIdx(MI.getOpcode(), Op);
1384*0b57cec5SDimitry Andric }
1385*0b57cec5SDimitry Andric 
1386*0b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
1387*0b57cec5SDimitry Andric   return R600::getNamedOperandIdx(Opcode, Op);
1388*0b57cec5SDimitry Andric }
1389*0b57cec5SDimitry Andric 
1390*0b57cec5SDimitry Andric void R600InstrInfo::setImmOperand(MachineInstr &MI, unsigned Op,
1391*0b57cec5SDimitry Andric                                   int64_t Imm) const {
1392*0b57cec5SDimitry Andric   int Idx = getOperandIdx(MI, Op);
1393*0b57cec5SDimitry Andric   assert(Idx != -1 && "Operand not supported for this instruction.");
1394*0b57cec5SDimitry Andric   assert(MI.getOperand(Idx).isImm());
1395*0b57cec5SDimitry Andric   MI.getOperand(Idx).setImm(Imm);
1396*0b57cec5SDimitry Andric }
1397*0b57cec5SDimitry Andric 
1398*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1399*0b57cec5SDimitry Andric // Instruction flag getters/setters
1400*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1401*0b57cec5SDimitry Andric 
1402*0b57cec5SDimitry Andric MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
1403*0b57cec5SDimitry Andric                                          unsigned Flag) const {
1404*0b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1405*0b57cec5SDimitry Andric   int FlagIndex = 0;
1406*0b57cec5SDimitry Andric   if (Flag != 0) {
1407*0b57cec5SDimitry Andric     // If we pass something other than the default value of Flag to this
1408*0b57cec5SDimitry Andric     // function, it means we are want to set a flag on an instruction
1409*0b57cec5SDimitry Andric     // that uses native encoding.
1410*0b57cec5SDimitry Andric     assert(HAS_NATIVE_OPERANDS(TargetFlags));
1411*0b57cec5SDimitry Andric     bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1412*0b57cec5SDimitry Andric     switch (Flag) {
1413*0b57cec5SDimitry Andric     case MO_FLAG_CLAMP:
1414*0b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
1415*0b57cec5SDimitry Andric       break;
1416*0b57cec5SDimitry Andric     case MO_FLAG_MASK:
1417*0b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::write);
1418*0b57cec5SDimitry Andric       break;
1419*0b57cec5SDimitry Andric     case MO_FLAG_NOT_LAST:
1420*0b57cec5SDimitry Andric     case MO_FLAG_LAST:
1421*0b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::last);
1422*0b57cec5SDimitry Andric       break;
1423*0b57cec5SDimitry Andric     case MO_FLAG_NEG:
1424*0b57cec5SDimitry Andric       switch (SrcIdx) {
1425*0b57cec5SDimitry Andric       case 0:
1426*0b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
1427*0b57cec5SDimitry Andric         break;
1428*0b57cec5SDimitry Andric       case 1:
1429*0b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
1430*0b57cec5SDimitry Andric         break;
1431*0b57cec5SDimitry Andric       case 2:
1432*0b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
1433*0b57cec5SDimitry Andric         break;
1434*0b57cec5SDimitry Andric       }
1435*0b57cec5SDimitry Andric       break;
1436*0b57cec5SDimitry Andric 
1437*0b57cec5SDimitry Andric     case MO_FLAG_ABS:
1438*0b57cec5SDimitry Andric       assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1439*0b57cec5SDimitry Andric                        "instructions.");
1440*0b57cec5SDimitry Andric       (void)IsOP3;
1441*0b57cec5SDimitry Andric       switch (SrcIdx) {
1442*0b57cec5SDimitry Andric       case 0:
1443*0b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
1444*0b57cec5SDimitry Andric         break;
1445*0b57cec5SDimitry Andric       case 1:
1446*0b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
1447*0b57cec5SDimitry Andric         break;
1448*0b57cec5SDimitry Andric       }
1449*0b57cec5SDimitry Andric       break;
1450*0b57cec5SDimitry Andric 
1451*0b57cec5SDimitry Andric     default:
1452*0b57cec5SDimitry Andric       FlagIndex = -1;
1453*0b57cec5SDimitry Andric       break;
1454*0b57cec5SDimitry Andric     }
1455*0b57cec5SDimitry Andric     assert(FlagIndex != -1 && "Flag not supported for this instruction");
1456*0b57cec5SDimitry Andric   } else {
1457*0b57cec5SDimitry Andric       FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1458*0b57cec5SDimitry Andric       assert(FlagIndex != 0 &&
1459*0b57cec5SDimitry Andric          "Instruction flags not supported for this instruction");
1460*0b57cec5SDimitry Andric   }
1461*0b57cec5SDimitry Andric 
1462*0b57cec5SDimitry Andric   MachineOperand &FlagOp = MI.getOperand(FlagIndex);
1463*0b57cec5SDimitry Andric   assert(FlagOp.isImm());
1464*0b57cec5SDimitry Andric   return FlagOp;
1465*0b57cec5SDimitry Andric }
1466*0b57cec5SDimitry Andric 
1467*0b57cec5SDimitry Andric void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
1468*0b57cec5SDimitry Andric                             unsigned Flag) const {
1469*0b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1470*0b57cec5SDimitry Andric   if (Flag == 0) {
1471*0b57cec5SDimitry Andric     return;
1472*0b57cec5SDimitry Andric   }
1473*0b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1474*0b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1475*0b57cec5SDimitry Andric     if (Flag == MO_FLAG_NOT_LAST) {
1476*0b57cec5SDimitry Andric       clearFlag(MI, Operand, MO_FLAG_LAST);
1477*0b57cec5SDimitry Andric     } else if (Flag == MO_FLAG_MASK) {
1478*0b57cec5SDimitry Andric       clearFlag(MI, Operand, Flag);
1479*0b57cec5SDimitry Andric     } else {
1480*0b57cec5SDimitry Andric       FlagOp.setImm(1);
1481*0b57cec5SDimitry Andric     }
1482*0b57cec5SDimitry Andric   } else {
1483*0b57cec5SDimitry Andric       MachineOperand &FlagOp = getFlagOp(MI, Operand);
1484*0b57cec5SDimitry Andric       FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1485*0b57cec5SDimitry Andric   }
1486*0b57cec5SDimitry Andric }
1487*0b57cec5SDimitry Andric 
1488*0b57cec5SDimitry Andric void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
1489*0b57cec5SDimitry Andric                               unsigned Flag) const {
1490*0b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
1491*0b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1492*0b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1493*0b57cec5SDimitry Andric     FlagOp.setImm(0);
1494*0b57cec5SDimitry Andric   } else {
1495*0b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI);
1496*0b57cec5SDimitry Andric     unsigned InstFlags = FlagOp.getImm();
1497*0b57cec5SDimitry Andric     InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1498*0b57cec5SDimitry Andric     FlagOp.setImm(InstFlags);
1499*0b57cec5SDimitry Andric   }
1500*0b57cec5SDimitry Andric }
1501*0b57cec5SDimitry Andric 
1502*0b57cec5SDimitry Andric unsigned R600InstrInfo::getAddressSpaceForPseudoSourceKind(
1503*0b57cec5SDimitry Andric     unsigned Kind) const {
1504*0b57cec5SDimitry Andric   switch (Kind) {
1505*0b57cec5SDimitry Andric   case PseudoSourceValue::Stack:
1506*0b57cec5SDimitry Andric   case PseudoSourceValue::FixedStack:
1507*0b57cec5SDimitry Andric     return AMDGPUAS::PRIVATE_ADDRESS;
1508*0b57cec5SDimitry Andric   case PseudoSourceValue::ConstantPool:
1509*0b57cec5SDimitry Andric   case PseudoSourceValue::GOT:
1510*0b57cec5SDimitry Andric   case PseudoSourceValue::JumpTable:
1511*0b57cec5SDimitry Andric   case PseudoSourceValue::GlobalValueCallEntry:
1512*0b57cec5SDimitry Andric   case PseudoSourceValue::ExternalSymbolCallEntry:
1513*0b57cec5SDimitry Andric   case PseudoSourceValue::TargetCustom:
1514*0b57cec5SDimitry Andric     return AMDGPUAS::CONSTANT_ADDRESS;
1515*0b57cec5SDimitry Andric   }
1516*0b57cec5SDimitry Andric 
1517*0b57cec5SDimitry Andric   llvm_unreachable("Invalid pseudo source kind");
1518*0b57cec5SDimitry Andric }
1519