From bc9c70d50fdcc4ac3fb45b9041258a3069e9afa7 Mon Sep 17 00:00:00 2001 From: nmzik Date: Sun, 23 Aug 2026 16:39:01 +0200 Subject: [PATCH] shader: implement RDNA2 V_LSHLREV_B64 --- .../frontend/decode/ShaderDecoder.h | 1 + .../frontend/decode/VectorAluOps.cpp | 2 + .../recompiler/ir/opcodes/ShaderIROpcodes.cpp | 2 + tests/ShaderRecompilerComputeTests.cpp | 29 +++++++++++++ tests/shaderCfgTests.cpp | 41 +++++++++++++++++++ 5 files changed, 75 insertions(+) diff --git a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h index 188561e4f..cf2b6462b 100644 --- a/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h +++ b/src/graphics/shader/recompiler/frontend/decode/ShaderDecoder.h @@ -299,6 +299,7 @@ enum class Opcode { V_LSHRREV_B32, V_ASHR_I32, V_ASHRREV_I32, + V_LSHLREV_B64, V_LSHRREV_B64, V_LSHLREV_B16, V_LSHRREV_B16, diff --git a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp index 8a3450b17..7aa2bf23e 100644 --- a/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp +++ b/src/graphics/shader/recompiler/frontend/decode/VectorAluOps.cpp @@ -281,6 +281,7 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = { {0x16au, Opcode::V_MUL_HI_U32}, {0x16bu, Opcode::V_MUL_LO_I32}, {0x16cu, Opcode::V_MUL_HI_I32}, + {0x2ffu, Opcode::V_LSHLREV_B64}, {0x300u, Opcode::V_LSHRREV_B64}, {0x303u, Opcode::V_ADD_NC_U16}, {0x304u, Opcode::V_SUB_NC_U16}, @@ -1248,6 +1249,7 @@ uint32_t NativeVop3SourceCount(Opcode opcode) { case Opcode::V_MIN_I16: case Opcode::V_ADD_NC_I16: case Opcode::V_SUB_NC_I16: + case Opcode::V_LSHLREV_B64: case Opcode::V_LSHRREV_B64: case Opcode::V_LSHLREV_B16: case Opcode::V_LSHRREV_B16: diff --git a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp index 5a5a18a77..e890961c7 100644 --- a/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp +++ b/src/graphics/shader/recompiler/ir/opcodes/ShaderIROpcodes.cpp @@ -250,6 +250,7 @@ constexpr LowerMap LOWER_OPS[] = { {Decoder::Opcode::V_LSHLREV_B16, Opcode::ShiftLeftLogicalU16}, {Decoder::Opcode::V_LSHR_B32, Opcode::ShiftRightLogicalU32}, {Decoder::Opcode::V_LSHRREV_B32, Opcode::ShiftRightLogicalU32}, + {Decoder::Opcode::V_LSHLREV_B64, Opcode::ShiftLeftLogicalU64}, {Decoder::Opcode::V_LSHRREV_B64, Opcode::ShiftRightLogicalU64}, {Decoder::Opcode::V_LSHRREV_B16, Opcode::ShiftRightLogicalU16}, {Decoder::Opcode::V_ASHR_I32, Opcode::ShiftRightArithmeticI32}, @@ -468,6 +469,7 @@ bool IsReversedBinary(Decoder::Opcode opcode) { case Decoder::Opcode::V_LSHLREV_B32: case Decoder::Opcode::V_LSHRREV_B32: case Decoder::Opcode::V_ASHRREV_I32: + case Decoder::Opcode::V_LSHLREV_B64: case Decoder::Opcode::V_LSHRREV_B64: case Decoder::Opcode::V_LSHLREV_B16: case Decoder::Opcode::V_LSHRREV_B16: diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 67ef05856..7e87c6986 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -12956,6 +12956,34 @@ TestCase VectorVop3LshrrevB64Captured() { return test; } +TestCase VectorVop3LshlrevB64Captured() { + using O = ShaderOpcode; + + std::vector code; + AppendBufferLoadDword(&code, 3, 30); + code.push_back(0xd6ff0021u); + code.push_back(0x00010303u); // v_lshlrev_b64 v[33:34], v3, 1 + AppendStoreVgpr(&code, 33, 1); + AppendStoreVgpr(&code, 34, 2); + code.push_back(EncodeVop2(0x03, 3, InlineU32(31), 3)); + code.push_back(0xd6ff0021u); + code.push_back(0x00010303u); + AppendStoreVgpr(&code, 33, 3); + AppendStoreVgpr(&code, 34, 4); + AppendEnd(&code); + + TestCase test; + test.name = "VectorVop3LshlrevB64Captured"; + test.code = std::move(code); + test.initial = {33u, 0u, 0u, 0u, 0u}; + test.expected = {33u, 0u, 2u, 1u, 0u}; + test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_LSHLREV_B64, O::V_ADD_NC_U32, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}; + test.required_spirv = {"OpShiftLeftLogical", "OpSelect"}; + test.forbidden_spirv = {"OpTypeInt 64"}; + return test; +} + TestCase VectorVop3IntegerOps() { using O = ShaderOpcode; @@ -19670,6 +19698,7 @@ std::vector MakeCases() { AddCase(Vop2SdwaMinU32PreservesWordDestination); AddCase(VectorShiftCountsMaskLowBits); AddCase(VectorVop3LshrrevB64Captured); + AddCase(VectorVop3LshlrevB64Captured); AddCase(VectorVop3IntegerOps); AddCase(VectorBfeI32SignExtendsField); AddCase(VectorAlignByteUsesFiveBitByteOffset); diff --git a/tests/shaderCfgTests.cpp b/tests/shaderCfgTests.cpp index 3bfd55258..d26fc40e9 100644 --- a/tests/shaderCfgTests.cpp +++ b/tests/shaderCfgTests.cpp @@ -8412,6 +8412,47 @@ void TestNewShaderRecompilerU64PairLowering() { "V_LSHRREV_B64 did not reverse its encoded operands for pair-U64 IR"); CheckSpirvBinaryValidates(result.spirv); + const uint32_t lshlrev_b64_shader[] = { + 0xd6ff0021u, 0x00010303u, // v_lshlrev_b64 v[33:34], v3, 1 + EncodeSopp(0x01), + }; + Decoder::Instruction decoded_lshlrev_b64; + Check(Decoder::DecodeInstruction(lshlrev_b64_shader, 0u, + decoded_lshlrev_b64, &error), + error.c_str()); + Check(decoded_lshlrev_b64.opcode == Decoder::Opcode::V_LSHLREV_B64 && + decoded_lshlrev_b64.dst.kind == Decoder::OperandKind::Vgpr && + decoded_lshlrev_b64.dst.reg == 33u && + decoded_lshlrev_b64.src_count == 2u && + decoded_lshlrev_b64.src0.kind == Decoder::OperandKind::Vgpr && + decoded_lshlrev_b64.src0.reg == 3u && + decoded_lshlrev_b64.src1.kind == + Decoder::OperandKind::IntegerInlineConstant && + decoded_lshlrev_b64.src1.value == 1u, + "decoder rejected captured VOP3 V_LSHLREV_B64 fields"); + Check(TryRecompile(lshlrev_b64_shader, options, result, &error), + error.c_str()); + Check(Common::ContainsStr(result.decoded_dump, + "V_LSHLREV_B64 v33, v3, 1"), + "captured VOP3 V_LSHLREV_B64 was not present in the decoded dump"); + Decoder::Program decoded_lshlrev_b64_program; + CFG::Graph graph_lshlrev_b64; + IR::Program native_lshlrev_b64; + Check(Decoder::DecodeProgram(lshlrev_b64_shader, + decoded_lshlrev_b64_program, &error), + error.c_str()); + Check(CFG::BuildGraph(decoded_lshlrev_b64_program, graph_lshlrev_b64, + &error) && + CFG::Structurize(graph_lshlrev_b64, &error), + error.c_str()); + Check(IR::LowerProgram(decoded_lshlrev_b64_program, graph_lshlrev_b64, + ShaderType::Compute, 64u, native_lshlrev_b64, &error), + error.c_str()); + Check(Common::ContainsStr(IR::ProgramToString(native_lshlrev_b64), + "ShiftLeftLogicalU64 v33, 0x00000001, v3"), + "V_LSHLREV_B64 did not reverse its encoded operands for pair-U64 IR"); + CheckSpirvBinaryValidates(result.spirv); + const uint32_t cmpx_i64_shader[] = { 0xd4b5007eu, 0x00020e80u, // v_cmpx_ne_i64 exec, 0, v[7:8] EncodeSopp(0x01),