xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600InstrInfo.cpp (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
10b57cec5SDimitry Andric //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// R600 Implementation of TargetInstrInfo.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "R600InstrInfo.h"
150b57cec5SDimitry Andric #include "AMDGPU.h"
16349cc55cSDimitry Andric #include "MCTargetDesc/R600MCTargetDesc.h"
17349cc55cSDimitry Andric #include "R600.h"
18e8d8bef9SDimitry Andric #include "R600Defines.h"
19e8d8bef9SDimitry Andric #include "R600Subtarget.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace llvm;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
250b57cec5SDimitry Andric #include "R600GenDFAPacketizer.inc"
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric #define GET_INSTRINFO_CTOR_DTOR
280b57cec5SDimitry Andric #define GET_INSTRMAP_INFO
290b57cec5SDimitry Andric #define GET_INSTRINFO_NAMED_OPS
300b57cec5SDimitry Andric #include "R600GenInstrInfo.inc"
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)
330b57cec5SDimitry Andric   : R600GenInstrInfo(-1, -1), RI(), ST(ST) {}
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric bool R600InstrInfo::isVector(const MachineInstr &MI) const {
360b57cec5SDimitry Andric   return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
370b57cec5SDimitry Andric }
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric void R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
400b57cec5SDimitry Andric                                 MachineBasicBlock::iterator MI,
41480093f4SDimitry Andric                                 const DebugLoc &DL, MCRegister DestReg,
42480093f4SDimitry Andric                                 MCRegister SrcReg, bool KillSrc) const {
430b57cec5SDimitry Andric   unsigned VectorComponents = 0;
440b57cec5SDimitry Andric   if ((R600::R600_Reg128RegClass.contains(DestReg) ||
450b57cec5SDimitry Andric       R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&
460b57cec5SDimitry Andric       (R600::R600_Reg128RegClass.contains(SrcReg) ||
470b57cec5SDimitry Andric        R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {
480b57cec5SDimitry Andric     VectorComponents = 4;
490b57cec5SDimitry Andric   } else if((R600::R600_Reg64RegClass.contains(DestReg) ||
500b57cec5SDimitry Andric             R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&
510b57cec5SDimitry Andric             (R600::R600_Reg64RegClass.contains(SrcReg) ||
520b57cec5SDimitry Andric              R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {
530b57cec5SDimitry Andric     VectorComponents = 2;
540b57cec5SDimitry Andric   }
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   if (VectorComponents > 0) {
570b57cec5SDimitry Andric     for (unsigned I = 0; I < VectorComponents; I++) {
585ffd83dbSDimitry Andric       unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(I);
590b57cec5SDimitry Andric       buildDefaultInstruction(MBB, MI, R600::MOV,
600b57cec5SDimitry Andric                               RI.getSubReg(DestReg, SubRegIndex),
610b57cec5SDimitry Andric                               RI.getSubReg(SrcReg, SubRegIndex))
620b57cec5SDimitry Andric                               .addReg(DestReg,
630b57cec5SDimitry Andric                                       RegState::Define | RegState::Implicit);
640b57cec5SDimitry Andric     }
650b57cec5SDimitry Andric   } else {
660b57cec5SDimitry Andric     MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, R600::MOV,
670b57cec5SDimitry Andric                                                   DestReg, SrcReg);
680b57cec5SDimitry Andric     NewMI->getOperand(getOperandIdx(*NewMI, R600::OpName::src0))
690b57cec5SDimitry Andric                                     .setIsKill(KillSrc);
700b57cec5SDimitry Andric   }
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric /// \returns true if \p MBBI can be moved into a new basic.
740b57cec5SDimitry Andric bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,
750b57cec5SDimitry Andric                                        MachineBasicBlock::iterator MBBI) const {
760b57cec5SDimitry Andric   for (MachineInstr::const_mop_iterator I = MBBI->operands_begin(),
770b57cec5SDimitry Andric                                         E = MBBI->operands_end(); I != E; ++I) {
78e8d8bef9SDimitry Andric     if (I->isReg() && !I->getReg().isVirtual() && I->isUse() &&
798bcb0991SDimitry Andric         RI.isPhysRegLiveAcrossClauses(I->getReg()))
800b57cec5SDimitry Andric       return false;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric   return true;
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric bool R600InstrInfo::isMov(unsigned Opcode) const {
860b57cec5SDimitry Andric   switch(Opcode) {
870b57cec5SDimitry Andric   default:
880b57cec5SDimitry Andric     return false;
890b57cec5SDimitry Andric   case R600::MOV:
900b57cec5SDimitry Andric   case R600::MOV_IMM_F32:
910b57cec5SDimitry Andric   case R600::MOV_IMM_I32:
920b57cec5SDimitry Andric     return true;
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric bool R600InstrInfo::isReductionOp(unsigned Opcode) const {
970b57cec5SDimitry Andric   return false;
980b57cec5SDimitry Andric }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric bool R600InstrInfo::isCubeOp(unsigned Opcode) const {
1010b57cec5SDimitry Andric   switch(Opcode) {
1020b57cec5SDimitry Andric     default: return false;
1030b57cec5SDimitry Andric     case R600::CUBE_r600_pseudo:
1040b57cec5SDimitry Andric     case R600::CUBE_r600_real:
1050b57cec5SDimitry Andric     case R600::CUBE_eg_pseudo:
1060b57cec5SDimitry Andric     case R600::CUBE_eg_real:
1070b57cec5SDimitry Andric       return true;
1080b57cec5SDimitry Andric   }
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric bool R600InstrInfo::isALUInstr(unsigned Opcode) const {
1120b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   return (TargetFlags & R600_InstFlag::ALU_INST);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric bool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {
1180b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   return ((TargetFlags & R600_InstFlag::OP1) |
1210b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::OP2) |
1220b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::OP3));
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric bool R600InstrInfo::isLDSInstr(unsigned Opcode) const {
1260b57cec5SDimitry Andric   unsigned TargetFlags = get(Opcode).TSFlags;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   return ((TargetFlags & R600_InstFlag::LDS_1A) |
1290b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::LDS_1A1D) |
1300b57cec5SDimitry Andric           (TargetFlags & R600_InstFlag::LDS_1A2D));
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {
1340b57cec5SDimitry Andric   return isLDSInstr(Opcode) && getOperandIdx(Opcode, R600::OpName::dst) != -1;
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {
1380b57cec5SDimitry Andric   if (isALUInstr(MI.getOpcode()))
1390b57cec5SDimitry Andric     return true;
1400b57cec5SDimitry Andric   if (isVector(MI) || isCubeOp(MI.getOpcode()))
1410b57cec5SDimitry Andric     return true;
1420b57cec5SDimitry Andric   switch (MI.getOpcode()) {
1430b57cec5SDimitry Andric   case R600::PRED_X:
1440b57cec5SDimitry Andric   case R600::INTERP_PAIR_XY:
1450b57cec5SDimitry Andric   case R600::INTERP_PAIR_ZW:
1460b57cec5SDimitry Andric   case R600::INTERP_VEC_LOAD:
1470b57cec5SDimitry Andric   case R600::COPY:
1480b57cec5SDimitry Andric   case R600::DOT_4:
1490b57cec5SDimitry Andric     return true;
1500b57cec5SDimitry Andric   default:
1510b57cec5SDimitry Andric     return false;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric }
1540b57cec5SDimitry Andric 
1550b57cec5SDimitry Andric bool R600InstrInfo::isTransOnly(unsigned Opcode) const {
1560b57cec5SDimitry Andric   if (ST.hasCaymanISA())
1570b57cec5SDimitry Andric     return false;
1580b57cec5SDimitry Andric   return (get(Opcode).getSchedClass() == R600::Sched::TransALU);
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {
1620b57cec5SDimitry Andric   return isTransOnly(MI.getOpcode());
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {
1660b57cec5SDimitry Andric   return (get(Opcode).getSchedClass() == R600::Sched::VecALU);
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {
1700b57cec5SDimitry Andric   return isVectorOnly(MI.getOpcode());
1710b57cec5SDimitry Andric }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric bool R600InstrInfo::isExport(unsigned Opcode) const {
1740b57cec5SDimitry Andric   return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
1780b57cec5SDimitry Andric   return ST.hasVertexCache() && IS_VTX(get(Opcode));
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {
1820b57cec5SDimitry Andric   const MachineFunction *MF = MI.getParent()->getParent();
1830b57cec5SDimitry Andric   return !AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
1840b57cec5SDimitry Andric          usesVertexCache(MI.getOpcode());
1850b57cec5SDimitry Andric }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
1880b57cec5SDimitry Andric   return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {
1920b57cec5SDimitry Andric   const MachineFunction *MF = MI.getParent()->getParent();
1930b57cec5SDimitry Andric   return (AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&
1940b57cec5SDimitry Andric           usesVertexCache(MI.getOpcode())) ||
1950b57cec5SDimitry Andric           usesTextureCache(MI.getOpcode());
1960b57cec5SDimitry Andric }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric bool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {
1990b57cec5SDimitry Andric   switch (Opcode) {
2000b57cec5SDimitry Andric   case R600::KILLGT:
2010b57cec5SDimitry Andric   case R600::GROUP_BARRIER:
2020b57cec5SDimitry Andric     return true;
2030b57cec5SDimitry Andric   default:
2040b57cec5SDimitry Andric     return false;
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {
2090b57cec5SDimitry Andric   return MI.findRegisterUseOperandIdx(R600::AR_X, false, &RI) != -1;
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {
2130b57cec5SDimitry Andric   return MI.findRegisterDefOperandIdx(R600::AR_X, false, false, &RI) != -1;
2140b57cec5SDimitry Andric }
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {
2170b57cec5SDimitry Andric   if (!isALUInstr(MI.getOpcode())) {
2180b57cec5SDimitry Andric     return false;
2190b57cec5SDimitry Andric   }
2200b57cec5SDimitry Andric   for (MachineInstr::const_mop_iterator I = MI.operands_begin(),
2210b57cec5SDimitry Andric                                         E = MI.operands_end();
2220b57cec5SDimitry Andric        I != E; ++I) {
223e8d8bef9SDimitry Andric     if (!I->isReg() || !I->isUse() || I->getReg().isVirtual())
2240b57cec5SDimitry Andric       continue;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric     if (R600::R600_LDS_SRC_REGRegClass.contains(I->getReg()))
2270b57cec5SDimitry Andric       return true;
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric   return false;
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric int R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {
2330b57cec5SDimitry Andric   static const unsigned SrcSelTable[][2] = {
2340b57cec5SDimitry Andric     {R600::OpName::src0, R600::OpName::src0_sel},
2350b57cec5SDimitry Andric     {R600::OpName::src1, R600::OpName::src1_sel},
2360b57cec5SDimitry Andric     {R600::OpName::src2, R600::OpName::src2_sel},
2370b57cec5SDimitry Andric     {R600::OpName::src0_X, R600::OpName::src0_sel_X},
2380b57cec5SDimitry Andric     {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
2390b57cec5SDimitry Andric     {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
2400b57cec5SDimitry Andric     {R600::OpName::src0_W, R600::OpName::src0_sel_W},
2410b57cec5SDimitry Andric     {R600::OpName::src1_X, R600::OpName::src1_sel_X},
2420b57cec5SDimitry Andric     {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
2430b57cec5SDimitry Andric     {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
2440b57cec5SDimitry Andric     {R600::OpName::src1_W, R600::OpName::src1_sel_W}
2450b57cec5SDimitry Andric   };
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric   for (const auto &Row : SrcSelTable) {
2480b57cec5SDimitry Andric     if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {
2490b57cec5SDimitry Andric       return getOperandIdx(Opcode, Row[1]);
2500b57cec5SDimitry Andric     }
2510b57cec5SDimitry Andric   }
2520b57cec5SDimitry Andric   return -1;
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric SmallVector<std::pair<MachineOperand *, int64_t>, 3>
2560b57cec5SDimitry Andric R600InstrInfo::getSrcs(MachineInstr &MI) const {
2570b57cec5SDimitry Andric   SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (MI.getOpcode() == R600::DOT_4) {
2600b57cec5SDimitry Andric     static const unsigned OpTable[8][2] = {
2610b57cec5SDimitry Andric       {R600::OpName::src0_X, R600::OpName::src0_sel_X},
2620b57cec5SDimitry Andric       {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},
2630b57cec5SDimitry Andric       {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},
2640b57cec5SDimitry Andric       {R600::OpName::src0_W, R600::OpName::src0_sel_W},
2650b57cec5SDimitry Andric       {R600::OpName::src1_X, R600::OpName::src1_sel_X},
2660b57cec5SDimitry Andric       {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},
2670b57cec5SDimitry Andric       {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},
2680b57cec5SDimitry Andric       {R600::OpName::src1_W, R600::OpName::src1_sel_W},
2690b57cec5SDimitry Andric     };
2700b57cec5SDimitry Andric 
271*0eae32dcSDimitry Andric     for (const auto &Op : OpTable) {
272*0eae32dcSDimitry Andric       MachineOperand &MO = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[0]));
2738bcb0991SDimitry Andric       Register Reg = MO.getReg();
2740b57cec5SDimitry Andric       if (Reg == R600::ALU_CONST) {
2750b57cec5SDimitry Andric         MachineOperand &Sel =
276*0eae32dcSDimitry Andric             MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
2770b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Sel.getImm()));
2780b57cec5SDimitry Andric         continue;
2790b57cec5SDimitry Andric       }
2800b57cec5SDimitry Andric     }
2810b57cec5SDimitry Andric     return Result;
2820b57cec5SDimitry Andric   }
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   static const unsigned OpTable[3][2] = {
2850b57cec5SDimitry Andric     {R600::OpName::src0, R600::OpName::src0_sel},
2860b57cec5SDimitry Andric     {R600::OpName::src1, R600::OpName::src1_sel},
2870b57cec5SDimitry Andric     {R600::OpName::src2, R600::OpName::src2_sel},
2880b57cec5SDimitry Andric   };
2890b57cec5SDimitry Andric 
290*0eae32dcSDimitry Andric   for (const auto &Op : OpTable) {
291*0eae32dcSDimitry Andric     int SrcIdx = getOperandIdx(MI.getOpcode(), Op[0]);
2920b57cec5SDimitry Andric     if (SrcIdx < 0)
2930b57cec5SDimitry Andric       break;
2940b57cec5SDimitry Andric     MachineOperand &MO = MI.getOperand(SrcIdx);
2958bcb0991SDimitry Andric     Register Reg = MO.getReg();
2960b57cec5SDimitry Andric     if (Reg == R600::ALU_CONST) {
297*0eae32dcSDimitry Andric       MachineOperand &Sel = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));
2980b57cec5SDimitry Andric       Result.push_back(std::make_pair(&MO, Sel.getImm()));
2990b57cec5SDimitry Andric       continue;
3000b57cec5SDimitry Andric     }
3010b57cec5SDimitry Andric     if (Reg == R600::ALU_LITERAL_X) {
3020b57cec5SDimitry Andric       MachineOperand &Operand =
3030b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
3040b57cec5SDimitry Andric       if (Operand.isImm()) {
3050b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Operand.getImm()));
3060b57cec5SDimitry Andric         continue;
3070b57cec5SDimitry Andric       }
3080b57cec5SDimitry Andric       assert(Operand.isGlobal());
3090b57cec5SDimitry Andric     }
3100b57cec5SDimitry Andric     Result.push_back(std::make_pair(&MO, 0));
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric   return Result;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric std::vector<std::pair<int, unsigned>>
3160b57cec5SDimitry Andric R600InstrInfo::ExtractSrcs(MachineInstr &MI,
3170b57cec5SDimitry Andric                            const DenseMap<unsigned, unsigned> &PV,
3180b57cec5SDimitry Andric                            unsigned &ConstCount) const {
3190b57cec5SDimitry Andric   ConstCount = 0;
3200b57cec5SDimitry Andric   const std::pair<int, unsigned> DummyPair(-1, 0);
3210b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> Result;
3220b57cec5SDimitry Andric   unsigned i = 0;
3230b57cec5SDimitry Andric   for (const auto &Src : getSrcs(MI)) {
3240b57cec5SDimitry Andric     ++i;
3258bcb0991SDimitry Andric     Register Reg = Src.first->getReg();
3260b57cec5SDimitry Andric     int Index = RI.getEncodingValue(Reg) & 0xff;
3270b57cec5SDimitry Andric     if (Reg == R600::OQAP) {
3280b57cec5SDimitry Andric       Result.push_back(std::make_pair(Index, 0U));
3290b57cec5SDimitry Andric     }
3300b57cec5SDimitry Andric     if (PV.find(Reg) != PV.end()) {
3310b57cec5SDimitry Andric       // 255 is used to tells its a PS/PV reg
3320b57cec5SDimitry Andric       Result.push_back(std::make_pair(255, 0U));
3330b57cec5SDimitry Andric       continue;
3340b57cec5SDimitry Andric     }
3350b57cec5SDimitry Andric     if (Index > 127) {
3360b57cec5SDimitry Andric       ConstCount++;
3370b57cec5SDimitry Andric       Result.push_back(DummyPair);
3380b57cec5SDimitry Andric       continue;
3390b57cec5SDimitry Andric     }
3400b57cec5SDimitry Andric     unsigned Chan = RI.getHWRegChan(Reg);
3410b57cec5SDimitry Andric     Result.push_back(std::make_pair(Index, Chan));
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric   for (; i < 3; ++i)
3440b57cec5SDimitry Andric     Result.push_back(DummyPair);
3450b57cec5SDimitry Andric   return Result;
3460b57cec5SDimitry Andric }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric static std::vector<std::pair<int, unsigned>>
3490b57cec5SDimitry Andric Swizzle(std::vector<std::pair<int, unsigned>> Src,
3500b57cec5SDimitry Andric         R600InstrInfo::BankSwizzle Swz) {
3510b57cec5SDimitry Andric   if (Src[0] == Src[1])
3520b57cec5SDimitry Andric     Src[1].first = -1;
3530b57cec5SDimitry Andric   switch (Swz) {
3540b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210:
3550b57cec5SDimitry Andric     break;
3560b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122:
3570b57cec5SDimitry Andric     std::swap(Src[1], Src[2]);
3580b57cec5SDimitry Andric     break;
3590b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221:
3600b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3610b57cec5SDimitry Andric     break;
3620b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212:
3630b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3640b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3650b57cec5SDimitry Andric     break;
3660b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_201:
3670b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3680b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3690b57cec5SDimitry Andric     break;
3700b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_210:
3710b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3720b57cec5SDimitry Andric     break;
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric   return Src;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
3780b57cec5SDimitry Andric   assert(Op < 3 && "Out of range swizzle index");
3790b57cec5SDimitry Andric   switch (Swz) {
3800b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210: {
3810b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 0};
3820b57cec5SDimitry Andric     return Cycles[Op];
3830b57cec5SDimitry Andric   }
3840b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122: {
3850b57cec5SDimitry Andric     unsigned Cycles[3] = { 1, 2, 2};
3860b57cec5SDimitry Andric     return Cycles[Op];
3870b57cec5SDimitry Andric   }
3880b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212: {
3890b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 2};
3900b57cec5SDimitry Andric     return Cycles[Op];
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221: {
3930b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 2, 1};
3940b57cec5SDimitry Andric     return Cycles[Op];
3950b57cec5SDimitry Andric   }
3960b57cec5SDimitry Andric   default:
3970b57cec5SDimitry Andric     llvm_unreachable("Wrong Swizzle for Trans Slot");
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric /// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
4020b57cec5SDimitry Andric /// in the same Instruction Group while meeting read port limitations given a
4030b57cec5SDimitry Andric /// Swz swizzle sequence.
4040b57cec5SDimitry Andric unsigned  R600InstrInfo::isLegalUpTo(
4050b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
4060b57cec5SDimitry Andric     const std::vector<R600InstrInfo::BankSwizzle> &Swz,
4070b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
4080b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
4090b57cec5SDimitry Andric   int Vector[4][3];
4100b57cec5SDimitry Andric   memset(Vector, -1, sizeof(Vector));
4110b57cec5SDimitry Andric   for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
4120b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &Srcs =
4130b57cec5SDimitry Andric         Swizzle(IGSrcs[i], Swz[i]);
4140b57cec5SDimitry Andric     for (unsigned j = 0; j < 3; j++) {
4150b57cec5SDimitry Andric       const std::pair<int, unsigned> &Src = Srcs[j];
4160b57cec5SDimitry Andric       if (Src.first < 0 || Src.first == 255)
4170b57cec5SDimitry Andric         continue;
4180b57cec5SDimitry Andric       if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
4190b57cec5SDimitry Andric         if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
4200b57cec5SDimitry Andric             Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
4210b57cec5SDimitry Andric             // The value from output queue A (denoted by register OQAP) can
4220b57cec5SDimitry Andric             // only be fetched during the first cycle.
4230b57cec5SDimitry Andric             return false;
4240b57cec5SDimitry Andric         }
4250b57cec5SDimitry Andric         // OQAP does not count towards the normal read port restrictions
4260b57cec5SDimitry Andric         continue;
4270b57cec5SDimitry Andric       }
4280b57cec5SDimitry Andric       if (Vector[Src.second][j] < 0)
4290b57cec5SDimitry Andric         Vector[Src.second][j] = Src.first;
4300b57cec5SDimitry Andric       if (Vector[Src.second][j] != Src.first)
4310b57cec5SDimitry Andric         return i;
4320b57cec5SDimitry Andric     }
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric   // Now check Trans Alu
4350b57cec5SDimitry Andric   for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
4360b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransSrcs[i];
4370b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
4380b57cec5SDimitry Andric     if (Src.first < 0)
4390b57cec5SDimitry Andric       continue;
4400b57cec5SDimitry Andric     if (Src.first == 255)
4410b57cec5SDimitry Andric       continue;
4420b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] < 0)
4430b57cec5SDimitry Andric       Vector[Src.second][Cycle] = Src.first;
4440b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] != Src.first)
4450b57cec5SDimitry Andric       return IGSrcs.size() - 1;
4460b57cec5SDimitry Andric   }
4470b57cec5SDimitry Andric   return IGSrcs.size();
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric /// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
4510b57cec5SDimitry Andric /// (in lexicographic term) swizzle sequence assuming that all swizzles after
4520b57cec5SDimitry Andric /// Idx can be skipped
4530b57cec5SDimitry Andric static bool
4540b57cec5SDimitry Andric NextPossibleSolution(
4550b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4560b57cec5SDimitry Andric     unsigned Idx) {
4570b57cec5SDimitry Andric   assert(Idx < SwzCandidate.size());
4580b57cec5SDimitry Andric   int ResetIdx = Idx;
4590b57cec5SDimitry Andric   while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
4600b57cec5SDimitry Andric     ResetIdx --;
4610b57cec5SDimitry Andric   for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
4620b57cec5SDimitry Andric     SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric   if (ResetIdx == -1)
4650b57cec5SDimitry Andric     return false;
4660b57cec5SDimitry Andric   int NextSwizzle = SwzCandidate[ResetIdx] + 1;
4670b57cec5SDimitry Andric   SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
4680b57cec5SDimitry Andric   return true;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric /// Enumerate all possible Swizzle sequence to find one that can meet all
4720b57cec5SDimitry Andric /// read port requirements.
4730b57cec5SDimitry Andric bool R600InstrInfo::FindSwizzleForVectorSlot(
4740b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
4750b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4760b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
4770b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
4780b57cec5SDimitry Andric   unsigned ValidUpTo = 0;
4790b57cec5SDimitry Andric   do {
4800b57cec5SDimitry Andric     ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
4810b57cec5SDimitry Andric     if (ValidUpTo == IGSrcs.size())
4820b57cec5SDimitry Andric       return true;
4830b57cec5SDimitry Andric   } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
4840b57cec5SDimitry Andric   return false;
4850b57cec5SDimitry Andric }
4860b57cec5SDimitry Andric 
4870b57cec5SDimitry Andric /// Instructions in Trans slot can't read gpr at cycle 0 if they also read
4880b57cec5SDimitry Andric /// a const, and can't read a gpr at cycle 1 if they read 2 const.
4890b57cec5SDimitry Andric static bool
4900b57cec5SDimitry Andric isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
4910b57cec5SDimitry Andric                   const std::vector<std::pair<int, unsigned>> &TransOps,
4920b57cec5SDimitry Andric                   unsigned ConstCount) {
4930b57cec5SDimitry Andric   // TransALU can't read 3 constants
4940b57cec5SDimitry Andric   if (ConstCount > 2)
4950b57cec5SDimitry Andric     return false;
4960b57cec5SDimitry Andric   for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
4970b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransOps[i];
4980b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
4990b57cec5SDimitry Andric     if (Src.first < 0)
5000b57cec5SDimitry Andric       continue;
5010b57cec5SDimitry Andric     if (ConstCount > 0 && Cycle == 0)
5020b57cec5SDimitry Andric       return false;
5030b57cec5SDimitry Andric     if (ConstCount > 1 && Cycle == 1)
5040b57cec5SDimitry Andric       return false;
5050b57cec5SDimitry Andric   }
5060b57cec5SDimitry Andric   return true;
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric 
5090b57cec5SDimitry Andric bool
5100b57cec5SDimitry Andric R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
5110b57cec5SDimitry Andric                                        const DenseMap<unsigned, unsigned> &PV,
5120b57cec5SDimitry Andric                                        std::vector<BankSwizzle> &ValidSwizzle,
5130b57cec5SDimitry Andric                                        bool isLastAluTrans)
5140b57cec5SDimitry Andric     const {
5150b57cec5SDimitry Andric   //Todo : support shared src0 - src1 operand
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
5180b57cec5SDimitry Andric   ValidSwizzle.clear();
5195ffd83dbSDimitry Andric   unsigned ConstCount;
5200b57cec5SDimitry Andric   BankSwizzle TransBS = ALU_VEC_012_SCL_210;
521*0eae32dcSDimitry Andric   for (MachineInstr *MI : IG) {
522*0eae32dcSDimitry Andric     IGSrcs.push_back(ExtractSrcs(*MI, PV, ConstCount));
523*0eae32dcSDimitry Andric     unsigned Op = getOperandIdx(MI->getOpcode(), R600::OpName::bank_swizzle);
524*0eae32dcSDimitry Andric     ValidSwizzle.push_back(
525*0eae32dcSDimitry Andric         (R600InstrInfo::BankSwizzle)MI->getOperand(Op).getImm());
5260b57cec5SDimitry Andric   }
5270b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> TransOps;
5280b57cec5SDimitry Andric   if (!isLastAluTrans)
5290b57cec5SDimitry Andric     return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   TransOps = std::move(IGSrcs.back());
5320b57cec5SDimitry Andric   IGSrcs.pop_back();
5330b57cec5SDimitry Andric   ValidSwizzle.pop_back();
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   static const R600InstrInfo::BankSwizzle TransSwz[] = {
5360b57cec5SDimitry Andric     ALU_VEC_012_SCL_210,
5370b57cec5SDimitry Andric     ALU_VEC_021_SCL_122,
5380b57cec5SDimitry Andric     ALU_VEC_120_SCL_212,
5390b57cec5SDimitry Andric     ALU_VEC_102_SCL_221
5400b57cec5SDimitry Andric   };
541*0eae32dcSDimitry Andric   for (R600InstrInfo::BankSwizzle TransBS : TransSwz) {
5420b57cec5SDimitry Andric     if (!isConstCompatible(TransBS, TransOps, ConstCount))
5430b57cec5SDimitry Andric       continue;
5440b57cec5SDimitry Andric     bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
5450b57cec5SDimitry Andric         TransBS);
5460b57cec5SDimitry Andric     if (Result) {
5470b57cec5SDimitry Andric       ValidSwizzle.push_back(TransBS);
5480b57cec5SDimitry Andric       return true;
5490b57cec5SDimitry Andric     }
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   return false;
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric bool
5560b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
5570b57cec5SDimitry Andric     const {
5580b57cec5SDimitry Andric   assert (Consts.size() <= 12 && "Too many operands in instructions group");
5590b57cec5SDimitry Andric   unsigned Pair1 = 0, Pair2 = 0;
560*0eae32dcSDimitry Andric   for (unsigned Const : Consts) {
561*0eae32dcSDimitry Andric     unsigned ReadConstHalf = Const & 2;
562*0eae32dcSDimitry Andric     unsigned ReadConstIndex = Const & (~3);
5630b57cec5SDimitry Andric     unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
5640b57cec5SDimitry Andric     if (!Pair1) {
5650b57cec5SDimitry Andric       Pair1 = ReadHalfConst;
5660b57cec5SDimitry Andric       continue;
5670b57cec5SDimitry Andric     }
5680b57cec5SDimitry Andric     if (Pair1 == ReadHalfConst)
5690b57cec5SDimitry Andric       continue;
5700b57cec5SDimitry Andric     if (!Pair2) {
5710b57cec5SDimitry Andric       Pair2 = ReadHalfConst;
5720b57cec5SDimitry Andric       continue;
5730b57cec5SDimitry Andric     }
5740b57cec5SDimitry Andric     if (Pair2 != ReadHalfConst)
5750b57cec5SDimitry Andric       return false;
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric   return true;
5780b57cec5SDimitry Andric }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric bool
5810b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
5820b57cec5SDimitry Andric     const {
5830b57cec5SDimitry Andric   std::vector<unsigned> Consts;
5840b57cec5SDimitry Andric   SmallSet<int64_t, 4> Literals;
585*0eae32dcSDimitry Andric   for (MachineInstr *MI : MIs) {
586*0eae32dcSDimitry Andric     if (!isALUInstr(MI->getOpcode()))
5870b57cec5SDimitry Andric       continue;
5880b57cec5SDimitry Andric 
589*0eae32dcSDimitry Andric     for (const auto &Src : getSrcs(*MI)) {
5900b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_LITERAL_X)
5910b57cec5SDimitry Andric         Literals.insert(Src.second);
5920b57cec5SDimitry Andric       if (Literals.size() > 4)
5930b57cec5SDimitry Andric         return false;
5940b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_CONST)
5950b57cec5SDimitry Andric         Consts.push_back(Src.second);
5960b57cec5SDimitry Andric       if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
5970b57cec5SDimitry Andric           R600::R600_KC1RegClass.contains(Src.first->getReg())) {
5980b57cec5SDimitry Andric         unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
5990b57cec5SDimitry Andric         unsigned Chan = RI.getHWRegChan(Src.first->getReg());
6000b57cec5SDimitry Andric         Consts.push_back((Index << 2) | Chan);
6010b57cec5SDimitry Andric       }
6020b57cec5SDimitry Andric     }
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric   return fitsConstReadLimitations(Consts);
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric DFAPacketizer *
6080b57cec5SDimitry Andric R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
6090b57cec5SDimitry Andric   const InstrItineraryData *II = STI.getInstrItineraryData();
6100b57cec5SDimitry Andric   return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric static bool
6140b57cec5SDimitry Andric isPredicateSetter(unsigned Opcode) {
6150b57cec5SDimitry Andric   switch (Opcode) {
6160b57cec5SDimitry Andric   case R600::PRED_X:
6170b57cec5SDimitry Andric     return true;
6180b57cec5SDimitry Andric   default:
6190b57cec5SDimitry Andric     return false;
6200b57cec5SDimitry Andric   }
6210b57cec5SDimitry Andric }
6220b57cec5SDimitry Andric 
6230b57cec5SDimitry Andric static MachineInstr *
6240b57cec5SDimitry Andric findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
6250b57cec5SDimitry Andric                              MachineBasicBlock::iterator I) {
6260b57cec5SDimitry Andric   while (I != MBB.begin()) {
6270b57cec5SDimitry Andric     --I;
6280b57cec5SDimitry Andric     MachineInstr &MI = *I;
6290b57cec5SDimitry Andric     if (isPredicateSetter(MI.getOpcode()))
6300b57cec5SDimitry Andric       return &MI;
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   return nullptr;
6340b57cec5SDimitry Andric }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric static
6370b57cec5SDimitry Andric bool isJump(unsigned Opcode) {
6380b57cec5SDimitry Andric   return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
6390b57cec5SDimitry Andric }
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric static bool isBranch(unsigned Opcode) {
6420b57cec5SDimitry Andric   return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
6430b57cec5SDimitry Andric       Opcode == R600::BRANCH_COND_f32;
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
6470b57cec5SDimitry Andric                                   MachineBasicBlock *&TBB,
6480b57cec5SDimitry Andric                                   MachineBasicBlock *&FBB,
6490b57cec5SDimitry Andric                                   SmallVectorImpl<MachineOperand> &Cond,
6500b57cec5SDimitry Andric                                   bool AllowModify) const {
6515ffd83dbSDimitry Andric   // Most of the following comes from the ARM implementation of analyzeBranch
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   // If the block has no terminators, it just falls into the block after it.
6540b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
6550b57cec5SDimitry Andric   if (I == MBB.end())
6560b57cec5SDimitry Andric     return false;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   // R600::BRANCH* instructions are only available after isel and are not
6590b57cec5SDimitry Andric   // handled
6600b57cec5SDimitry Andric   if (isBranch(I->getOpcode()))
6610b57cec5SDimitry Andric     return true;
6620b57cec5SDimitry Andric   if (!isJump(I->getOpcode())) {
6630b57cec5SDimitry Andric     return false;
6640b57cec5SDimitry Andric   }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric   // Remove successive JUMP
6670b57cec5SDimitry Andric   while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
6680b57cec5SDimitry Andric       MachineBasicBlock::iterator PriorI = std::prev(I);
6690b57cec5SDimitry Andric       if (AllowModify)
6700b57cec5SDimitry Andric         I->removeFromParent();
6710b57cec5SDimitry Andric       I = PriorI;
6720b57cec5SDimitry Andric   }
6730b57cec5SDimitry Andric   MachineInstr &LastInst = *I;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   // If there is only one terminator instruction, process it.
6760b57cec5SDimitry Andric   unsigned LastOpc = LastInst.getOpcode();
6770b57cec5SDimitry Andric   if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
6780b57cec5SDimitry Andric     if (LastOpc == R600::JUMP) {
6790b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
6800b57cec5SDimitry Andric       return false;
6810b57cec5SDimitry Andric     } else if (LastOpc == R600::JUMP_COND) {
6820b57cec5SDimitry Andric       auto predSet = I;
6830b57cec5SDimitry Andric       while (!isPredicateSetter(predSet->getOpcode())) {
6840b57cec5SDimitry Andric         predSet = --I;
6850b57cec5SDimitry Andric       }
6860b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
6870b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(1));
6880b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(2));
6890b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
6900b57cec5SDimitry Andric       return false;
6910b57cec5SDimitry Andric     }
6920b57cec5SDimitry Andric     return true;  // Can't handle indirect branch.
6930b57cec5SDimitry Andric   }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   // Get the instruction before it if it is a terminator.
6960b57cec5SDimitry Andric   MachineInstr &SecondLastInst = *I;
6970b57cec5SDimitry Andric   unsigned SecondLastOpc = SecondLastInst.getOpcode();
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   // If the block ends with a B and a Bcc, handle it.
7000b57cec5SDimitry Andric   if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
7010b57cec5SDimitry Andric     auto predSet = --I;
7020b57cec5SDimitry Andric     while (!isPredicateSetter(predSet->getOpcode())) {
7030b57cec5SDimitry Andric       predSet = --I;
7040b57cec5SDimitry Andric     }
7050b57cec5SDimitry Andric     TBB = SecondLastInst.getOperand(0).getMBB();
7060b57cec5SDimitry Andric     FBB = LastInst.getOperand(0).getMBB();
7070b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(1));
7080b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(2));
7090b57cec5SDimitry Andric     Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
7100b57cec5SDimitry Andric     return false;
7110b57cec5SDimitry Andric   }
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric   // Otherwise, can't handle this.
7140b57cec5SDimitry Andric   return true;
7150b57cec5SDimitry Andric }
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric static
7180b57cec5SDimitry Andric MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
7190b57cec5SDimitry Andric   for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
7200b57cec5SDimitry Andric       It != E; ++It) {
7210b57cec5SDimitry Andric     if (It->getOpcode() == R600::CF_ALU ||
7220b57cec5SDimitry Andric         It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
7230b57cec5SDimitry Andric       return It.getReverse();
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric   return MBB.end();
7260b57cec5SDimitry Andric }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,
7290b57cec5SDimitry Andric                                      MachineBasicBlock *TBB,
7300b57cec5SDimitry Andric                                      MachineBasicBlock *FBB,
7310b57cec5SDimitry Andric                                      ArrayRef<MachineOperand> Cond,
7320b57cec5SDimitry Andric                                      const DebugLoc &DL,
7330b57cec5SDimitry Andric                                      int *BytesAdded) const {
7340b57cec5SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
7350b57cec5SDimitry Andric   assert(!BytesAdded && "code size not handled");
7360b57cec5SDimitry Andric 
7370b57cec5SDimitry Andric   if (!FBB) {
7380b57cec5SDimitry Andric     if (Cond.empty()) {
7390b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
7400b57cec5SDimitry Andric       return 1;
7410b57cec5SDimitry Andric     } else {
7420b57cec5SDimitry Andric       MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
7430b57cec5SDimitry Andric       assert(PredSet && "No previous predicate !");
7440b57cec5SDimitry Andric       addFlag(*PredSet, 0, MO_FLAG_PUSH);
7450b57cec5SDimitry Andric       PredSet->getOperand(2).setImm(Cond[1].getImm());
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP_COND))
7480b57cec5SDimitry Andric              .addMBB(TBB)
7490b57cec5SDimitry Andric              .addReg(R600::PREDICATE_BIT, RegState::Kill);
7500b57cec5SDimitry Andric       MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
7510b57cec5SDimitry Andric       if (CfAlu == MBB.end())
7520b57cec5SDimitry Andric         return 1;
7530b57cec5SDimitry Andric       assert (CfAlu->getOpcode() == R600::CF_ALU);
7540b57cec5SDimitry Andric       CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
7550b57cec5SDimitry Andric       return 1;
7560b57cec5SDimitry Andric     }
7570b57cec5SDimitry Andric   } else {
7580b57cec5SDimitry Andric     MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
7590b57cec5SDimitry Andric     assert(PredSet && "No previous predicate !");
7600b57cec5SDimitry Andric     addFlag(*PredSet, 0, MO_FLAG_PUSH);
7610b57cec5SDimitry Andric     PredSet->getOperand(2).setImm(Cond[1].getImm());
7620b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP_COND))
7630b57cec5SDimitry Andric             .addMBB(TBB)
7640b57cec5SDimitry Andric             .addReg(R600::PREDICATE_BIT, RegState::Kill);
7650b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
7660b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
7670b57cec5SDimitry Andric     if (CfAlu == MBB.end())
7680b57cec5SDimitry Andric       return 2;
7690b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU);
7700b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
7710b57cec5SDimitry Andric     return 2;
7720b57cec5SDimitry Andric   }
7730b57cec5SDimitry Andric }
7740b57cec5SDimitry Andric 
7750b57cec5SDimitry Andric unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,
7760b57cec5SDimitry Andric                                      int *BytesRemoved) const {
7770b57cec5SDimitry Andric   assert(!BytesRemoved && "code size not handled");
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   // Note : we leave PRED* instructions there.
7800b57cec5SDimitry Andric   // They may be needed when predicating instructions.
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   if (I == MBB.begin()) {
7850b57cec5SDimitry Andric     return 0;
7860b57cec5SDimitry Andric   }
7870b57cec5SDimitry Andric   --I;
7880b57cec5SDimitry Andric   switch (I->getOpcode()) {
7890b57cec5SDimitry Andric   default:
7900b57cec5SDimitry Andric     return 0;
7910b57cec5SDimitry Andric   case R600::JUMP_COND: {
7920b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
7930b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
7940b57cec5SDimitry Andric     I->eraseFromParent();
7950b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
7960b57cec5SDimitry Andric     if (CfAlu == MBB.end())
7970b57cec5SDimitry Andric       break;
7980b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
7990b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
8000b57cec5SDimitry Andric     break;
8010b57cec5SDimitry Andric   }
8020b57cec5SDimitry Andric   case R600::JUMP:
8030b57cec5SDimitry Andric     I->eraseFromParent();
8040b57cec5SDimitry Andric     break;
8050b57cec5SDimitry Andric   }
8060b57cec5SDimitry Andric   I = MBB.end();
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric   if (I == MBB.begin()) {
8090b57cec5SDimitry Andric     return 1;
8100b57cec5SDimitry Andric   }
8110b57cec5SDimitry Andric   --I;
8120b57cec5SDimitry Andric   switch (I->getOpcode()) {
8130b57cec5SDimitry Andric     // FIXME: only one case??
8140b57cec5SDimitry Andric   default:
8150b57cec5SDimitry Andric     return 1;
8160b57cec5SDimitry Andric   case R600::JUMP_COND: {
8170b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
8180b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
8190b57cec5SDimitry Andric     I->eraseFromParent();
8200b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
8210b57cec5SDimitry Andric     if (CfAlu == MBB.end())
8220b57cec5SDimitry Andric       break;
8230b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
8240b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
8250b57cec5SDimitry Andric     break;
8260b57cec5SDimitry Andric   }
8270b57cec5SDimitry Andric   case R600::JUMP:
8280b57cec5SDimitry Andric     I->eraseFromParent();
8290b57cec5SDimitry Andric     break;
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric   return 2;
8320b57cec5SDimitry Andric }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
8350b57cec5SDimitry Andric   int idx = MI.findFirstPredOperandIdx();
8360b57cec5SDimitry Andric   if (idx < 0)
8370b57cec5SDimitry Andric     return false;
8380b57cec5SDimitry Andric 
8398bcb0991SDimitry Andric   Register Reg = MI.getOperand(idx).getReg();
8400b57cec5SDimitry Andric   switch (Reg) {
8410b57cec5SDimitry Andric   default: return false;
8420b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
8430b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
8440b57cec5SDimitry Andric   case R600::PREDICATE_BIT:
8450b57cec5SDimitry Andric     return true;
8460b57cec5SDimitry Andric   }
8470b57cec5SDimitry Andric }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {
8500b57cec5SDimitry Andric   // XXX: KILL* instructions can be predicated, but they must be the last
8510b57cec5SDimitry Andric   // instruction in a clause, so this means any instructions after them cannot
8520b57cec5SDimitry Andric   // be predicated.  Until we have proper support for instruction clauses in the
8530b57cec5SDimitry Andric   // backend, we will mark KILL* instructions as unpredicable.
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric   if (MI.getOpcode() == R600::KILLGT) {
8560b57cec5SDimitry Andric     return false;
8570b57cec5SDimitry Andric   } else if (MI.getOpcode() == R600::CF_ALU) {
8580b57cec5SDimitry Andric     // If the clause start in the middle of MBB then the MBB has more
8590b57cec5SDimitry Andric     // than a single clause, unable to predicate several clauses.
8600b57cec5SDimitry Andric     if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
8610b57cec5SDimitry Andric       return false;
8620b57cec5SDimitry Andric     // TODO: We don't support KC merging atm
8630b57cec5SDimitry Andric     return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
8640b57cec5SDimitry Andric   } else if (isVector(MI)) {
8650b57cec5SDimitry Andric     return false;
8660b57cec5SDimitry Andric   } else {
8670b57cec5SDimitry Andric     return TargetInstrInfo::isPredicable(MI);
8680b57cec5SDimitry Andric   }
8690b57cec5SDimitry Andric }
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric bool
8720b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
8730b57cec5SDimitry Andric                                    unsigned NumCycles,
8740b57cec5SDimitry Andric                                    unsigned ExtraPredCycles,
8750b57cec5SDimitry Andric                                    BranchProbability Probability) const{
8760b57cec5SDimitry Andric   return true;
8770b57cec5SDimitry Andric }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric bool
8800b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
8810b57cec5SDimitry Andric                                    unsigned NumTCycles,
8820b57cec5SDimitry Andric                                    unsigned ExtraTCycles,
8830b57cec5SDimitry Andric                                    MachineBasicBlock &FMBB,
8840b57cec5SDimitry Andric                                    unsigned NumFCycles,
8850b57cec5SDimitry Andric                                    unsigned ExtraFCycles,
8860b57cec5SDimitry Andric                                    BranchProbability Probability) const {
8870b57cec5SDimitry Andric   return true;
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
8900b57cec5SDimitry Andric bool
8910b57cec5SDimitry Andric R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
8920b57cec5SDimitry Andric                                          unsigned NumCycles,
8930b57cec5SDimitry Andric                                          BranchProbability Probability)
8940b57cec5SDimitry Andric                                          const {
8950b57cec5SDimitry Andric   return true;
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric bool
8990b57cec5SDimitry Andric R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
9000b57cec5SDimitry Andric                                          MachineBasicBlock &FMBB) const {
9010b57cec5SDimitry Andric   return false;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric bool
9050b57cec5SDimitry Andric R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
9060b57cec5SDimitry Andric   MachineOperand &MO = Cond[1];
9070b57cec5SDimitry Andric   switch (MO.getImm()) {
9080b57cec5SDimitry Andric   case R600::PRED_SETE_INT:
9090b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE_INT);
9100b57cec5SDimitry Andric     break;
9110b57cec5SDimitry Andric   case R600::PRED_SETNE_INT:
9120b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE_INT);
9130b57cec5SDimitry Andric     break;
9140b57cec5SDimitry Andric   case R600::PRED_SETE:
9150b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE);
9160b57cec5SDimitry Andric     break;
9170b57cec5SDimitry Andric   case R600::PRED_SETNE:
9180b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE);
9190b57cec5SDimitry Andric     break;
9200b57cec5SDimitry Andric   default:
9210b57cec5SDimitry Andric     return true;
9220b57cec5SDimitry Andric   }
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   MachineOperand &MO2 = Cond[2];
9250b57cec5SDimitry Andric   switch (MO2.getReg()) {
9260b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
9270b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ONE);
9280b57cec5SDimitry Andric     break;
9290b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
9300b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ZERO);
9310b57cec5SDimitry Andric     break;
9320b57cec5SDimitry Andric   default:
9330b57cec5SDimitry Andric     return true;
9340b57cec5SDimitry Andric   }
9350b57cec5SDimitry Andric   return false;
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric 
938e8d8bef9SDimitry Andric bool R600InstrInfo::ClobbersPredicate(MachineInstr &MI,
939e8d8bef9SDimitry Andric                                       std::vector<MachineOperand> &Pred,
940e8d8bef9SDimitry Andric                                       bool SkipDead) const {
9410b57cec5SDimitry Andric   return isPredicateSetter(MI.getOpcode());
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,
9450b57cec5SDimitry Andric                                          ArrayRef<MachineOperand> Pred) const {
9460b57cec5SDimitry Andric   int PIdx = MI.findFirstPredOperandIdx();
9470b57cec5SDimitry Andric 
9480b57cec5SDimitry Andric   if (MI.getOpcode() == R600::CF_ALU) {
9490b57cec5SDimitry Andric     MI.getOperand(8).setImm(0);
9500b57cec5SDimitry Andric     return true;
9510b57cec5SDimitry Andric   }
9520b57cec5SDimitry Andric 
9530b57cec5SDimitry Andric   if (MI.getOpcode() == R600::DOT_4) {
9540b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
9550b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9560b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
9570b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9580b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
9590b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9600b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
9610b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9620b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
9630b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
9640b57cec5SDimitry Andric     return true;
9650b57cec5SDimitry Andric   }
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric   if (PIdx != -1) {
9680b57cec5SDimitry Andric     MachineOperand &PMO = MI.getOperand(PIdx);
9690b57cec5SDimitry Andric     PMO.setReg(Pred[2].getReg());
9700b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
9710b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
9720b57cec5SDimitry Andric     return true;
9730b57cec5SDimitry Andric   }
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric   return false;
9760b57cec5SDimitry Andric }
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
9790b57cec5SDimitry Andric   return 2;
9800b57cec5SDimitry Andric }
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
9830b57cec5SDimitry Andric                                             const MachineInstr &,
9840b57cec5SDimitry Andric                                             unsigned *PredCost) const {
9850b57cec5SDimitry Andric   if (PredCost)
9860b57cec5SDimitry Andric     *PredCost = 2;
9870b57cec5SDimitry Andric   return 2;
9880b57cec5SDimitry Andric }
9890b57cec5SDimitry Andric 
9900b57cec5SDimitry Andric unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
9910b57cec5SDimitry Andric                                                    unsigned Channel) const {
9920b57cec5SDimitry Andric   assert(Channel == 0);
9930b57cec5SDimitry Andric   return RegIndex;
9940b57cec5SDimitry Andric }
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
9970b57cec5SDimitry Andric   switch (MI.getOpcode()) {
9980b57cec5SDimitry Andric   default: {
9990b57cec5SDimitry Andric     MachineBasicBlock *MBB = MI.getParent();
10000b57cec5SDimitry Andric     int OffsetOpIdx =
10010b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
10020b57cec5SDimitry Andric     // addr is a custom operand with multiple MI operands, and only the
10030b57cec5SDimitry Andric     // first MI operand is given a name.
10040b57cec5SDimitry Andric     int RegOpIdx = OffsetOpIdx + 1;
10050b57cec5SDimitry Andric     int ChanOpIdx =
10060b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
10070b57cec5SDimitry Andric     if (isRegisterLoad(MI)) {
10080b57cec5SDimitry Andric       int DstOpIdx =
10090b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
10100b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
10110b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
10120b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
10138bcb0991SDimitry Andric       Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
10140b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
10150b57cec5SDimitry Andric         buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
10160b57cec5SDimitry Andric                       getIndirectAddrRegClass()->getRegister(Address));
10170b57cec5SDimitry Andric       } else {
10180b57cec5SDimitry Andric         buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
10190b57cec5SDimitry Andric                           OffsetReg);
10200b57cec5SDimitry Andric       }
10210b57cec5SDimitry Andric     } else if (isRegisterStore(MI)) {
10220b57cec5SDimitry Andric       int ValOpIdx =
10230b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
10240b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
10250b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
10260b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
10278bcb0991SDimitry Andric       Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
10280b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
10290b57cec5SDimitry Andric         buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
10300b57cec5SDimitry Andric                       MI.getOperand(ValOpIdx).getReg());
10310b57cec5SDimitry Andric       } else {
10320b57cec5SDimitry Andric         buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
10330b57cec5SDimitry Andric                            calculateIndirectAddress(RegIndex, Channel),
10340b57cec5SDimitry Andric                            OffsetReg);
10350b57cec5SDimitry Andric       }
10360b57cec5SDimitry Andric     } else {
10370b57cec5SDimitry Andric       return false;
10380b57cec5SDimitry Andric     }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric     MBB->erase(MI);
10410b57cec5SDimitry Andric     return true;
10420b57cec5SDimitry Andric   }
10430b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V2:
10440b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V4:
10450b57cec5SDimitry Andric     buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
10460b57cec5SDimitry Andric                       RI.getHWRegIndex(MI.getOperand(1).getReg()), //  Address
10470b57cec5SDimitry Andric                       MI.getOperand(2).getReg(),
10480b57cec5SDimitry Andric                       RI.getHWRegChan(MI.getOperand(1).getReg()));
10490b57cec5SDimitry Andric     break;
10500b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V2:
10510b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V4:
10520b57cec5SDimitry Andric     buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
10530b57cec5SDimitry Andric                        RI.getHWRegIndex(MI.getOperand(1).getReg()),   // Address
10540b57cec5SDimitry Andric                        MI.getOperand(3).getReg(),                     // Offset
10550b57cec5SDimitry Andric                        RI.getHWRegChan(MI.getOperand(1).getReg()));   // Channel
10560b57cec5SDimitry Andric     break;
10570b57cec5SDimitry Andric   }
10580b57cec5SDimitry Andric   MI.eraseFromParent();
10590b57cec5SDimitry Andric   return true;
10600b57cec5SDimitry Andric }
10610b57cec5SDimitry Andric 
10620b57cec5SDimitry Andric void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,
10630b57cec5SDimitry Andric                                              const MachineFunction &MF,
10640b57cec5SDimitry Andric                                              const R600RegisterInfo &TRI) const {
10650b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
10660b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   unsigned StackWidth = TFL->getStackWidth(MF);
10690b57cec5SDimitry Andric   int End = getIndirectIndexEnd(MF);
10700b57cec5SDimitry Andric 
10710b57cec5SDimitry Andric   if (End == -1)
10720b57cec5SDimitry Andric     return;
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
10750b57cec5SDimitry Andric     for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
10760b57cec5SDimitry Andric       unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
10770b57cec5SDimitry Andric       TRI.reserveRegisterTuples(Reserved, Reg);
10780b57cec5SDimitry Andric     }
10790b57cec5SDimitry Andric   }
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
10830b57cec5SDimitry Andric   return &R600::R600_TReg32_XRegClass;
10840b57cec5SDimitry Andric }
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
10870b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
10880b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
10890b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
10900b57cec5SDimitry Andric   return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
10910b57cec5SDimitry Andric }
10920b57cec5SDimitry Andric 
10930b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
10940b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
10950b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
10960b57cec5SDimitry Andric                                        unsigned OffsetReg,
10970b57cec5SDimitry Andric                                        unsigned AddrChan) const {
10980b57cec5SDimitry Andric   unsigned AddrReg;
10990b57cec5SDimitry Andric   switch (AddrChan) {
11000b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
11010b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
11020b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
11030b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
11040b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
11070b57cec5SDimitry Andric                                                R600::AR_X, OffsetReg);
11080b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
11110b57cec5SDimitry Andric                                       AddrReg, ValueReg)
11120b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
11130b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
11140b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::dst_rel, 1);
11150b57cec5SDimitry Andric   return Mov;
11160b57cec5SDimitry Andric }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
11190b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
11200b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
11210b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
11220b57cec5SDimitry Andric   return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
11230b57cec5SDimitry Andric }
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
11260b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
11270b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
11280b57cec5SDimitry Andric                                        unsigned OffsetReg,
11290b57cec5SDimitry Andric                                        unsigned AddrChan) const {
11300b57cec5SDimitry Andric   unsigned AddrReg;
11310b57cec5SDimitry Andric   switch (AddrChan) {
11320b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
11330b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
11340b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
11350b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
11360b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
11370b57cec5SDimitry Andric   }
11380b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
11390b57cec5SDimitry Andric                                                        R600::AR_X,
11400b57cec5SDimitry Andric                                                        OffsetReg);
11410b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
11420b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
11430b57cec5SDimitry Andric                                       ValueReg,
11440b57cec5SDimitry Andric                                       AddrReg)
11450b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
11460b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
11470b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::src0_rel, 1);
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   return Mov;
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric 
11520b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
11530b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
11540b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
11550b57cec5SDimitry Andric   int Offset = -1;
11560b57cec5SDimitry Andric 
11570b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
11580b57cec5SDimitry Andric     return -1;
11590b57cec5SDimitry Andric   }
11600b57cec5SDimitry Andric 
11610b57cec5SDimitry Andric   if (MRI.livein_empty()) {
11620b57cec5SDimitry Andric     return 0;
11630b57cec5SDimitry Andric   }
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric   const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
11660b57cec5SDimitry Andric   for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1167e8d8bef9SDimitry Andric     Register Reg = LI.first;
1168e8d8bef9SDimitry Andric     if (Reg.isVirtual() || !IndirectRC->contains(Reg))
11690b57cec5SDimitry Andric       continue;
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric     unsigned RegIndex;
11720b57cec5SDimitry Andric     unsigned RegEnd;
11730b57cec5SDimitry Andric     for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
11740b57cec5SDimitry Andric                                                           ++RegIndex) {
1175e8d8bef9SDimitry Andric       if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)
11760b57cec5SDimitry Andric         break;
11770b57cec5SDimitry Andric     }
11780b57cec5SDimitry Andric     Offset = std::max(Offset, (int)RegIndex);
11790b57cec5SDimitry Andric   }
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   return Offset + 1;
11820b57cec5SDimitry Andric }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
11850b57cec5SDimitry Andric   int Offset = 0;
11860b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric   // Variable sized objects are not supported
11890b57cec5SDimitry Andric   if (MFI.hasVarSizedObjects()) {
11900b57cec5SDimitry Andric     return -1;
11910b57cec5SDimitry Andric   }
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
11940b57cec5SDimitry Andric     return -1;
11950b57cec5SDimitry Andric   }
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
11980b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
11990b57cec5SDimitry Andric 
12005ffd83dbSDimitry Andric   Register IgnoredFrameReg;
1201e8d8bef9SDimitry Andric   Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   return getIndirectIndexBegin(MF) + Offset;
12040b57cec5SDimitry Andric }
12050b57cec5SDimitry Andric 
12060b57cec5SDimitry Andric unsigned R600InstrInfo::getMaxAlusPerClause() const {
12070b57cec5SDimitry Andric   return 115;
12080b57cec5SDimitry Andric }
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
12110b57cec5SDimitry Andric                                                   MachineBasicBlock::iterator I,
12120b57cec5SDimitry Andric                                                   unsigned Opcode,
12130b57cec5SDimitry Andric                                                   unsigned DstReg,
12140b57cec5SDimitry Andric                                                   unsigned Src0Reg,
12150b57cec5SDimitry Andric                                                   unsigned Src1Reg) const {
12160b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
12170b57cec5SDimitry Andric     DstReg);           // $dst
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric   if (Src1Reg) {
12200b57cec5SDimitry Andric     MIB.addImm(0)     // $update_exec_mask
12210b57cec5SDimitry Andric        .addImm(0);    // $update_predicate
12220b57cec5SDimitry Andric   }
12230b57cec5SDimitry Andric   MIB.addImm(1)        // $write
12240b57cec5SDimitry Andric      .addImm(0)        // $omod
12250b57cec5SDimitry Andric      .addImm(0)        // $dst_rel
12260b57cec5SDimitry Andric      .addImm(0)        // $dst_clamp
12270b57cec5SDimitry Andric      .addReg(Src0Reg)  // $src0
12280b57cec5SDimitry Andric      .addImm(0)        // $src0_neg
12290b57cec5SDimitry Andric      .addImm(0)        // $src0_rel
12300b57cec5SDimitry Andric      .addImm(0)        // $src0_abs
12310b57cec5SDimitry Andric      .addImm(-1);       // $src0_sel
12320b57cec5SDimitry Andric 
12330b57cec5SDimitry Andric   if (Src1Reg) {
12340b57cec5SDimitry Andric     MIB.addReg(Src1Reg) // $src1
12350b57cec5SDimitry Andric        .addImm(0)       // $src1_neg
12360b57cec5SDimitry Andric        .addImm(0)       // $src1_rel
12370b57cec5SDimitry Andric        .addImm(0)       // $src1_abs
12380b57cec5SDimitry Andric        .addImm(-1);      // $src1_sel
12390b57cec5SDimitry Andric   }
12400b57cec5SDimitry Andric 
12410b57cec5SDimitry Andric   //XXX: The r600g finalizer expects this to be 1, once we've moved the
12420b57cec5SDimitry Andric   //scheduling to the backend, we can change the default to 0.
12430b57cec5SDimitry Andric   MIB.addImm(1)        // $last
12440b57cec5SDimitry Andric       .addReg(R600::PRED_SEL_OFF) // $pred_sel
12450b57cec5SDimitry Andric       .addImm(0)         // $literal
12460b57cec5SDimitry Andric       .addImm(0);        // $bank_swizzle
12470b57cec5SDimitry Andric 
12480b57cec5SDimitry Andric   return MIB;
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric #define OPERAND_CASE(Label) \
12520b57cec5SDimitry Andric   case Label: { \
12530b57cec5SDimitry Andric     static const unsigned Ops[] = \
12540b57cec5SDimitry Andric     { \
12550b57cec5SDimitry Andric       Label##_X, \
12560b57cec5SDimitry Andric       Label##_Y, \
12570b57cec5SDimitry Andric       Label##_Z, \
12580b57cec5SDimitry Andric       Label##_W \
12590b57cec5SDimitry Andric     }; \
12600b57cec5SDimitry Andric     return Ops[Slot]; \
12610b57cec5SDimitry Andric   }
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric static unsigned getSlotedOps(unsigned  Op, unsigned Slot) {
12640b57cec5SDimitry Andric   switch (Op) {
12650b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_exec_mask)
12660b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_pred)
12670b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::write)
12680b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::omod)
12690b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::dst_rel)
12700b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::clamp)
12710b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0)
12720b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_neg)
12730b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_rel)
12740b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_abs)
12750b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_sel)
12760b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1)
12770b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_neg)
12780b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_rel)
12790b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_abs)
12800b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_sel)
12810b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::pred_sel)
12820b57cec5SDimitry Andric   default:
12830b57cec5SDimitry Andric     llvm_unreachable("Wrong Operand");
12840b57cec5SDimitry Andric   }
12850b57cec5SDimitry Andric }
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric #undef OPERAND_CASE
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
12900b57cec5SDimitry Andric     MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
12910b57cec5SDimitry Andric     const {
12920b57cec5SDimitry Andric   assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
12930b57cec5SDimitry Andric   unsigned Opcode;
12940b57cec5SDimitry Andric   if (ST.getGeneration() <= AMDGPUSubtarget::R700)
12950b57cec5SDimitry Andric     Opcode = R600::DOT4_r600;
12960b57cec5SDimitry Andric   else
12970b57cec5SDimitry Andric     Opcode = R600::DOT4_eg;
12980b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MI;
12990b57cec5SDimitry Andric   MachineOperand &Src0 = MI->getOperand(
13000b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
13010b57cec5SDimitry Andric   MachineOperand &Src1 = MI->getOperand(
13020b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
13030b57cec5SDimitry Andric   MachineInstr *MIB = buildDefaultInstruction(
13040b57cec5SDimitry Andric       MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
13050b57cec5SDimitry Andric   static const unsigned  Operands[14] = {
13060b57cec5SDimitry Andric     R600::OpName::update_exec_mask,
13070b57cec5SDimitry Andric     R600::OpName::update_pred,
13080b57cec5SDimitry Andric     R600::OpName::write,
13090b57cec5SDimitry Andric     R600::OpName::omod,
13100b57cec5SDimitry Andric     R600::OpName::dst_rel,
13110b57cec5SDimitry Andric     R600::OpName::clamp,
13120b57cec5SDimitry Andric     R600::OpName::src0_neg,
13130b57cec5SDimitry Andric     R600::OpName::src0_rel,
13140b57cec5SDimitry Andric     R600::OpName::src0_abs,
13150b57cec5SDimitry Andric     R600::OpName::src0_sel,
13160b57cec5SDimitry Andric     R600::OpName::src1_neg,
13170b57cec5SDimitry Andric     R600::OpName::src1_rel,
13180b57cec5SDimitry Andric     R600::OpName::src1_abs,
13190b57cec5SDimitry Andric     R600::OpName::src1_sel,
13200b57cec5SDimitry Andric   };
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric   MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
13230b57cec5SDimitry Andric       getSlotedOps(R600::OpName::pred_sel, Slot)));
13240b57cec5SDimitry Andric   MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
13250b57cec5SDimitry Andric       .setReg(MO.getReg());
13260b57cec5SDimitry Andric 
1327*0eae32dcSDimitry Andric   for (unsigned Operand : Operands) {
13280b57cec5SDimitry Andric     MachineOperand &MO = MI->getOperand(
1329*0eae32dcSDimitry Andric         getOperandIdx(MI->getOpcode(), getSlotedOps(Operand, Slot)));
13300b57cec5SDimitry Andric     assert (MO.isImm());
1331*0eae32dcSDimitry Andric     setImmOperand(*MIB, Operand, MO.getImm());
13320b57cec5SDimitry Andric   }
13330b57cec5SDimitry Andric   MIB->getOperand(20).setImm(0);
13340b57cec5SDimitry Andric   return MIB;
13350b57cec5SDimitry Andric }
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
13380b57cec5SDimitry Andric                                          MachineBasicBlock::iterator I,
13390b57cec5SDimitry Andric                                          unsigned DstReg,
13400b57cec5SDimitry Andric                                          uint64_t Imm) const {
13410b57cec5SDimitry Andric   MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
13420b57cec5SDimitry Andric                                                   R600::ALU_LITERAL_X);
13430b57cec5SDimitry Andric   setImmOperand(*MovImm, R600::OpName::literal, Imm);
13440b57cec5SDimitry Andric   return MovImm;
13450b57cec5SDimitry Andric }
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
13480b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
13490b57cec5SDimitry Andric                                        unsigned DstReg, unsigned SrcReg) const {
13500b57cec5SDimitry Andric   return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
13510b57cec5SDimitry Andric }
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
13540b57cec5SDimitry Andric   return getOperandIdx(MI.getOpcode(), Op);
13550b57cec5SDimitry Andric }
13560b57cec5SDimitry Andric 
13570b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
13580b57cec5SDimitry Andric   return R600::getNamedOperandIdx(Opcode, Op);
13590b57cec5SDimitry Andric }
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric void R600InstrInfo::setImmOperand(MachineInstr &MI, unsigned Op,
13620b57cec5SDimitry Andric                                   int64_t Imm) const {
13630b57cec5SDimitry Andric   int Idx = getOperandIdx(MI, Op);
13640b57cec5SDimitry Andric   assert(Idx != -1 && "Operand not supported for this instruction.");
13650b57cec5SDimitry Andric   assert(MI.getOperand(Idx).isImm());
13660b57cec5SDimitry Andric   MI.getOperand(Idx).setImm(Imm);
13670b57cec5SDimitry Andric }
13680b57cec5SDimitry Andric 
13690b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13700b57cec5SDimitry Andric // Instruction flag getters/setters
13710b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
13740b57cec5SDimitry Andric                                          unsigned Flag) const {
13750b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
13760b57cec5SDimitry Andric   int FlagIndex = 0;
13770b57cec5SDimitry Andric   if (Flag != 0) {
13780b57cec5SDimitry Andric     // If we pass something other than the default value of Flag to this
13790b57cec5SDimitry Andric     // function, it means we are want to set a flag on an instruction
13800b57cec5SDimitry Andric     // that uses native encoding.
13810b57cec5SDimitry Andric     assert(HAS_NATIVE_OPERANDS(TargetFlags));
13820b57cec5SDimitry Andric     bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
13830b57cec5SDimitry Andric     switch (Flag) {
13840b57cec5SDimitry Andric     case MO_FLAG_CLAMP:
13850b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
13860b57cec5SDimitry Andric       break;
13870b57cec5SDimitry Andric     case MO_FLAG_MASK:
13880b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::write);
13890b57cec5SDimitry Andric       break;
13900b57cec5SDimitry Andric     case MO_FLAG_NOT_LAST:
13910b57cec5SDimitry Andric     case MO_FLAG_LAST:
13920b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::last);
13930b57cec5SDimitry Andric       break;
13940b57cec5SDimitry Andric     case MO_FLAG_NEG:
13950b57cec5SDimitry Andric       switch (SrcIdx) {
13960b57cec5SDimitry Andric       case 0:
13970b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
13980b57cec5SDimitry Andric         break;
13990b57cec5SDimitry Andric       case 1:
14000b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
14010b57cec5SDimitry Andric         break;
14020b57cec5SDimitry Andric       case 2:
14030b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
14040b57cec5SDimitry Andric         break;
14050b57cec5SDimitry Andric       }
14060b57cec5SDimitry Andric       break;
14070b57cec5SDimitry Andric 
14080b57cec5SDimitry Andric     case MO_FLAG_ABS:
14090b57cec5SDimitry Andric       assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
14100b57cec5SDimitry Andric                        "instructions.");
14110b57cec5SDimitry Andric       (void)IsOP3;
14120b57cec5SDimitry Andric       switch (SrcIdx) {
14130b57cec5SDimitry Andric       case 0:
14140b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
14150b57cec5SDimitry Andric         break;
14160b57cec5SDimitry Andric       case 1:
14170b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
14180b57cec5SDimitry Andric         break;
14190b57cec5SDimitry Andric       }
14200b57cec5SDimitry Andric       break;
14210b57cec5SDimitry Andric 
14220b57cec5SDimitry Andric     default:
14230b57cec5SDimitry Andric       FlagIndex = -1;
14240b57cec5SDimitry Andric       break;
14250b57cec5SDimitry Andric     }
14260b57cec5SDimitry Andric     assert(FlagIndex != -1 && "Flag not supported for this instruction");
14270b57cec5SDimitry Andric   } else {
14280b57cec5SDimitry Andric       FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
14290b57cec5SDimitry Andric       assert(FlagIndex != 0 &&
14300b57cec5SDimitry Andric          "Instruction flags not supported for this instruction");
14310b57cec5SDimitry Andric   }
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric   MachineOperand &FlagOp = MI.getOperand(FlagIndex);
14340b57cec5SDimitry Andric   assert(FlagOp.isImm());
14350b57cec5SDimitry Andric   return FlagOp;
14360b57cec5SDimitry Andric }
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
14390b57cec5SDimitry Andric                             unsigned Flag) const {
14400b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
14410b57cec5SDimitry Andric   if (Flag == 0) {
14420b57cec5SDimitry Andric     return;
14430b57cec5SDimitry Andric   }
14440b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
14450b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
14460b57cec5SDimitry Andric     if (Flag == MO_FLAG_NOT_LAST) {
14470b57cec5SDimitry Andric       clearFlag(MI, Operand, MO_FLAG_LAST);
14480b57cec5SDimitry Andric     } else if (Flag == MO_FLAG_MASK) {
14490b57cec5SDimitry Andric       clearFlag(MI, Operand, Flag);
14500b57cec5SDimitry Andric     } else {
14510b57cec5SDimitry Andric       FlagOp.setImm(1);
14520b57cec5SDimitry Andric     }
14530b57cec5SDimitry Andric   } else {
14540b57cec5SDimitry Andric       MachineOperand &FlagOp = getFlagOp(MI, Operand);
14550b57cec5SDimitry Andric       FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
14560b57cec5SDimitry Andric   }
14570b57cec5SDimitry Andric }
14580b57cec5SDimitry Andric 
14590b57cec5SDimitry Andric void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
14600b57cec5SDimitry Andric                               unsigned Flag) const {
14610b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
14620b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
14630b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
14640b57cec5SDimitry Andric     FlagOp.setImm(0);
14650b57cec5SDimitry Andric   } else {
14660b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI);
14670b57cec5SDimitry Andric     unsigned InstFlags = FlagOp.getImm();
14680b57cec5SDimitry Andric     InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
14690b57cec5SDimitry Andric     FlagOp.setImm(InstFlags);
14700b57cec5SDimitry Andric   }
14710b57cec5SDimitry Andric }
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric unsigned R600InstrInfo::getAddressSpaceForPseudoSourceKind(
14740b57cec5SDimitry Andric     unsigned Kind) const {
14750b57cec5SDimitry Andric   switch (Kind) {
14760b57cec5SDimitry Andric   case PseudoSourceValue::Stack:
14770b57cec5SDimitry Andric   case PseudoSourceValue::FixedStack:
14780b57cec5SDimitry Andric     return AMDGPUAS::PRIVATE_ADDRESS;
14790b57cec5SDimitry Andric   case PseudoSourceValue::ConstantPool:
14800b57cec5SDimitry Andric   case PseudoSourceValue::GOT:
14810b57cec5SDimitry Andric   case PseudoSourceValue::JumpTable:
14820b57cec5SDimitry Andric   case PseudoSourceValue::GlobalValueCallEntry:
14830b57cec5SDimitry Andric   case PseudoSourceValue::ExternalSymbolCallEntry:
14840b57cec5SDimitry Andric   case PseudoSourceValue::TargetCustom:
14850b57cec5SDimitry Andric     return AMDGPUAS::CONSTANT_ADDRESS;
14860b57cec5SDimitry Andric   }
14870b57cec5SDimitry Andric 
14880b57cec5SDimitry Andric   llvm_unreachable("Invalid pseudo source kind");
14890b57cec5SDimitry Andric }
1490