xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AMDGPU/R600InstrInfo.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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"
16*349cc55cSDimitry Andric #include "MCTargetDesc/R600MCTargetDesc.h"
17*349cc55cSDimitry 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 
2710b57cec5SDimitry Andric     for (unsigned j = 0; j < 8; j++) {
2720b57cec5SDimitry Andric       MachineOperand &MO =
2730b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][0]));
2748bcb0991SDimitry Andric       Register Reg = MO.getReg();
2750b57cec5SDimitry Andric       if (Reg == R600::ALU_CONST) {
2760b57cec5SDimitry Andric         MachineOperand &Sel =
2770b57cec5SDimitry Andric             MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
2780b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Sel.getImm()));
2790b57cec5SDimitry Andric         continue;
2800b57cec5SDimitry Andric       }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric     }
2830b57cec5SDimitry Andric     return Result;
2840b57cec5SDimitry Andric   }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   static const unsigned OpTable[3][2] = {
2870b57cec5SDimitry Andric     {R600::OpName::src0, R600::OpName::src0_sel},
2880b57cec5SDimitry Andric     {R600::OpName::src1, R600::OpName::src1_sel},
2890b57cec5SDimitry Andric     {R600::OpName::src2, R600::OpName::src2_sel},
2900b57cec5SDimitry Andric   };
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   for (unsigned j = 0; j < 3; j++) {
2930b57cec5SDimitry Andric     int SrcIdx = getOperandIdx(MI.getOpcode(), OpTable[j][0]);
2940b57cec5SDimitry Andric     if (SrcIdx < 0)
2950b57cec5SDimitry Andric       break;
2960b57cec5SDimitry Andric     MachineOperand &MO = MI.getOperand(SrcIdx);
2978bcb0991SDimitry Andric     Register Reg = MO.getReg();
2980b57cec5SDimitry Andric     if (Reg == R600::ALU_CONST) {
2990b57cec5SDimitry Andric       MachineOperand &Sel =
3000b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), OpTable[j][1]));
3010b57cec5SDimitry Andric       Result.push_back(std::make_pair(&MO, Sel.getImm()));
3020b57cec5SDimitry Andric       continue;
3030b57cec5SDimitry Andric     }
3040b57cec5SDimitry Andric     if (Reg == R600::ALU_LITERAL_X) {
3050b57cec5SDimitry Andric       MachineOperand &Operand =
3060b57cec5SDimitry Andric           MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));
3070b57cec5SDimitry Andric       if (Operand.isImm()) {
3080b57cec5SDimitry Andric         Result.push_back(std::make_pair(&MO, Operand.getImm()));
3090b57cec5SDimitry Andric         continue;
3100b57cec5SDimitry Andric       }
3110b57cec5SDimitry Andric       assert(Operand.isGlobal());
3120b57cec5SDimitry Andric     }
3130b57cec5SDimitry Andric     Result.push_back(std::make_pair(&MO, 0));
3140b57cec5SDimitry Andric   }
3150b57cec5SDimitry Andric   return Result;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric std::vector<std::pair<int, unsigned>>
3190b57cec5SDimitry Andric R600InstrInfo::ExtractSrcs(MachineInstr &MI,
3200b57cec5SDimitry Andric                            const DenseMap<unsigned, unsigned> &PV,
3210b57cec5SDimitry Andric                            unsigned &ConstCount) const {
3220b57cec5SDimitry Andric   ConstCount = 0;
3230b57cec5SDimitry Andric   const std::pair<int, unsigned> DummyPair(-1, 0);
3240b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> Result;
3250b57cec5SDimitry Andric   unsigned i = 0;
3260b57cec5SDimitry Andric   for (const auto &Src : getSrcs(MI)) {
3270b57cec5SDimitry Andric     ++i;
3288bcb0991SDimitry Andric     Register Reg = Src.first->getReg();
3290b57cec5SDimitry Andric     int Index = RI.getEncodingValue(Reg) & 0xff;
3300b57cec5SDimitry Andric     if (Reg == R600::OQAP) {
3310b57cec5SDimitry Andric       Result.push_back(std::make_pair(Index, 0U));
3320b57cec5SDimitry Andric     }
3330b57cec5SDimitry Andric     if (PV.find(Reg) != PV.end()) {
3340b57cec5SDimitry Andric       // 255 is used to tells its a PS/PV reg
3350b57cec5SDimitry Andric       Result.push_back(std::make_pair(255, 0U));
3360b57cec5SDimitry Andric       continue;
3370b57cec5SDimitry Andric     }
3380b57cec5SDimitry Andric     if (Index > 127) {
3390b57cec5SDimitry Andric       ConstCount++;
3400b57cec5SDimitry Andric       Result.push_back(DummyPair);
3410b57cec5SDimitry Andric       continue;
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric     unsigned Chan = RI.getHWRegChan(Reg);
3440b57cec5SDimitry Andric     Result.push_back(std::make_pair(Index, Chan));
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric   for (; i < 3; ++i)
3470b57cec5SDimitry Andric     Result.push_back(DummyPair);
3480b57cec5SDimitry Andric   return Result;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric static std::vector<std::pair<int, unsigned>>
3520b57cec5SDimitry Andric Swizzle(std::vector<std::pair<int, unsigned>> Src,
3530b57cec5SDimitry Andric         R600InstrInfo::BankSwizzle Swz) {
3540b57cec5SDimitry Andric   if (Src[0] == Src[1])
3550b57cec5SDimitry Andric     Src[1].first = -1;
3560b57cec5SDimitry Andric   switch (Swz) {
3570b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210:
3580b57cec5SDimitry Andric     break;
3590b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122:
3600b57cec5SDimitry Andric     std::swap(Src[1], Src[2]);
3610b57cec5SDimitry Andric     break;
3620b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221:
3630b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3640b57cec5SDimitry Andric     break;
3650b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212:
3660b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3670b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3680b57cec5SDimitry Andric     break;
3690b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_201:
3700b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3710b57cec5SDimitry Andric     std::swap(Src[0], Src[1]);
3720b57cec5SDimitry Andric     break;
3730b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_210:
3740b57cec5SDimitry Andric     std::swap(Src[0], Src[2]);
3750b57cec5SDimitry Andric     break;
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric   return Src;
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
3810b57cec5SDimitry Andric   assert(Op < 3 && "Out of range swizzle index");
3820b57cec5SDimitry Andric   switch (Swz) {
3830b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_012_SCL_210: {
3840b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 0};
3850b57cec5SDimitry Andric     return Cycles[Op];
3860b57cec5SDimitry Andric   }
3870b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_021_SCL_122: {
3880b57cec5SDimitry Andric     unsigned Cycles[3] = { 1, 2, 2};
3890b57cec5SDimitry Andric     return Cycles[Op];
3900b57cec5SDimitry Andric   }
3910b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_120_SCL_212: {
3920b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 1, 2};
3930b57cec5SDimitry Andric     return Cycles[Op];
3940b57cec5SDimitry Andric   }
3950b57cec5SDimitry Andric   case R600InstrInfo::ALU_VEC_102_SCL_221: {
3960b57cec5SDimitry Andric     unsigned Cycles[3] = { 2, 2, 1};
3970b57cec5SDimitry Andric     return Cycles[Op];
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric   default:
4000b57cec5SDimitry Andric     llvm_unreachable("Wrong Swizzle for Trans Slot");
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric }
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric /// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
4050b57cec5SDimitry Andric /// in the same Instruction Group while meeting read port limitations given a
4060b57cec5SDimitry Andric /// Swz swizzle sequence.
4070b57cec5SDimitry Andric unsigned  R600InstrInfo::isLegalUpTo(
4080b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
4090b57cec5SDimitry Andric     const std::vector<R600InstrInfo::BankSwizzle> &Swz,
4100b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
4110b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
4120b57cec5SDimitry Andric   int Vector[4][3];
4130b57cec5SDimitry Andric   memset(Vector, -1, sizeof(Vector));
4140b57cec5SDimitry Andric   for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
4150b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &Srcs =
4160b57cec5SDimitry Andric         Swizzle(IGSrcs[i], Swz[i]);
4170b57cec5SDimitry Andric     for (unsigned j = 0; j < 3; j++) {
4180b57cec5SDimitry Andric       const std::pair<int, unsigned> &Src = Srcs[j];
4190b57cec5SDimitry Andric       if (Src.first < 0 || Src.first == 255)
4200b57cec5SDimitry Andric         continue;
4210b57cec5SDimitry Andric       if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {
4220b57cec5SDimitry Andric         if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
4230b57cec5SDimitry Andric             Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
4240b57cec5SDimitry Andric             // The value from output queue A (denoted by register OQAP) can
4250b57cec5SDimitry Andric             // only be fetched during the first cycle.
4260b57cec5SDimitry Andric             return false;
4270b57cec5SDimitry Andric         }
4280b57cec5SDimitry Andric         // OQAP does not count towards the normal read port restrictions
4290b57cec5SDimitry Andric         continue;
4300b57cec5SDimitry Andric       }
4310b57cec5SDimitry Andric       if (Vector[Src.second][j] < 0)
4320b57cec5SDimitry Andric         Vector[Src.second][j] = Src.first;
4330b57cec5SDimitry Andric       if (Vector[Src.second][j] != Src.first)
4340b57cec5SDimitry Andric         return i;
4350b57cec5SDimitry Andric     }
4360b57cec5SDimitry Andric   }
4370b57cec5SDimitry Andric   // Now check Trans Alu
4380b57cec5SDimitry Andric   for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
4390b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransSrcs[i];
4400b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
4410b57cec5SDimitry Andric     if (Src.first < 0)
4420b57cec5SDimitry Andric       continue;
4430b57cec5SDimitry Andric     if (Src.first == 255)
4440b57cec5SDimitry Andric       continue;
4450b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] < 0)
4460b57cec5SDimitry Andric       Vector[Src.second][Cycle] = Src.first;
4470b57cec5SDimitry Andric     if (Vector[Src.second][Cycle] != Src.first)
4480b57cec5SDimitry Andric       return IGSrcs.size() - 1;
4490b57cec5SDimitry Andric   }
4500b57cec5SDimitry Andric   return IGSrcs.size();
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric /// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
4540b57cec5SDimitry Andric /// (in lexicographic term) swizzle sequence assuming that all swizzles after
4550b57cec5SDimitry Andric /// Idx can be skipped
4560b57cec5SDimitry Andric static bool
4570b57cec5SDimitry Andric NextPossibleSolution(
4580b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4590b57cec5SDimitry Andric     unsigned Idx) {
4600b57cec5SDimitry Andric   assert(Idx < SwzCandidate.size());
4610b57cec5SDimitry Andric   int ResetIdx = Idx;
4620b57cec5SDimitry Andric   while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
4630b57cec5SDimitry Andric     ResetIdx --;
4640b57cec5SDimitry Andric   for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
4650b57cec5SDimitry Andric     SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
4660b57cec5SDimitry Andric   }
4670b57cec5SDimitry Andric   if (ResetIdx == -1)
4680b57cec5SDimitry Andric     return false;
4690b57cec5SDimitry Andric   int NextSwizzle = SwzCandidate[ResetIdx] + 1;
4700b57cec5SDimitry Andric   SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
4710b57cec5SDimitry Andric   return true;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric /// Enumerate all possible Swizzle sequence to find one that can meet all
4750b57cec5SDimitry Andric /// read port requirements.
4760b57cec5SDimitry Andric bool R600InstrInfo::FindSwizzleForVectorSlot(
4770b57cec5SDimitry Andric     const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,
4780b57cec5SDimitry Andric     std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4790b57cec5SDimitry Andric     const std::vector<std::pair<int, unsigned>> &TransSrcs,
4800b57cec5SDimitry Andric     R600InstrInfo::BankSwizzle TransSwz) const {
4810b57cec5SDimitry Andric   unsigned ValidUpTo = 0;
4820b57cec5SDimitry Andric   do {
4830b57cec5SDimitry Andric     ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
4840b57cec5SDimitry Andric     if (ValidUpTo == IGSrcs.size())
4850b57cec5SDimitry Andric       return true;
4860b57cec5SDimitry Andric   } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
4870b57cec5SDimitry Andric   return false;
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric /// Instructions in Trans slot can't read gpr at cycle 0 if they also read
4910b57cec5SDimitry Andric /// a const, and can't read a gpr at cycle 1 if they read 2 const.
4920b57cec5SDimitry Andric static bool
4930b57cec5SDimitry Andric isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
4940b57cec5SDimitry Andric                   const std::vector<std::pair<int, unsigned>> &TransOps,
4950b57cec5SDimitry Andric                   unsigned ConstCount) {
4960b57cec5SDimitry Andric   // TransALU can't read 3 constants
4970b57cec5SDimitry Andric   if (ConstCount > 2)
4980b57cec5SDimitry Andric     return false;
4990b57cec5SDimitry Andric   for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
5000b57cec5SDimitry Andric     const std::pair<int, unsigned> &Src = TransOps[i];
5010b57cec5SDimitry Andric     unsigned Cycle = getTransSwizzle(TransSwz, i);
5020b57cec5SDimitry Andric     if (Src.first < 0)
5030b57cec5SDimitry Andric       continue;
5040b57cec5SDimitry Andric     if (ConstCount > 0 && Cycle == 0)
5050b57cec5SDimitry Andric       return false;
5060b57cec5SDimitry Andric     if (ConstCount > 1 && Cycle == 1)
5070b57cec5SDimitry Andric       return false;
5080b57cec5SDimitry Andric   }
5090b57cec5SDimitry Andric   return true;
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric bool
5130b57cec5SDimitry Andric R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
5140b57cec5SDimitry Andric                                        const DenseMap<unsigned, unsigned> &PV,
5150b57cec5SDimitry Andric                                        std::vector<BankSwizzle> &ValidSwizzle,
5160b57cec5SDimitry Andric                                        bool isLastAluTrans)
5170b57cec5SDimitry Andric     const {
5180b57cec5SDimitry Andric   //Todo : support shared src0 - src1 operand
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;
5210b57cec5SDimitry Andric   ValidSwizzle.clear();
5225ffd83dbSDimitry Andric   unsigned ConstCount;
5230b57cec5SDimitry Andric   BankSwizzle TransBS = ALU_VEC_012_SCL_210;
5240b57cec5SDimitry Andric   for (unsigned i = 0, e = IG.size(); i < e; ++i) {
5250b57cec5SDimitry Andric     IGSrcs.push_back(ExtractSrcs(*IG[i], PV, ConstCount));
5260b57cec5SDimitry Andric     unsigned Op = getOperandIdx(IG[i]->getOpcode(),
5270b57cec5SDimitry Andric         R600::OpName::bank_swizzle);
5280b57cec5SDimitry Andric     ValidSwizzle.push_back( (R600InstrInfo::BankSwizzle)
5290b57cec5SDimitry Andric         IG[i]->getOperand(Op).getImm());
5300b57cec5SDimitry Andric   }
5310b57cec5SDimitry Andric   std::vector<std::pair<int, unsigned>> TransOps;
5320b57cec5SDimitry Andric   if (!isLastAluTrans)
5330b57cec5SDimitry Andric     return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   TransOps = std::move(IGSrcs.back());
5360b57cec5SDimitry Andric   IGSrcs.pop_back();
5370b57cec5SDimitry Andric   ValidSwizzle.pop_back();
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   static const R600InstrInfo::BankSwizzle TransSwz[] = {
5400b57cec5SDimitry Andric     ALU_VEC_012_SCL_210,
5410b57cec5SDimitry Andric     ALU_VEC_021_SCL_122,
5420b57cec5SDimitry Andric     ALU_VEC_120_SCL_212,
5430b57cec5SDimitry Andric     ALU_VEC_102_SCL_221
5440b57cec5SDimitry Andric   };
5450b57cec5SDimitry Andric   for (unsigned i = 0; i < 4; i++) {
5460b57cec5SDimitry Andric     TransBS = TransSwz[i];
5470b57cec5SDimitry Andric     if (!isConstCompatible(TransBS, TransOps, ConstCount))
5480b57cec5SDimitry Andric       continue;
5490b57cec5SDimitry Andric     bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
5500b57cec5SDimitry Andric         TransBS);
5510b57cec5SDimitry Andric     if (Result) {
5520b57cec5SDimitry Andric       ValidSwizzle.push_back(TransBS);
5530b57cec5SDimitry Andric       return true;
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   return false;
5580b57cec5SDimitry Andric }
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric bool
5610b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
5620b57cec5SDimitry Andric     const {
5630b57cec5SDimitry Andric   assert (Consts.size() <= 12 && "Too many operands in instructions group");
5640b57cec5SDimitry Andric   unsigned Pair1 = 0, Pair2 = 0;
5650b57cec5SDimitry Andric   for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
5660b57cec5SDimitry Andric     unsigned ReadConstHalf = Consts[i] & 2;
5670b57cec5SDimitry Andric     unsigned ReadConstIndex = Consts[i] & (~3);
5680b57cec5SDimitry Andric     unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
5690b57cec5SDimitry Andric     if (!Pair1) {
5700b57cec5SDimitry Andric       Pair1 = ReadHalfConst;
5710b57cec5SDimitry Andric       continue;
5720b57cec5SDimitry Andric     }
5730b57cec5SDimitry Andric     if (Pair1 == ReadHalfConst)
5740b57cec5SDimitry Andric       continue;
5750b57cec5SDimitry Andric     if (!Pair2) {
5760b57cec5SDimitry Andric       Pair2 = ReadHalfConst;
5770b57cec5SDimitry Andric       continue;
5780b57cec5SDimitry Andric     }
5790b57cec5SDimitry Andric     if (Pair2 != ReadHalfConst)
5800b57cec5SDimitry Andric       return false;
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric   return true;
5830b57cec5SDimitry Andric }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric bool
5860b57cec5SDimitry Andric R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
5870b57cec5SDimitry Andric     const {
5880b57cec5SDimitry Andric   std::vector<unsigned> Consts;
5890b57cec5SDimitry Andric   SmallSet<int64_t, 4> Literals;
5900b57cec5SDimitry Andric   for (unsigned i = 0, n = MIs.size(); i < n; i++) {
5910b57cec5SDimitry Andric     MachineInstr &MI = *MIs[i];
5920b57cec5SDimitry Andric     if (!isALUInstr(MI.getOpcode()))
5930b57cec5SDimitry Andric       continue;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric     for (const auto &Src : getSrcs(MI)) {
5960b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_LITERAL_X)
5970b57cec5SDimitry Andric         Literals.insert(Src.second);
5980b57cec5SDimitry Andric       if (Literals.size() > 4)
5990b57cec5SDimitry Andric         return false;
6000b57cec5SDimitry Andric       if (Src.first->getReg() == R600::ALU_CONST)
6010b57cec5SDimitry Andric         Consts.push_back(Src.second);
6020b57cec5SDimitry Andric       if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||
6030b57cec5SDimitry Andric           R600::R600_KC1RegClass.contains(Src.first->getReg())) {
6040b57cec5SDimitry Andric         unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
6050b57cec5SDimitry Andric         unsigned Chan = RI.getHWRegChan(Src.first->getReg());
6060b57cec5SDimitry Andric         Consts.push_back((Index << 2) | Chan);
6070b57cec5SDimitry Andric       }
6080b57cec5SDimitry Andric     }
6090b57cec5SDimitry Andric   }
6100b57cec5SDimitry Andric   return fitsConstReadLimitations(Consts);
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric DFAPacketizer *
6140b57cec5SDimitry Andric R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {
6150b57cec5SDimitry Andric   const InstrItineraryData *II = STI.getInstrItineraryData();
6160b57cec5SDimitry Andric   return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);
6170b57cec5SDimitry Andric }
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric static bool
6200b57cec5SDimitry Andric isPredicateSetter(unsigned Opcode) {
6210b57cec5SDimitry Andric   switch (Opcode) {
6220b57cec5SDimitry Andric   case R600::PRED_X:
6230b57cec5SDimitry Andric     return true;
6240b57cec5SDimitry Andric   default:
6250b57cec5SDimitry Andric     return false;
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric }
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric static MachineInstr *
6300b57cec5SDimitry Andric findFirstPredicateSetterFrom(MachineBasicBlock &MBB,
6310b57cec5SDimitry Andric                              MachineBasicBlock::iterator I) {
6320b57cec5SDimitry Andric   while (I != MBB.begin()) {
6330b57cec5SDimitry Andric     --I;
6340b57cec5SDimitry Andric     MachineInstr &MI = *I;
6350b57cec5SDimitry Andric     if (isPredicateSetter(MI.getOpcode()))
6360b57cec5SDimitry Andric       return &MI;
6370b57cec5SDimitry Andric   }
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   return nullptr;
6400b57cec5SDimitry Andric }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric static
6430b57cec5SDimitry Andric bool isJump(unsigned Opcode) {
6440b57cec5SDimitry Andric   return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;
6450b57cec5SDimitry Andric }
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric static bool isBranch(unsigned Opcode) {
6480b57cec5SDimitry Andric   return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||
6490b57cec5SDimitry Andric       Opcode == R600::BRANCH_COND_f32;
6500b57cec5SDimitry Andric }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
6530b57cec5SDimitry Andric                                   MachineBasicBlock *&TBB,
6540b57cec5SDimitry Andric                                   MachineBasicBlock *&FBB,
6550b57cec5SDimitry Andric                                   SmallVectorImpl<MachineOperand> &Cond,
6560b57cec5SDimitry Andric                                   bool AllowModify) const {
6575ffd83dbSDimitry Andric   // Most of the following comes from the ARM implementation of analyzeBranch
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   // If the block has no terminators, it just falls into the block after it.
6600b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
6610b57cec5SDimitry Andric   if (I == MBB.end())
6620b57cec5SDimitry Andric     return false;
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   // R600::BRANCH* instructions are only available after isel and are not
6650b57cec5SDimitry Andric   // handled
6660b57cec5SDimitry Andric   if (isBranch(I->getOpcode()))
6670b57cec5SDimitry Andric     return true;
6680b57cec5SDimitry Andric   if (!isJump(I->getOpcode())) {
6690b57cec5SDimitry Andric     return false;
6700b57cec5SDimitry Andric   }
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   // Remove successive JUMP
6730b57cec5SDimitry Andric   while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {
6740b57cec5SDimitry Andric       MachineBasicBlock::iterator PriorI = std::prev(I);
6750b57cec5SDimitry Andric       if (AllowModify)
6760b57cec5SDimitry Andric         I->removeFromParent();
6770b57cec5SDimitry Andric       I = PriorI;
6780b57cec5SDimitry Andric   }
6790b57cec5SDimitry Andric   MachineInstr &LastInst = *I;
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric   // If there is only one terminator instruction, process it.
6820b57cec5SDimitry Andric   unsigned LastOpc = LastInst.getOpcode();
6830b57cec5SDimitry Andric   if (I == MBB.begin() || !isJump((--I)->getOpcode())) {
6840b57cec5SDimitry Andric     if (LastOpc == R600::JUMP) {
6850b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
6860b57cec5SDimitry Andric       return false;
6870b57cec5SDimitry Andric     } else if (LastOpc == R600::JUMP_COND) {
6880b57cec5SDimitry Andric       auto predSet = I;
6890b57cec5SDimitry Andric       while (!isPredicateSetter(predSet->getOpcode())) {
6900b57cec5SDimitry Andric         predSet = --I;
6910b57cec5SDimitry Andric       }
6920b57cec5SDimitry Andric       TBB = LastInst.getOperand(0).getMBB();
6930b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(1));
6940b57cec5SDimitry Andric       Cond.push_back(predSet->getOperand(2));
6950b57cec5SDimitry Andric       Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
6960b57cec5SDimitry Andric       return false;
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric     return true;  // Can't handle indirect branch.
6990b57cec5SDimitry Andric   }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric   // Get the instruction before it if it is a terminator.
7020b57cec5SDimitry Andric   MachineInstr &SecondLastInst = *I;
7030b57cec5SDimitry Andric   unsigned SecondLastOpc = SecondLastInst.getOpcode();
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric   // If the block ends with a B and a Bcc, handle it.
7060b57cec5SDimitry Andric   if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {
7070b57cec5SDimitry Andric     auto predSet = --I;
7080b57cec5SDimitry Andric     while (!isPredicateSetter(predSet->getOpcode())) {
7090b57cec5SDimitry Andric       predSet = --I;
7100b57cec5SDimitry Andric     }
7110b57cec5SDimitry Andric     TBB = SecondLastInst.getOperand(0).getMBB();
7120b57cec5SDimitry Andric     FBB = LastInst.getOperand(0).getMBB();
7130b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(1));
7140b57cec5SDimitry Andric     Cond.push_back(predSet->getOperand(2));
7150b57cec5SDimitry Andric     Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));
7160b57cec5SDimitry Andric     return false;
7170b57cec5SDimitry Andric   }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric   // Otherwise, can't handle this.
7200b57cec5SDimitry Andric   return true;
7210b57cec5SDimitry Andric }
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric static
7240b57cec5SDimitry Andric MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
7250b57cec5SDimitry Andric   for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
7260b57cec5SDimitry Andric       It != E; ++It) {
7270b57cec5SDimitry Andric     if (It->getOpcode() == R600::CF_ALU ||
7280b57cec5SDimitry Andric         It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)
7290b57cec5SDimitry Andric       return It.getReverse();
7300b57cec5SDimitry Andric   }
7310b57cec5SDimitry Andric   return MBB.end();
7320b57cec5SDimitry Andric }
7330b57cec5SDimitry Andric 
7340b57cec5SDimitry Andric unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,
7350b57cec5SDimitry Andric                                      MachineBasicBlock *TBB,
7360b57cec5SDimitry Andric                                      MachineBasicBlock *FBB,
7370b57cec5SDimitry Andric                                      ArrayRef<MachineOperand> Cond,
7380b57cec5SDimitry Andric                                      const DebugLoc &DL,
7390b57cec5SDimitry Andric                                      int *BytesAdded) const {
7400b57cec5SDimitry Andric   assert(TBB && "insertBranch must not be told to insert a fallthrough");
7410b57cec5SDimitry Andric   assert(!BytesAdded && "code size not handled");
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   if (!FBB) {
7440b57cec5SDimitry Andric     if (Cond.empty()) {
7450b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);
7460b57cec5SDimitry Andric       return 1;
7470b57cec5SDimitry Andric     } else {
7480b57cec5SDimitry Andric       MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
7490b57cec5SDimitry Andric       assert(PredSet && "No previous predicate !");
7500b57cec5SDimitry Andric       addFlag(*PredSet, 0, MO_FLAG_PUSH);
7510b57cec5SDimitry Andric       PredSet->getOperand(2).setImm(Cond[1].getImm());
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric       BuildMI(&MBB, DL, get(R600::JUMP_COND))
7540b57cec5SDimitry Andric              .addMBB(TBB)
7550b57cec5SDimitry Andric              .addReg(R600::PREDICATE_BIT, RegState::Kill);
7560b57cec5SDimitry Andric       MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
7570b57cec5SDimitry Andric       if (CfAlu == MBB.end())
7580b57cec5SDimitry Andric         return 1;
7590b57cec5SDimitry Andric       assert (CfAlu->getOpcode() == R600::CF_ALU);
7600b57cec5SDimitry Andric       CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
7610b57cec5SDimitry Andric       return 1;
7620b57cec5SDimitry Andric     }
7630b57cec5SDimitry Andric   } else {
7640b57cec5SDimitry Andric     MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
7650b57cec5SDimitry Andric     assert(PredSet && "No previous predicate !");
7660b57cec5SDimitry Andric     addFlag(*PredSet, 0, MO_FLAG_PUSH);
7670b57cec5SDimitry Andric     PredSet->getOperand(2).setImm(Cond[1].getImm());
7680b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP_COND))
7690b57cec5SDimitry Andric             .addMBB(TBB)
7700b57cec5SDimitry Andric             .addReg(R600::PREDICATE_BIT, RegState::Kill);
7710b57cec5SDimitry Andric     BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);
7720b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
7730b57cec5SDimitry Andric     if (CfAlu == MBB.end())
7740b57cec5SDimitry Andric       return 2;
7750b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU);
7760b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));
7770b57cec5SDimitry Andric     return 2;
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,
7820b57cec5SDimitry Andric                                      int *BytesRemoved) const {
7830b57cec5SDimitry Andric   assert(!BytesRemoved && "code size not handled");
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric   // Note : we leave PRED* instructions there.
7860b57cec5SDimitry Andric   // They may be needed when predicating instructions.
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MBB.end();
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric   if (I == MBB.begin()) {
7910b57cec5SDimitry Andric     return 0;
7920b57cec5SDimitry Andric   }
7930b57cec5SDimitry Andric   --I;
7940b57cec5SDimitry Andric   switch (I->getOpcode()) {
7950b57cec5SDimitry Andric   default:
7960b57cec5SDimitry Andric     return 0;
7970b57cec5SDimitry Andric   case R600::JUMP_COND: {
7980b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
7990b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
8000b57cec5SDimitry Andric     I->eraseFromParent();
8010b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
8020b57cec5SDimitry Andric     if (CfAlu == MBB.end())
8030b57cec5SDimitry Andric       break;
8040b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
8050b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
8060b57cec5SDimitry Andric     break;
8070b57cec5SDimitry Andric   }
8080b57cec5SDimitry Andric   case R600::JUMP:
8090b57cec5SDimitry Andric     I->eraseFromParent();
8100b57cec5SDimitry Andric     break;
8110b57cec5SDimitry Andric   }
8120b57cec5SDimitry Andric   I = MBB.end();
8130b57cec5SDimitry Andric 
8140b57cec5SDimitry Andric   if (I == MBB.begin()) {
8150b57cec5SDimitry Andric     return 1;
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric   --I;
8180b57cec5SDimitry Andric   switch (I->getOpcode()) {
8190b57cec5SDimitry Andric     // FIXME: only one case??
8200b57cec5SDimitry Andric   default:
8210b57cec5SDimitry Andric     return 1;
8220b57cec5SDimitry Andric   case R600::JUMP_COND: {
8230b57cec5SDimitry Andric     MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
8240b57cec5SDimitry Andric     clearFlag(*predSet, 0, MO_FLAG_PUSH);
8250b57cec5SDimitry Andric     I->eraseFromParent();
8260b57cec5SDimitry Andric     MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
8270b57cec5SDimitry Andric     if (CfAlu == MBB.end())
8280b57cec5SDimitry Andric       break;
8290b57cec5SDimitry Andric     assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);
8300b57cec5SDimitry Andric     CfAlu->setDesc(get(R600::CF_ALU));
8310b57cec5SDimitry Andric     break;
8320b57cec5SDimitry Andric   }
8330b57cec5SDimitry Andric   case R600::JUMP:
8340b57cec5SDimitry Andric     I->eraseFromParent();
8350b57cec5SDimitry Andric     break;
8360b57cec5SDimitry Andric   }
8370b57cec5SDimitry Andric   return 2;
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {
8410b57cec5SDimitry Andric   int idx = MI.findFirstPredOperandIdx();
8420b57cec5SDimitry Andric   if (idx < 0)
8430b57cec5SDimitry Andric     return false;
8440b57cec5SDimitry Andric 
8458bcb0991SDimitry Andric   Register Reg = MI.getOperand(idx).getReg();
8460b57cec5SDimitry Andric   switch (Reg) {
8470b57cec5SDimitry Andric   default: return false;
8480b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
8490b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
8500b57cec5SDimitry Andric   case R600::PREDICATE_BIT:
8510b57cec5SDimitry Andric     return true;
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
8550b57cec5SDimitry Andric bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {
8560b57cec5SDimitry Andric   // XXX: KILL* instructions can be predicated, but they must be the last
8570b57cec5SDimitry Andric   // instruction in a clause, so this means any instructions after them cannot
8580b57cec5SDimitry Andric   // be predicated.  Until we have proper support for instruction clauses in the
8590b57cec5SDimitry Andric   // backend, we will mark KILL* instructions as unpredicable.
8600b57cec5SDimitry Andric 
8610b57cec5SDimitry Andric   if (MI.getOpcode() == R600::KILLGT) {
8620b57cec5SDimitry Andric     return false;
8630b57cec5SDimitry Andric   } else if (MI.getOpcode() == R600::CF_ALU) {
8640b57cec5SDimitry Andric     // If the clause start in the middle of MBB then the MBB has more
8650b57cec5SDimitry Andric     // than a single clause, unable to predicate several clauses.
8660b57cec5SDimitry Andric     if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))
8670b57cec5SDimitry Andric       return false;
8680b57cec5SDimitry Andric     // TODO: We don't support KC merging atm
8690b57cec5SDimitry Andric     return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;
8700b57cec5SDimitry Andric   } else if (isVector(MI)) {
8710b57cec5SDimitry Andric     return false;
8720b57cec5SDimitry Andric   } else {
8730b57cec5SDimitry Andric     return TargetInstrInfo::isPredicable(MI);
8740b57cec5SDimitry Andric   }
8750b57cec5SDimitry Andric }
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric bool
8780b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
8790b57cec5SDimitry Andric                                    unsigned NumCycles,
8800b57cec5SDimitry Andric                                    unsigned ExtraPredCycles,
8810b57cec5SDimitry Andric                                    BranchProbability Probability) const{
8820b57cec5SDimitry Andric   return true;
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric bool
8860b57cec5SDimitry Andric R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
8870b57cec5SDimitry Andric                                    unsigned NumTCycles,
8880b57cec5SDimitry Andric                                    unsigned ExtraTCycles,
8890b57cec5SDimitry Andric                                    MachineBasicBlock &FMBB,
8900b57cec5SDimitry Andric                                    unsigned NumFCycles,
8910b57cec5SDimitry Andric                                    unsigned ExtraFCycles,
8920b57cec5SDimitry Andric                                    BranchProbability Probability) const {
8930b57cec5SDimitry Andric   return true;
8940b57cec5SDimitry Andric }
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric bool
8970b57cec5SDimitry Andric R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
8980b57cec5SDimitry Andric                                          unsigned NumCycles,
8990b57cec5SDimitry Andric                                          BranchProbability Probability)
9000b57cec5SDimitry Andric                                          const {
9010b57cec5SDimitry Andric   return true;
9020b57cec5SDimitry Andric }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric bool
9050b57cec5SDimitry Andric R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
9060b57cec5SDimitry Andric                                          MachineBasicBlock &FMBB) const {
9070b57cec5SDimitry Andric   return false;
9080b57cec5SDimitry Andric }
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric bool
9110b57cec5SDimitry Andric R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
9120b57cec5SDimitry Andric   MachineOperand &MO = Cond[1];
9130b57cec5SDimitry Andric   switch (MO.getImm()) {
9140b57cec5SDimitry Andric   case R600::PRED_SETE_INT:
9150b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE_INT);
9160b57cec5SDimitry Andric     break;
9170b57cec5SDimitry Andric   case R600::PRED_SETNE_INT:
9180b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE_INT);
9190b57cec5SDimitry Andric     break;
9200b57cec5SDimitry Andric   case R600::PRED_SETE:
9210b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETNE);
9220b57cec5SDimitry Andric     break;
9230b57cec5SDimitry Andric   case R600::PRED_SETNE:
9240b57cec5SDimitry Andric     MO.setImm(R600::PRED_SETE);
9250b57cec5SDimitry Andric     break;
9260b57cec5SDimitry Andric   default:
9270b57cec5SDimitry Andric     return true;
9280b57cec5SDimitry Andric   }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   MachineOperand &MO2 = Cond[2];
9310b57cec5SDimitry Andric   switch (MO2.getReg()) {
9320b57cec5SDimitry Andric   case R600::PRED_SEL_ZERO:
9330b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ONE);
9340b57cec5SDimitry Andric     break;
9350b57cec5SDimitry Andric   case R600::PRED_SEL_ONE:
9360b57cec5SDimitry Andric     MO2.setReg(R600::PRED_SEL_ZERO);
9370b57cec5SDimitry Andric     break;
9380b57cec5SDimitry Andric   default:
9390b57cec5SDimitry Andric     return true;
9400b57cec5SDimitry Andric   }
9410b57cec5SDimitry Andric   return false;
9420b57cec5SDimitry Andric }
9430b57cec5SDimitry Andric 
944e8d8bef9SDimitry Andric bool R600InstrInfo::ClobbersPredicate(MachineInstr &MI,
945e8d8bef9SDimitry Andric                                       std::vector<MachineOperand> &Pred,
946e8d8bef9SDimitry Andric                                       bool SkipDead) const {
9470b57cec5SDimitry Andric   return isPredicateSetter(MI.getOpcode());
9480b57cec5SDimitry Andric }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,
9510b57cec5SDimitry Andric                                          ArrayRef<MachineOperand> Pred) const {
9520b57cec5SDimitry Andric   int PIdx = MI.findFirstPredOperandIdx();
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric   if (MI.getOpcode() == R600::CF_ALU) {
9550b57cec5SDimitry Andric     MI.getOperand(8).setImm(0);
9560b57cec5SDimitry Andric     return true;
9570b57cec5SDimitry Andric   }
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric   if (MI.getOpcode() == R600::DOT_4) {
9600b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))
9610b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9620b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))
9630b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9640b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))
9650b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9660b57cec5SDimitry Andric     MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))
9670b57cec5SDimitry Andric         .setReg(Pred[2].getReg());
9680b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
9690b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
9700b57cec5SDimitry Andric     return true;
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric   if (PIdx != -1) {
9740b57cec5SDimitry Andric     MachineOperand &PMO = MI.getOperand(PIdx);
9750b57cec5SDimitry Andric     PMO.setReg(Pred[2].getReg());
9760b57cec5SDimitry Andric     MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
9770b57cec5SDimitry Andric     MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);
9780b57cec5SDimitry Andric     return true;
9790b57cec5SDimitry Andric   }
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   return false;
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {
9850b57cec5SDimitry Andric   return 2;
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
9890b57cec5SDimitry Andric                                             const MachineInstr &,
9900b57cec5SDimitry Andric                                             unsigned *PredCost) const {
9910b57cec5SDimitry Andric   if (PredCost)
9920b57cec5SDimitry Andric     *PredCost = 2;
9930b57cec5SDimitry Andric   return 2;
9940b57cec5SDimitry Andric }
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
9970b57cec5SDimitry Andric                                                    unsigned Channel) const {
9980b57cec5SDimitry Andric   assert(Channel == 0);
9990b57cec5SDimitry Andric   return RegIndex;
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
10030b57cec5SDimitry Andric   switch (MI.getOpcode()) {
10040b57cec5SDimitry Andric   default: {
10050b57cec5SDimitry Andric     MachineBasicBlock *MBB = MI.getParent();
10060b57cec5SDimitry Andric     int OffsetOpIdx =
10070b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);
10080b57cec5SDimitry Andric     // addr is a custom operand with multiple MI operands, and only the
10090b57cec5SDimitry Andric     // first MI operand is given a name.
10100b57cec5SDimitry Andric     int RegOpIdx = OffsetOpIdx + 1;
10110b57cec5SDimitry Andric     int ChanOpIdx =
10120b57cec5SDimitry Andric         R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);
10130b57cec5SDimitry Andric     if (isRegisterLoad(MI)) {
10140b57cec5SDimitry Andric       int DstOpIdx =
10150b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);
10160b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
10170b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
10180b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
10198bcb0991SDimitry Andric       Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
10200b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
10210b57cec5SDimitry Andric         buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),
10220b57cec5SDimitry Andric                       getIndirectAddrRegClass()->getRegister(Address));
10230b57cec5SDimitry Andric       } else {
10240b57cec5SDimitry Andric         buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,
10250b57cec5SDimitry Andric                           OffsetReg);
10260b57cec5SDimitry Andric       }
10270b57cec5SDimitry Andric     } else if (isRegisterStore(MI)) {
10280b57cec5SDimitry Andric       int ValOpIdx =
10290b57cec5SDimitry Andric           R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);
10300b57cec5SDimitry Andric       unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();
10310b57cec5SDimitry Andric       unsigned Channel = MI.getOperand(ChanOpIdx).getImm();
10320b57cec5SDimitry Andric       unsigned Address = calculateIndirectAddress(RegIndex, Channel);
10338bcb0991SDimitry Andric       Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();
10340b57cec5SDimitry Andric       if (OffsetReg == R600::INDIRECT_BASE_ADDR) {
10350b57cec5SDimitry Andric         buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),
10360b57cec5SDimitry Andric                       MI.getOperand(ValOpIdx).getReg());
10370b57cec5SDimitry Andric       } else {
10380b57cec5SDimitry Andric         buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),
10390b57cec5SDimitry Andric                            calculateIndirectAddress(RegIndex, Channel),
10400b57cec5SDimitry Andric                            OffsetReg);
10410b57cec5SDimitry Andric       }
10420b57cec5SDimitry Andric     } else {
10430b57cec5SDimitry Andric       return false;
10440b57cec5SDimitry Andric     }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric     MBB->erase(MI);
10470b57cec5SDimitry Andric     return true;
10480b57cec5SDimitry Andric   }
10490b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V2:
10500b57cec5SDimitry Andric   case R600::R600_EXTRACT_ELT_V4:
10510b57cec5SDimitry Andric     buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),
10520b57cec5SDimitry Andric                       RI.getHWRegIndex(MI.getOperand(1).getReg()), //  Address
10530b57cec5SDimitry Andric                       MI.getOperand(2).getReg(),
10540b57cec5SDimitry Andric                       RI.getHWRegChan(MI.getOperand(1).getReg()));
10550b57cec5SDimitry Andric     break;
10560b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V2:
10570b57cec5SDimitry Andric   case R600::R600_INSERT_ELT_V4:
10580b57cec5SDimitry Andric     buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value
10590b57cec5SDimitry Andric                        RI.getHWRegIndex(MI.getOperand(1).getReg()),   // Address
10600b57cec5SDimitry Andric                        MI.getOperand(3).getReg(),                     // Offset
10610b57cec5SDimitry Andric                        RI.getHWRegChan(MI.getOperand(1).getReg()));   // Channel
10620b57cec5SDimitry Andric     break;
10630b57cec5SDimitry Andric   }
10640b57cec5SDimitry Andric   MI.eraseFromParent();
10650b57cec5SDimitry Andric   return true;
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,
10690b57cec5SDimitry Andric                                              const MachineFunction &MF,
10700b57cec5SDimitry Andric                                              const R600RegisterInfo &TRI) const {
10710b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
10720b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   unsigned StackWidth = TFL->getStackWidth(MF);
10750b57cec5SDimitry Andric   int End = getIndirectIndexEnd(MF);
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric   if (End == -1)
10780b57cec5SDimitry Andric     return;
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric   for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
10810b57cec5SDimitry Andric     for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
10820b57cec5SDimitry Andric       unsigned Reg = R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
10830b57cec5SDimitry Andric       TRI.reserveRegisterTuples(Reserved, Reg);
10840b57cec5SDimitry Andric     }
10850b57cec5SDimitry Andric   }
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {
10890b57cec5SDimitry Andric   return &R600::R600_TReg32_XRegClass;
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
10930b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
10940b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
10950b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
10960b57cec5SDimitry Andric   return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
11000b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
11010b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
11020b57cec5SDimitry Andric                                        unsigned OffsetReg,
11030b57cec5SDimitry Andric                                        unsigned AddrChan) const {
11040b57cec5SDimitry Andric   unsigned AddrReg;
11050b57cec5SDimitry Andric   switch (AddrChan) {
11060b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
11070b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
11080b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
11090b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
11100b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
11130b57cec5SDimitry Andric                                                R600::AR_X, OffsetReg);
11140b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
11170b57cec5SDimitry Andric                                       AddrReg, ValueReg)
11180b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
11190b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
11200b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::dst_rel, 1);
11210b57cec5SDimitry Andric   return Mov;
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
11250b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
11260b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
11270b57cec5SDimitry Andric                                        unsigned OffsetReg) const {
11280b57cec5SDimitry Andric   return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);
11290b57cec5SDimitry Andric }
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
11320b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
11330b57cec5SDimitry Andric                                        unsigned ValueReg, unsigned Address,
11340b57cec5SDimitry Andric                                        unsigned OffsetReg,
11350b57cec5SDimitry Andric                                        unsigned AddrChan) const {
11360b57cec5SDimitry Andric   unsigned AddrReg;
11370b57cec5SDimitry Andric   switch (AddrChan) {
11380b57cec5SDimitry Andric     default: llvm_unreachable("Invalid Channel");
11390b57cec5SDimitry Andric     case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;
11400b57cec5SDimitry Andric     case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;
11410b57cec5SDimitry Andric     case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;
11420b57cec5SDimitry Andric     case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;
11430b57cec5SDimitry Andric   }
11440b57cec5SDimitry Andric   MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,
11450b57cec5SDimitry Andric                                                        R600::AR_X,
11460b57cec5SDimitry Andric                                                        OffsetReg);
11470b57cec5SDimitry Andric   setImmOperand(*MOVA, R600::OpName::write, 0);
11480b57cec5SDimitry Andric   MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,
11490b57cec5SDimitry Andric                                       ValueReg,
11500b57cec5SDimitry Andric                                       AddrReg)
11510b57cec5SDimitry Andric                                       .addReg(R600::AR_X,
11520b57cec5SDimitry Andric                                            RegState::Implicit | RegState::Kill);
11530b57cec5SDimitry Andric   setImmOperand(*Mov, R600::OpName::src0_rel, 1);
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric   return Mov;
11560b57cec5SDimitry Andric }
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
11590b57cec5SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
11600b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
11610b57cec5SDimitry Andric   int Offset = -1;
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
11640b57cec5SDimitry Andric     return -1;
11650b57cec5SDimitry Andric   }
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   if (MRI.livein_empty()) {
11680b57cec5SDimitry Andric     return 0;
11690b57cec5SDimitry Andric   }
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric   const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();
11720b57cec5SDimitry Andric   for (std::pair<unsigned, unsigned> LI : MRI.liveins()) {
1173e8d8bef9SDimitry Andric     Register Reg = LI.first;
1174e8d8bef9SDimitry Andric     if (Reg.isVirtual() || !IndirectRC->contains(Reg))
11750b57cec5SDimitry Andric       continue;
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric     unsigned RegIndex;
11780b57cec5SDimitry Andric     unsigned RegEnd;
11790b57cec5SDimitry Andric     for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;
11800b57cec5SDimitry Andric                                                           ++RegIndex) {
1181e8d8bef9SDimitry Andric       if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)
11820b57cec5SDimitry Andric         break;
11830b57cec5SDimitry Andric     }
11840b57cec5SDimitry Andric     Offset = std::max(Offset, (int)RegIndex);
11850b57cec5SDimitry Andric   }
11860b57cec5SDimitry Andric 
11870b57cec5SDimitry Andric   return Offset + 1;
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
11910b57cec5SDimitry Andric   int Offset = 0;
11920b57cec5SDimitry Andric   const MachineFrameInfo &MFI = MF.getFrameInfo();
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   // Variable sized objects are not supported
11950b57cec5SDimitry Andric   if (MFI.hasVarSizedObjects()) {
11960b57cec5SDimitry Andric     return -1;
11970b57cec5SDimitry Andric   }
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   if (MFI.getNumObjects() == 0) {
12000b57cec5SDimitry Andric     return -1;
12010b57cec5SDimitry Andric   }
12020b57cec5SDimitry Andric 
12030b57cec5SDimitry Andric   const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();
12040b57cec5SDimitry Andric   const R600FrameLowering *TFL = ST.getFrameLowering();
12050b57cec5SDimitry Andric 
12065ffd83dbSDimitry Andric   Register IgnoredFrameReg;
1207e8d8bef9SDimitry Andric   Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric   return getIndirectIndexBegin(MF) + Offset;
12100b57cec5SDimitry Andric }
12110b57cec5SDimitry Andric 
12120b57cec5SDimitry Andric unsigned R600InstrInfo::getMaxAlusPerClause() const {
12130b57cec5SDimitry Andric   return 115;
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
12170b57cec5SDimitry Andric                                                   MachineBasicBlock::iterator I,
12180b57cec5SDimitry Andric                                                   unsigned Opcode,
12190b57cec5SDimitry Andric                                                   unsigned DstReg,
12200b57cec5SDimitry Andric                                                   unsigned Src0Reg,
12210b57cec5SDimitry Andric                                                   unsigned Src1Reg) const {
12220b57cec5SDimitry Andric   MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
12230b57cec5SDimitry Andric     DstReg);           // $dst
12240b57cec5SDimitry Andric 
12250b57cec5SDimitry Andric   if (Src1Reg) {
12260b57cec5SDimitry Andric     MIB.addImm(0)     // $update_exec_mask
12270b57cec5SDimitry Andric        .addImm(0);    // $update_predicate
12280b57cec5SDimitry Andric   }
12290b57cec5SDimitry Andric   MIB.addImm(1)        // $write
12300b57cec5SDimitry Andric      .addImm(0)        // $omod
12310b57cec5SDimitry Andric      .addImm(0)        // $dst_rel
12320b57cec5SDimitry Andric      .addImm(0)        // $dst_clamp
12330b57cec5SDimitry Andric      .addReg(Src0Reg)  // $src0
12340b57cec5SDimitry Andric      .addImm(0)        // $src0_neg
12350b57cec5SDimitry Andric      .addImm(0)        // $src0_rel
12360b57cec5SDimitry Andric      .addImm(0)        // $src0_abs
12370b57cec5SDimitry Andric      .addImm(-1);       // $src0_sel
12380b57cec5SDimitry Andric 
12390b57cec5SDimitry Andric   if (Src1Reg) {
12400b57cec5SDimitry Andric     MIB.addReg(Src1Reg) // $src1
12410b57cec5SDimitry Andric        .addImm(0)       // $src1_neg
12420b57cec5SDimitry Andric        .addImm(0)       // $src1_rel
12430b57cec5SDimitry Andric        .addImm(0)       // $src1_abs
12440b57cec5SDimitry Andric        .addImm(-1);      // $src1_sel
12450b57cec5SDimitry Andric   }
12460b57cec5SDimitry Andric 
12470b57cec5SDimitry Andric   //XXX: The r600g finalizer expects this to be 1, once we've moved the
12480b57cec5SDimitry Andric   //scheduling to the backend, we can change the default to 0.
12490b57cec5SDimitry Andric   MIB.addImm(1)        // $last
12500b57cec5SDimitry Andric       .addReg(R600::PRED_SEL_OFF) // $pred_sel
12510b57cec5SDimitry Andric       .addImm(0)         // $literal
12520b57cec5SDimitry Andric       .addImm(0);        // $bank_swizzle
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric   return MIB;
12550b57cec5SDimitry Andric }
12560b57cec5SDimitry Andric 
12570b57cec5SDimitry Andric #define OPERAND_CASE(Label) \
12580b57cec5SDimitry Andric   case Label: { \
12590b57cec5SDimitry Andric     static const unsigned Ops[] = \
12600b57cec5SDimitry Andric     { \
12610b57cec5SDimitry Andric       Label##_X, \
12620b57cec5SDimitry Andric       Label##_Y, \
12630b57cec5SDimitry Andric       Label##_Z, \
12640b57cec5SDimitry Andric       Label##_W \
12650b57cec5SDimitry Andric     }; \
12660b57cec5SDimitry Andric     return Ops[Slot]; \
12670b57cec5SDimitry Andric   }
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric static unsigned getSlotedOps(unsigned  Op, unsigned Slot) {
12700b57cec5SDimitry Andric   switch (Op) {
12710b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_exec_mask)
12720b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::update_pred)
12730b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::write)
12740b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::omod)
12750b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::dst_rel)
12760b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::clamp)
12770b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0)
12780b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_neg)
12790b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_rel)
12800b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_abs)
12810b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src0_sel)
12820b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1)
12830b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_neg)
12840b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_rel)
12850b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_abs)
12860b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::src1_sel)
12870b57cec5SDimitry Andric   OPERAND_CASE(R600::OpName::pred_sel)
12880b57cec5SDimitry Andric   default:
12890b57cec5SDimitry Andric     llvm_unreachable("Wrong Operand");
12900b57cec5SDimitry Andric   }
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric #undef OPERAND_CASE
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
12960b57cec5SDimitry Andric     MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
12970b57cec5SDimitry Andric     const {
12980b57cec5SDimitry Andric   assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");
12990b57cec5SDimitry Andric   unsigned Opcode;
13000b57cec5SDimitry Andric   if (ST.getGeneration() <= AMDGPUSubtarget::R700)
13010b57cec5SDimitry Andric     Opcode = R600::DOT4_r600;
13020b57cec5SDimitry Andric   else
13030b57cec5SDimitry Andric     Opcode = R600::DOT4_eg;
13040b57cec5SDimitry Andric   MachineBasicBlock::iterator I = MI;
13050b57cec5SDimitry Andric   MachineOperand &Src0 = MI->getOperand(
13060b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));
13070b57cec5SDimitry Andric   MachineOperand &Src1 = MI->getOperand(
13080b57cec5SDimitry Andric       getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));
13090b57cec5SDimitry Andric   MachineInstr *MIB = buildDefaultInstruction(
13100b57cec5SDimitry Andric       MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
13110b57cec5SDimitry Andric   static const unsigned  Operands[14] = {
13120b57cec5SDimitry Andric     R600::OpName::update_exec_mask,
13130b57cec5SDimitry Andric     R600::OpName::update_pred,
13140b57cec5SDimitry Andric     R600::OpName::write,
13150b57cec5SDimitry Andric     R600::OpName::omod,
13160b57cec5SDimitry Andric     R600::OpName::dst_rel,
13170b57cec5SDimitry Andric     R600::OpName::clamp,
13180b57cec5SDimitry Andric     R600::OpName::src0_neg,
13190b57cec5SDimitry Andric     R600::OpName::src0_rel,
13200b57cec5SDimitry Andric     R600::OpName::src0_abs,
13210b57cec5SDimitry Andric     R600::OpName::src0_sel,
13220b57cec5SDimitry Andric     R600::OpName::src1_neg,
13230b57cec5SDimitry Andric     R600::OpName::src1_rel,
13240b57cec5SDimitry Andric     R600::OpName::src1_abs,
13250b57cec5SDimitry Andric     R600::OpName::src1_sel,
13260b57cec5SDimitry Andric   };
13270b57cec5SDimitry Andric 
13280b57cec5SDimitry Andric   MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
13290b57cec5SDimitry Andric       getSlotedOps(R600::OpName::pred_sel, Slot)));
13300b57cec5SDimitry Andric   MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))
13310b57cec5SDimitry Andric       .setReg(MO.getReg());
13320b57cec5SDimitry Andric 
13330b57cec5SDimitry Andric   for (unsigned i = 0; i < 14; i++) {
13340b57cec5SDimitry Andric     MachineOperand &MO = MI->getOperand(
13350b57cec5SDimitry Andric         getOperandIdx(MI->getOpcode(), getSlotedOps(Operands[i], Slot)));
13360b57cec5SDimitry Andric     assert (MO.isImm());
13370b57cec5SDimitry Andric     setImmOperand(*MIB, Operands[i], MO.getImm());
13380b57cec5SDimitry Andric   }
13390b57cec5SDimitry Andric   MIB->getOperand(20).setImm(0);
13400b57cec5SDimitry Andric   return MIB;
13410b57cec5SDimitry Andric }
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
13440b57cec5SDimitry Andric                                          MachineBasicBlock::iterator I,
13450b57cec5SDimitry Andric                                          unsigned DstReg,
13460b57cec5SDimitry Andric                                          uint64_t Imm) const {
13470b57cec5SDimitry Andric   MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,
13480b57cec5SDimitry Andric                                                   R600::ALU_LITERAL_X);
13490b57cec5SDimitry Andric   setImmOperand(*MovImm, R600::OpName::literal, Imm);
13500b57cec5SDimitry Andric   return MovImm;
13510b57cec5SDimitry Andric }
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,
13540b57cec5SDimitry Andric                                        MachineBasicBlock::iterator I,
13550b57cec5SDimitry Andric                                        unsigned DstReg, unsigned SrcReg) const {
13560b57cec5SDimitry Andric   return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);
13570b57cec5SDimitry Andric }
13580b57cec5SDimitry Andric 
13590b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
13600b57cec5SDimitry Andric   return getOperandIdx(MI.getOpcode(), Op);
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric int R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
13640b57cec5SDimitry Andric   return R600::getNamedOperandIdx(Opcode, Op);
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric void R600InstrInfo::setImmOperand(MachineInstr &MI, unsigned Op,
13680b57cec5SDimitry Andric                                   int64_t Imm) const {
13690b57cec5SDimitry Andric   int Idx = getOperandIdx(MI, Op);
13700b57cec5SDimitry Andric   assert(Idx != -1 && "Operand not supported for this instruction.");
13710b57cec5SDimitry Andric   assert(MI.getOperand(Idx).isImm());
13720b57cec5SDimitry Andric   MI.getOperand(Idx).setImm(Imm);
13730b57cec5SDimitry Andric }
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13760b57cec5SDimitry Andric // Instruction flag getters/setters
13770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13780b57cec5SDimitry Andric 
13790b57cec5SDimitry Andric MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,
13800b57cec5SDimitry Andric                                          unsigned Flag) const {
13810b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
13820b57cec5SDimitry Andric   int FlagIndex = 0;
13830b57cec5SDimitry Andric   if (Flag != 0) {
13840b57cec5SDimitry Andric     // If we pass something other than the default value of Flag to this
13850b57cec5SDimitry Andric     // function, it means we are want to set a flag on an instruction
13860b57cec5SDimitry Andric     // that uses native encoding.
13870b57cec5SDimitry Andric     assert(HAS_NATIVE_OPERANDS(TargetFlags));
13880b57cec5SDimitry Andric     bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
13890b57cec5SDimitry Andric     switch (Flag) {
13900b57cec5SDimitry Andric     case MO_FLAG_CLAMP:
13910b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::clamp);
13920b57cec5SDimitry Andric       break;
13930b57cec5SDimitry Andric     case MO_FLAG_MASK:
13940b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::write);
13950b57cec5SDimitry Andric       break;
13960b57cec5SDimitry Andric     case MO_FLAG_NOT_LAST:
13970b57cec5SDimitry Andric     case MO_FLAG_LAST:
13980b57cec5SDimitry Andric       FlagIndex = getOperandIdx(MI, R600::OpName::last);
13990b57cec5SDimitry Andric       break;
14000b57cec5SDimitry Andric     case MO_FLAG_NEG:
14010b57cec5SDimitry Andric       switch (SrcIdx) {
14020b57cec5SDimitry Andric       case 0:
14030b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);
14040b57cec5SDimitry Andric         break;
14050b57cec5SDimitry Andric       case 1:
14060b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);
14070b57cec5SDimitry Andric         break;
14080b57cec5SDimitry Andric       case 2:
14090b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);
14100b57cec5SDimitry Andric         break;
14110b57cec5SDimitry Andric       }
14120b57cec5SDimitry Andric       break;
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric     case MO_FLAG_ABS:
14150b57cec5SDimitry Andric       assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
14160b57cec5SDimitry Andric                        "instructions.");
14170b57cec5SDimitry Andric       (void)IsOP3;
14180b57cec5SDimitry Andric       switch (SrcIdx) {
14190b57cec5SDimitry Andric       case 0:
14200b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);
14210b57cec5SDimitry Andric         break;
14220b57cec5SDimitry Andric       case 1:
14230b57cec5SDimitry Andric         FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);
14240b57cec5SDimitry Andric         break;
14250b57cec5SDimitry Andric       }
14260b57cec5SDimitry Andric       break;
14270b57cec5SDimitry Andric 
14280b57cec5SDimitry Andric     default:
14290b57cec5SDimitry Andric       FlagIndex = -1;
14300b57cec5SDimitry Andric       break;
14310b57cec5SDimitry Andric     }
14320b57cec5SDimitry Andric     assert(FlagIndex != -1 && "Flag not supported for this instruction");
14330b57cec5SDimitry Andric   } else {
14340b57cec5SDimitry Andric       FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
14350b57cec5SDimitry Andric       assert(FlagIndex != 0 &&
14360b57cec5SDimitry Andric          "Instruction flags not supported for this instruction");
14370b57cec5SDimitry Andric   }
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric   MachineOperand &FlagOp = MI.getOperand(FlagIndex);
14400b57cec5SDimitry Andric   assert(FlagOp.isImm());
14410b57cec5SDimitry Andric   return FlagOp;
14420b57cec5SDimitry Andric }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric void R600InstrInfo::addFlag(MachineInstr &MI, unsigned Operand,
14450b57cec5SDimitry Andric                             unsigned Flag) const {
14460b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
14470b57cec5SDimitry Andric   if (Flag == 0) {
14480b57cec5SDimitry Andric     return;
14490b57cec5SDimitry Andric   }
14500b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
14510b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
14520b57cec5SDimitry Andric     if (Flag == MO_FLAG_NOT_LAST) {
14530b57cec5SDimitry Andric       clearFlag(MI, Operand, MO_FLAG_LAST);
14540b57cec5SDimitry Andric     } else if (Flag == MO_FLAG_MASK) {
14550b57cec5SDimitry Andric       clearFlag(MI, Operand, Flag);
14560b57cec5SDimitry Andric     } else {
14570b57cec5SDimitry Andric       FlagOp.setImm(1);
14580b57cec5SDimitry Andric     }
14590b57cec5SDimitry Andric   } else {
14600b57cec5SDimitry Andric       MachineOperand &FlagOp = getFlagOp(MI, Operand);
14610b57cec5SDimitry Andric       FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
14620b57cec5SDimitry Andric   }
14630b57cec5SDimitry Andric }
14640b57cec5SDimitry Andric 
14650b57cec5SDimitry Andric void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned Operand,
14660b57cec5SDimitry Andric                               unsigned Flag) const {
14670b57cec5SDimitry Andric   unsigned TargetFlags = get(MI.getOpcode()).TSFlags;
14680b57cec5SDimitry Andric   if (HAS_NATIVE_OPERANDS(TargetFlags)) {
14690b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
14700b57cec5SDimitry Andric     FlagOp.setImm(0);
14710b57cec5SDimitry Andric   } else {
14720b57cec5SDimitry Andric     MachineOperand &FlagOp = getFlagOp(MI);
14730b57cec5SDimitry Andric     unsigned InstFlags = FlagOp.getImm();
14740b57cec5SDimitry Andric     InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
14750b57cec5SDimitry Andric     FlagOp.setImm(InstFlags);
14760b57cec5SDimitry Andric   }
14770b57cec5SDimitry Andric }
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric unsigned R600InstrInfo::getAddressSpaceForPseudoSourceKind(
14800b57cec5SDimitry Andric     unsigned Kind) const {
14810b57cec5SDimitry Andric   switch (Kind) {
14820b57cec5SDimitry Andric   case PseudoSourceValue::Stack:
14830b57cec5SDimitry Andric   case PseudoSourceValue::FixedStack:
14840b57cec5SDimitry Andric     return AMDGPUAS::PRIVATE_ADDRESS;
14850b57cec5SDimitry Andric   case PseudoSourceValue::ConstantPool:
14860b57cec5SDimitry Andric   case PseudoSourceValue::GOT:
14870b57cec5SDimitry Andric   case PseudoSourceValue::JumpTable:
14880b57cec5SDimitry Andric   case PseudoSourceValue::GlobalValueCallEntry:
14890b57cec5SDimitry Andric   case PseudoSourceValue::ExternalSymbolCallEntry:
14900b57cec5SDimitry Andric   case PseudoSourceValue::TargetCustom:
14910b57cec5SDimitry Andric     return AMDGPUAS::CONSTANT_ADDRESS;
14920b57cec5SDimitry Andric   }
14930b57cec5SDimitry Andric 
14940b57cec5SDimitry Andric   llvm_unreachable("Invalid pseudo source kind");
14950b57cec5SDimitry Andric }
1496