diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp --- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -2305,29 +2305,6 @@ Inst.addOperand(MCOperand::createReg(AMDGPU::getMCReg(getReg(), AsmParser->getSTI()))); } -static bool isInlineValue(unsigned Reg) { - switch (Reg) { - case AMDGPU::SRC_SHARED_BASE_LO: - case AMDGPU::SRC_SHARED_BASE: - case AMDGPU::SRC_SHARED_LIMIT_LO: - case AMDGPU::SRC_SHARED_LIMIT: - case AMDGPU::SRC_PRIVATE_BASE_LO: - case AMDGPU::SRC_PRIVATE_BASE: - case AMDGPU::SRC_PRIVATE_LIMIT_LO: - case AMDGPU::SRC_PRIVATE_LIMIT: - case AMDGPU::SRC_POPS_EXITING_WAVE_ID: - return true; - case AMDGPU::SRC_VCCZ: - case AMDGPU::SRC_EXECZ: - case AMDGPU::SRC_SCC: - return true; - case AMDGPU::SGPR_NULL: - return true; - default: - return false; - } -} - bool AMDGPUOperand::isInlineValue() const { return isRegKind() && ::isInlineValue(getReg()); } diff --git a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp --- a/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp +++ b/llvm/lib/Target/AMDGPU/MCTargetDesc/AMDGPUInstPrinter.cpp @@ -667,6 +667,19 @@ const MCOperand &Op = MI->getOperand(OpNo); if (Op.isReg()) { printRegOperand(Op.getReg(), O, MRI); + + // Check if operand register class contains register used. + // Intention: print disassembler message when invalid code is decoded, + // for example sgpr register used in VReg or VISrc(VReg or imm) operand. + int RCID = Desc.OpInfo[OpNo].RegClass; + if (RCID != -1) { + const MCRegisterClass RC = MRI.getRegClass(RCID); + auto Reg = mc2PseudoReg(Op.getReg()); + if (!RC.contains(Reg) && !isInlineValue(Reg)) { + O << "/*Invalid register, operand has \'" << MRI.getRegClassName(&RC) + << "\' register class*/"; + } + } } else if (Op.isImm()) { const uint8_t OpTy = Desc.OpInfo[OpNo].OperandType; switch (OpTy) { diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -1131,6 +1131,9 @@ LLVM_READNONE unsigned mc2PseudoReg(unsigned Reg); +LLVM_READNONE +bool isInlineValue(unsigned Reg); + /// Is this an AMDGPU specific source operand? These include registers, /// inline constants, literals and mandatory literals (KImm). bool isSISrcOperand(const MCInstrDesc &Desc, unsigned OpNo); diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp --- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -2093,6 +2093,29 @@ MAP_REG2REG } +bool isInlineValue(unsigned Reg) { + switch (Reg) { + case AMDGPU::SRC_SHARED_BASE_LO: + case AMDGPU::SRC_SHARED_BASE: + case AMDGPU::SRC_SHARED_LIMIT_LO: + case AMDGPU::SRC_SHARED_LIMIT: + case AMDGPU::SRC_PRIVATE_BASE_LO: + case AMDGPU::SRC_PRIVATE_BASE: + case AMDGPU::SRC_PRIVATE_LIMIT_LO: + case AMDGPU::SRC_PRIVATE_LIMIT: + case AMDGPU::SRC_POPS_EXITING_WAVE_ID: + return true; + case AMDGPU::SRC_VCCZ: + case AMDGPU::SRC_EXECZ: + case AMDGPU::SRC_SCC: + return true; + case AMDGPU::SGPR_NULL: + return true; + default: + return false; + } +} + #undef CASE_CI_VI #undef CASE_VI_GFX9PLUS #undef CASE_GFXPRE11_GFX11PLUS diff --git a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt --- a/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt +++ b/llvm/test/MC/Disassembler/AMDGPU/decode-err.txt @@ -21,14 +21,14 @@ # W64: v_wmma_f32_16x16x16_f16 v[16:19], /*invalid immediate*/, v[8:15], v[16:19] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c] 0x10,0x40,0x40,0xcc,0xf2,0x10,0x42,0x1c # src0 1.0 -# W32: v_wmma_f32_16x16x16_f16 v[16:23], s[0:7], v[8:15], v[16:23] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c] -# W64: v_wmma_f32_16x16x16_f16 v[16:19], s[0:7], v[8:15], v[16:19] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c] +# W32: v_wmma_f32_16x16x16_f16 v[16:23], s[0:7]/*Invalid register, operand has 'VReg_256' register class*/, v[8:15], v[16:23] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c] +# W64: v_wmma_f32_16x16x16_f16 v[16:19], s[0:7]/*Invalid register, operand has 'VReg_256' register class*/, v[8:15], v[16:19] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c] 0x10,0x40,0x40,0xcc,0x00,0x10,0x42,0x1c # src0 sgpr0 # W32: v_wmma_f32_16x16x16_f16 v[16:23], v[0:7], v[8:15], 1.0 ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0xca,0x1b] # W64: v_wmma_f32_16x16x16_f16 v[16:19], v[0:7], v[8:15], 1.0 ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0xca,0x1b] 0x10,0x40,0x40,0xcc,0x00,0x11,0xca,0x1b # src2 1.0 -# W32: v_wmma_f32_16x16x16_f16 v[16:23], v[0:7], v[8:15], s[0:7] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x02,0x18] -# W64: v_wmma_f32_16x16x16_f16 v[16:19], v[0:7], v[8:15], s[0:3] ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x02,0x18] +# W32: v_wmma_f32_16x16x16_f16 v[16:23], v[0:7], v[8:15], s[0:7]/*Invalid register, operand has 'VReg_256' register class*/ ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x02,0x18] +# W64: v_wmma_f32_16x16x16_f16 v[16:19], v[0:7], v[8:15], s[0:3]/*Invalid register, operand has 'VReg_128' register class*/ ; encoding: [0x10,0x40,0x40,0xcc,0x00,0x11,0x02,0x18] 0x10,0x40,0x40,0xcc,0x00,0x11,0x02,0x18 # src2 sgpr0