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