From 248357365169243a604d6d89c013e182cd5a19ee Mon Sep 17 00:00:00 2001 From: nmzik Date: Mon, 26 Oct 2026 13:52:29 +0100 Subject: [PATCH] shader: mask V_MAD_U64_U32 carry-out bits of lanes outside EXEC --- .../recompiler/frontend/translate/Integer.cpp | 2 +- tests/ShaderRecompilerComputeTests.cpp | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp index 6ac64bf27..1aa68a39d 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Integer.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Integer.cpp @@ -291,7 +291,7 @@ void Translator::V_MAD_U64_U32(const Decoder::Instruction& inst) { inst.dst2.kind != Decoder::OperandKind::Unknown) { // The 32x32 product fits in 64 bits, so only the addition can carry. const auto carry = IR::U1(ir.Emit(IR::ValueOpcode::ULessThan64, {result, product})); - WriteMask(inst.dst2, carry, VectorMask(carry)); + WriteVectorMask(inst.dst2, carry); } } diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index f43577426..244fb22e4 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -27416,6 +27416,28 @@ TestCase VectorMadU64U32UnsignedCarryOut() { return test; } +// Like every VOP3B carry-out, the mask has zero bits for lanes outside EXEC. +TestCase VectorMadU64U32CarryMasksInactiveLanes() { + using O = ShaderOpcode; + TestCase test; + test.name = "VectorMadU64U32CarryMasksInactiveLanes"; + test.code = {EncodeVop2(0x1b, 3, InlineU32(1), 0), EncodeSop1(0x04, 40, 126), + EncodeVopc(0xd5, InlineU32(0), 3)}; + AppendVop3B(&test.code, 0x176u, 10, 20, 193, 193, 193); + test.code.push_back(EncodeSop1(0x04, 126, 40)); + AppendStoreSgpr(&test.code, 20, 0); + AppendEnd(&test.code); + test.initial = {0}; + test.expected = {0xaaaaaaaau}; + test.opcodes = {O::V_AND_B32, O::S_MOV_B64, O::V_CMPX_NE_U32, O::V_MAD_U64_U32, + O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; + test.compute_info.wave_size = 32; + test.compute_info.threads_num[0] = 32; + test.compute_info.thread_ids_num = 1; + test.has_compute_info = true; + return test; +} + TestCase VectorLaneAndPackedOps() { using O = ShaderOpcode; @@ -44870,6 +44892,7 @@ std::vector MakeCases() { AddCase(VectorVop3BCarryOutUsesEncodedSdst); AddCase(VectorVop3BSubCoU32UsesRdna2Opcode310); AddCase(VectorMadU64U32UnsignedCarryOut); + AddCase(VectorMadU64U32CarryMasksInactiveLanes); AddCase(VectorLaneAndPackedOps); AddCase(Vop2PkFmacF16AccumulatesPackedHalvesIndependently); AddCase(Vop2PkFmacF16DppNegatesBothPackedHalves); @@ -51985,6 +52008,7 @@ int main(int argc, char **argv) { RunCase(&vulkan, ScalarAshrI64Edges(true)); RunCase(&vulkan, VectorCompareInteger64Edges()); RunCase(&vulkan, VectorMadU64U32UnsignedCarryOut()); + RunCase(&vulkan, VectorMadU64U32CarryMasksInactiveLanes()); RunCase(&vulkan, ScalarWqmB64SelectsSccDomain()); RunCase(&vulkan, ScalarWqmB64PreservesPartialMasks()); return 0;