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