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