diff --git a/lib/Target/R600/SIDefines.h b/lib/Target/R600/SIDefines.h index f5445ad759e..7fdaee59a57 100644 --- a/lib/Target/R600/SIDefines.h +++ b/lib/Target/R600/SIDefines.h @@ -14,7 +14,11 @@ namespace SIInstrFlags { enum { MIMG = 1 << 3, - SMRD = 1 << 4 + SMRD = 1 << 4, + VOP1 = 1 << 5, + VOP2 = 1 << 6, + VOP3 = 1 << 7, + VOPC = 1 << 8 }; } diff --git a/lib/Target/R600/SIInstrFormats.td b/lib/Target/R600/SIInstrFormats.td index 9576c055b48..962e266f215 100644 --- a/lib/Target/R600/SIInstrFormats.td +++ b/lib/Target/R600/SIInstrFormats.td @@ -19,12 +19,20 @@ class InstSI pattern> : field bits<1> LGKM_CNT = 0; field bits<1> MIMG = 0; field bits<1> SMRD = 0; + field bits<1> VOP1 = 0; + field bits<1> VOP2 = 0; + field bits<1> VOP3 = 0; + field bits<1> VOPC = 0; let TSFlags{0} = VM_CNT; let TSFlags{1} = EXP_CNT; let TSFlags{2} = LGKM_CNT; let TSFlags{3} = MIMG; let TSFlags{4} = SMRD; + let TSFlags{5} = VOP1; + let TSFlags{6} = VOP2; + let TSFlags{7} = VOP3; + let TSFlags{8} = VOPC; } class Enc32 pattern> : @@ -167,6 +175,8 @@ class VOP1 op, dag outs, dag ins, string asm, list pattern> : let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let UseNamedOperandTable = 1; + let VOP1 = 1; } class VOP2 op, dag outs, dag ins, string asm, list pattern> : @@ -185,6 +195,8 @@ class VOP2 op, dag outs, dag ins, string asm, list pattern> : let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let UseNamedOperandTable = 1; + let VOP2 = 1; } class VOP3 op, dag outs, dag ins, string asm, list pattern> : @@ -213,6 +225,8 @@ class VOP3 op, dag outs, dag ins, string asm, list pattern> : let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let UseNamedOperandTable = 1; + let VOP3 = 1; } class VOP3b op, dag outs, dag ins, string asm, list pattern> : @@ -239,6 +253,8 @@ class VOP3b op, dag outs, dag ins, string asm, list pattern> : let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let UseNamedOperandTable = 1; + let VOP3 = 1; } class VOPC op, dag ins, string asm, list pattern> : @@ -256,6 +272,7 @@ class VOPC op, dag ins, string asm, list pattern> : let mayLoad = 0; let mayStore = 0; let hasSideEffects = 0; + let VOPC = 1; } class VINTRP op, dag outs, dag ins, string asm, list pattern> : diff --git a/lib/Target/R600/SIInstrInfo.cpp b/lib/Target/R600/SIInstrInfo.cpp index e23eef3e0f9..f838701b353 100644 --- a/lib/Target/R600/SIInstrInfo.cpp +++ b/lib/Target/R600/SIInstrInfo.cpp @@ -232,6 +232,113 @@ int SIInstrInfo::isSMRD(uint16_t Opcode) const { return get(Opcode).TSFlags & SIInstrFlags::SMRD; } +bool SIInstrInfo::isVOP1(uint16_t Opcode) const { + return get(Opcode).TSFlags & SIInstrFlags::VOP1; +} + +bool SIInstrInfo::isVOP2(uint16_t Opcode) const { + return get(Opcode).TSFlags & SIInstrFlags::VOP2; +} + +bool SIInstrInfo::isVOP3(uint16_t Opcode) const { + return get(Opcode).TSFlags & SIInstrFlags::VOP3; +} + +bool SIInstrInfo::isVOPC(uint16_t Opcode) const { + return get(Opcode).TSFlags & SIInstrFlags::VOPC; +} + +bool SIInstrInfo::isInlineConstant(const MachineOperand &MO) const { + if(MO.isImm()) { + return MO.getImm() >= -16 && MO.getImm() <= 64; + } + if (MO.isFPImm()) { + return MO.getFPImm()->isExactlyValue(0.0) || + MO.getFPImm()->isExactlyValue(0.5) || + MO.getFPImm()->isExactlyValue(-0.5) || + MO.getFPImm()->isExactlyValue(1.0) || + MO.getFPImm()->isExactlyValue(-1.0) || + MO.getFPImm()->isExactlyValue(2.0) || + MO.getFPImm()->isExactlyValue(-2.0) || + MO.getFPImm()->isExactlyValue(4.0) || + MO.getFPImm()->isExactlyValue(-4.0); + } + return false; +} + +bool SIInstrInfo::isLiteralConstant(const MachineOperand &MO) const { + return (MO.isImm() || MO.isFPImm()) && !isInlineConstant(MO); +} + +bool SIInstrInfo::verifyInstruction(const MachineInstr *MI, + StringRef &ErrInfo) const { + uint16_t Opcode = MI->getOpcode(); + int Src0Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src0); + int Src1Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src1); + int Src2Idx = AMDGPU::getNamedOperandIdx(Opcode, AMDGPU::OpName::src2); + + // Verify VOP* + if (isVOP1(Opcode) || isVOP2(Opcode) || isVOP3(Opcode) || isVOPC(Opcode)) { + unsigned ConstantBusCount = 0; + unsigned SGPRUsed = AMDGPU::NoRegister; + MI->dump(); + for (int i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && + !TargetRegisterInfo::isVirtualRegister(MO.getReg())) { + + // EXEC register uses the constant bus. + if (!MO.isImplicit() && MO.getReg() == AMDGPU::EXEC) + ++ConstantBusCount; + + // SGPRs use the constant bus + if (MO.getReg() == AMDGPU::M0 || MO.getReg() == AMDGPU::VCC || + (!MO.isImplicit() && + (AMDGPU::SGPR_32RegClass.contains(MO.getReg()) || + AMDGPU::SGPR_64RegClass.contains(MO.getReg())))) { + if (SGPRUsed != MO.getReg()) { + ++ConstantBusCount; + SGPRUsed = MO.getReg(); + } + } + } + // Literal constants use the constant bus. + if (isLiteralConstant(MO)) + ++ConstantBusCount; + } + if (ConstantBusCount > 1) { + ErrInfo = "VOP* instruction uses the constant bus more than once"; + return false; + } + } + + // Verify SRC1 for VOP2 and VOPC + if (Src1Idx != -1 && (isVOP2(Opcode) || isVOPC(Opcode))) { + const MachineOperand &Src1 = MI->getOperand(Src1Idx); + if (Src1.isImm()) { + ErrInfo = "VOP[2C] src1 cannot be an immediate."; + return false; + } + } + + // Verify VOP3 + if (isVOP3(Opcode)) { + if (Src0Idx != -1 && isLiteralConstant(MI->getOperand(Src0Idx))) { + ErrInfo = "VOP3 src0 cannot be a literal constant."; + return false; + } + if (Src1Idx != -1 && isLiteralConstant(MI->getOperand(Src1Idx))) { + ErrInfo = "VOP3 src1 cannot be a literal constant."; + return false; + } + if (Src2Idx != -1 && isLiteralConstant(MI->getOperand(Src2Idx))) { + ErrInfo = "VOP3 src2 cannot be a literal constant."; + return false; + } + } + return true; +} + //===----------------------------------------------------------------------===// // Indirect addressing callbacks //===----------------------------------------------------------------------===// diff --git a/lib/Target/R600/SIInstrInfo.h b/lib/Target/R600/SIInstrInfo.h index 87b80633a0a..4c99b9524f4 100644 --- a/lib/Target/R600/SIInstrInfo.h +++ b/lib/Target/R600/SIInstrInfo.h @@ -49,7 +49,15 @@ public: virtual bool isSafeToMoveRegClassDefs(const TargetRegisterClass *RC) const; int isMIMG(uint16_t Opcode) const; int isSMRD(uint16_t Opcode) const; + bool isVOP1(uint16_t Opcode) const; + bool isVOP2(uint16_t Opcode) const; + bool isVOP3(uint16_t Opcode) const; + bool isVOPC(uint16_t Opcode) const; + bool isInlineConstant(const MachineOperand &MO) const; + bool isLiteralConstant(const MachineOperand &MO) const; + virtual bool verifyInstruction(const MachineInstr *MI, + StringRef &ErrInfo) const; virtual int getIndirectIndexBegin(const MachineFunction &MF) const; virtual int getIndirectIndexEnd(const MachineFunction &MF) const; diff --git a/lib/Target/R600/SIRegisterInfo.td b/lib/Target/R600/SIRegisterInfo.td index 0b90772f288..2d7bff076dc 100644 --- a/lib/Target/R600/SIRegisterInfo.td +++ b/lib/Target/R600/SIRegisterInfo.td @@ -43,7 +43,7 @@ def SGPR_32 : RegisterClass<"AMDGPU", [f32, i32], 32, (add (sequence "SGPR%u", 0, 101))>; // SGPR 64-bit registers -def SGPR_64 : RegisterTuples<[sub0, sub1], +def SGPR_64Regs : RegisterTuples<[sub0, sub1], [(add (decimate (trunc SGPR_32, 101), 2)), (add (decimate (shl SGPR_32, 1), 2))]>; @@ -153,8 +153,10 @@ def SReg_32 : RegisterClass<"AMDGPU", [f32, i32], 32, (add SGPR_32, M0Reg) >; +def SGPR_64 : RegisterClass<"AMDGPU", [v2i32, i64], 64, (add SGPR_64Regs)>; + def SReg_64 : RegisterClass<"AMDGPU", [v2i32, i64, i1], 64, - (add SGPR_64, VCCReg, EXECReg) + (add SGPR_64Regs, VCCReg, EXECReg) >; def SReg_128 : RegisterClass<"AMDGPU", [i128], 128, (add SGPR_128)>;