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