diff options
author | Tom Stellard <thomas.stellard@amd.com> | 2013-10-10 17:11:55 +0000 |
---|---|---|
committer | Tom Stellard <thomas.stellard@amd.com> | 2013-10-10 17:11:55 +0000 |
commit | 47fbbc2dc5696d27f4e3c8a5432777976dd8da0a (patch) | |
tree | 096a79c4184a6ac2c9f710bebe924131ffbdd93a /lib/Target/R600/SIInstrInfo.cpp | |
parent | 39867850462b1eefd76510e25bca4f2a51f65a70 (diff) | |
download | llvm-47fbbc2dc5696d27f4e3c8a5432777976dd8da0a.tar.gz llvm-47fbbc2dc5696d27f4e3c8a5432777976dd8da0a.tar.bz2 llvm-47fbbc2dc5696d27f4e3c8a5432777976dd8da0a.tar.xz |
R600/SI: Implement SIInstrInfo::verifyInstruction() for VOP*
The function is used by the machine verifier and checks that VOP*
instructions have legal operands.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192367 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/R600/SIInstrInfo.cpp')
-rw-r--r-- | lib/Target/R600/SIInstrInfo.cpp | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/Target/R600/SIInstrInfo.cpp b/lib/Target/R600/SIInstrInfo.cpp index e23eef3e0f..f838701b35 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 //===----------------------------------------------------------------------===// |