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