From 34f6fd1f5f73165ed9d976178c1224f6850e81ed Mon Sep 17 00:00:00 2001 From: Nawid3333 <102778966+Nawid3333@users.noreply.github.com> Date: Thu, 8 Oct 2026 01:31:46 +0200 Subject: [PATCH] tests: cover the untested 16-bit integer ALU opcodes (#1151) * tests: cover the 16-bit integer VOPC compares V_CMP_{EQ,LE,GT,NE}_I16 and V_CMP_{EQ,LE,GT,NE,GE}_U16 decode and translate but no test exercised them. VectorCompareI16U16Ops compares low halves that differ in sign interpretation (0x8000 vs 0x7fff) with both the signed and the unsigned opcodes, and uses operands whose high halves differ to check that only the low 16 bits are compared. It runs in the default list and with --int16-compare-only. Co-Authored-By: Claude Opus 5.5 * tests: cover the 16-bit integer VOP3 ALU ops V_SUB_NC_U16, V_ADD_NC_I16, V_ASHRREV_I16, V_MAX_U16 and V_MIN_U16 decode and translate but no test exercised them. Vop3Int16Ops checks wraparound without clamp, the shift amount taken from the low four bits of src0, unsigned ordering for max/min on 0x8000 vs 0x7fff, that the high halves of the sources are ignored and that the high half of the destination is preserved. It runs in the default list and with --int16-alu-only. Co-Authored-By: Claude Opus 5.5 * tests: cover the packed 16-bit integer VOP3P ops V_PK_MAD_I16, V_PK_MAD_U16, V_PK_MUL_LO_U16, V_PK_ADD_I16, V_PK_SUB_U16, V_PK_LSHLREV_B16, V_PK_LSHRREV_B16, V_PK_ASHRREV_I16, V_PK_MIN_I16, V_PK_MAX_U16 and V_PK_MIN_U16 decode and translate but no test exercised them. Vop3pInt16Ops runs each on both halves with the default half selection: wraparound without clamp, shift amounts from the low four bits of each src0 half, and min/max on 0x8000 vs 0x0001 so signed and unsigned ordering give different results. It runs in the default list and with --int16-alu-only. Co-Authored-By: Claude Opus 5.5 --------- Co-authored-by: Claude Opus 5.5 --- tests/ShaderRecompilerComputeTests.cpp | 147 +++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 28b84efce..c9250a918 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -23603,6 +23603,48 @@ TestCase Vop3pIntegerNegationCapturedAndSelectedHalves() { O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; } +TestCase Vop3pInt16Ops() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovLiteral(&code, 1, 0x80007fffu); + AppendVMovLiteral(&code, 2, 0x00010001u); + AppendVMovLiteral(&code, 3, 0xfffe0003u); + AppendVMovLiteral(&code, 4, 0x00130004u); + AppendVMovLiteral(&code, 5, 0x8010f00fu); + AppendVMovLiteral(&code, 6, 0x00050007u); + + AppendVop3p(&code, 0x00u, 10, Vgpr(1), Vgpr(3), Vgpr(6), 0x7u); + AppendVop3p(&code, 0x09u, 11, Vgpr(1), Vgpr(3), Vgpr(6), 0x7u); + AppendVop3p(&code, 0x01u, 12, Vgpr(1), Vgpr(3), 0, 0x3u); + AppendVop3p(&code, 0x02u, 13, Vgpr(1), Vgpr(2), 0, 0x3u); + AppendVop3p(&code, 0x0bu, 14, Vgpr(2), Vgpr(3), 0, 0x3u); + AppendVop3p(&code, 0x04u, 15, Vgpr(4), Vgpr(5), 0, 0x3u); + AppendVop3p(&code, 0x05u, 16, Vgpr(4), Vgpr(5), 0, 0x3u); + AppendVop3p(&code, 0x06u, 17, Vgpr(4), Vgpr(5), 0, 0x3u); + AppendVop3p(&code, 0x08u, 18, Vgpr(1), Vgpr(2), 0, 0x3u); + AppendVop3p(&code, 0x0cu, 19, Vgpr(1), Vgpr(2), 0, 0x3u); + AppendVop3p(&code, 0x0du, 20, Vgpr(1), Vgpr(2), 0, 0x3u); + + for (u32 i = 0; i < 11; i++) { + AppendStoreVgpr(&code, 10 + i, i); + } + AppendEnd(&code); + + TestCase test; + test.name = "Vop3pInt16Ops"; + test.code = std::move(code); + test.expected = {0x00058004u, 0x00058004u, 0x00007ffdu, 0x80018000u, + 0x0003fffeu, 0x008000f0u, 0x10020f00u, 0xf002ff00u, + 0x80000001u, 0x80007fffu, 0x00010001u}; + test.opcodes = {O::V_MOV_B32, O::V_PK_MAD_I16, O::V_PK_MAD_U16, + O::V_PK_MUL_LO_U16, O::V_PK_ADD_I16, O::V_PK_SUB_U16, + O::V_PK_LSHLREV_B16, O::V_PK_LSHRREV_B16, O::V_PK_ASHRREV_I16, + O::V_PK_MIN_I16, O::V_PK_MAX_U16, O::V_PK_MIN_U16, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}; + return test; +} + TestCase CvtPkU8F32PacksSelectedByte() { using O = ShaderOpcode; @@ -24900,6 +24942,46 @@ TestCase FloatInlineConstantF16UsesNumericValue() { return test; } +TestCase Vop3Int16Ops() { + using O = ShaderOpcode; + + std::vector code; + AppendVMovLiteral(&code, 1, 0xabcd0001u); + AppendVMovLiteral(&code, 2, 0x12340002u); + AppendVMovLiteral(&code, 3, 0x55557fffu); + AppendVMovLiteral(&code, 4, 0x66668000u); + AppendVMovLiteral(&code, 5, 0x77770013u); + AppendVMovLiteral(&code, 6, 0x88888010u); + AppendVMovLiteral(&code, 10, 0xaaaa0000u); + AppendVMovLiteral(&code, 11, 0xbbbb0000u); + AppendVMovLiteral(&code, 12, 0xcccc0000u); + AppendVMovLiteral(&code, 13, 0xdddd0000u); + AppendVMovLiteral(&code, 14, 0xeeee0000u); + AppendVMovLiteral(&code, 15, 0x11110000u); + + AppendVop3(&code, 0x304u, 10, Vgpr(1), Vgpr(2)); + AppendVop3(&code, 0x30du, 11, Vgpr(3), Vgpr(1)); + AppendVop3(&code, 0x308u, 12, Vgpr(5), Vgpr(6)); + AppendVop3(&code, 0x309u, 13, Vgpr(3), Vgpr(4)); + AppendVop3(&code, 0x30bu, 14, Vgpr(3), Vgpr(4)); + AppendVop3(&code, 0x308u, 15, Vgpr(5), Vgpr(3)); + + for (u32 i = 0; i < 6; i++) { + AppendStoreVgpr(&code, 10 + i, i); + } + AppendEnd(&code); + + TestCase test; + test.name = "Vop3Int16Ops"; + test.code = std::move(code); + test.expected = {0xaaaaffffu, 0xbbbb8000u, 0xccccf002u, + 0xdddd8000u, 0xeeee7fffu, 0x11110fffu}; + test.opcodes = {O::V_MOV_B32, O::V_SUB_NC_U16, O::V_ADD_NC_I16, + O::V_ASHRREV_I16, O::V_MAX_U16, O::V_MIN_U16, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}; + return test; +} + TestCase VectorFloatControlContractPreservesInfNan() { using O = ShaderOpcode; @@ -26920,6 +27002,61 @@ TestCase VectorCompareF16Ops() { O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; } +TestCase VectorCompareI16U16Ops() { + using O = ShaderOpcode; + + std::vector code; + std::vector expected; + AppendVMovU32(&code, 1, 1); + AppendVMovLiteral(&code, 2, 0xabcd8000u); + AppendVMovLiteral(&code, 3, 0x00007fffu); + AppendVMovLiteral(&code, 4, 0x12348000u); + AppendVMovLiteral(&code, 5, 0xffff0001u); + AppendVMovLiteral(&code, 6, 0x00000001u); + + u32 dst = 10; + u32 out = 0; + auto append_compare = [&](u32 opcode, u32 src0, u32 src1, bool value) { + code.push_back(EncodeVopc(opcode, src0, src1)); + code.push_back(EncodeVop2(0x01, dst, InlineU32(0), 1)); + AppendStoreVgpr(&code, dst, out++); + expected.push_back(value ? 1u : 0u); + dst++; + }; + + append_compare(0x8a, Vgpr(2), 4, true); + append_compare(0x8a, Vgpr(2), 3, false); + append_compare(0x8b, Vgpr(2), 3, true); + append_compare(0x8b, Vgpr(3), 2, false); + append_compare(0x8b, Vgpr(5), 6, true); + append_compare(0x8c, Vgpr(3), 2, true); + append_compare(0x8c, Vgpr(2), 3, false); + append_compare(0x8d, Vgpr(2), 3, true); + append_compare(0x8d, Vgpr(5), 6, false); + + append_compare(0xaa, Vgpr(2), 4, true); + append_compare(0xaa, Vgpr(2), 3, false); + append_compare(0xab, Vgpr(3), 2, true); + append_compare(0xab, Vgpr(2), 3, false); + append_compare(0xac, Vgpr(2), 3, true); + append_compare(0xac, Vgpr(3), 2, false); + append_compare(0xad, Vgpr(2), 3, true); + append_compare(0xad, Vgpr(5), 6, false); + append_compare(0xae, Vgpr(2), 3, true); + append_compare(0xae, Vgpr(3), 2, false); + append_compare(0xae, Vgpr(5), 6, true); + AppendEnd(&code); + + return {"VectorCompareI16U16Ops", + code, + {}, + expected, + {O::V_MOV_B32, O::V_CMP_EQ_I16, O::V_CMP_LE_I16, O::V_CMP_GT_I16, + O::V_CMP_NE_I16, O::V_CMP_EQ_U16, O::V_CMP_LE_U16, O::V_CMP_GT_U16, + O::V_CMP_NE_U16, O::V_CMP_GE_U16, O::V_CNDMASK_B32, + O::BUFFER_STORE_DWORD, O::S_ENDPGM}}; +} + TestCase Vop2SdwaCndmaskSourceModifier() { using O = ShaderOpcode; @@ -36178,6 +36315,7 @@ std::vector MakeCases() { AddCase(Vop2PkFmacF16DppNegatesBothPackedHalves); AddCase(Vop3pOpselHiUsesArchitecturalSourceBits); AddCase(Vop3pIntegerNegationCapturedAndSelectedHalves); + AddCase(Vop3pInt16Ops); AddCase(CvtPkU8F32PacksSelectedByte); AddCase(CvtPkrtzF16F32SubnormalRoundsTowardZero); AddCase(CvtPkrtzF16F32SdwaAndOutputModifiers); @@ -36217,6 +36355,7 @@ std::vector MakeCases() { AddCase(MadMixF16NegHiIsAbsAndNegIsIndependent); AddCase(VectorVop3FmaF16UsesRdna2Opcode34b); AddCase(FloatInlineConstantF16UsesNumericValue); + AddCase(Vop3Int16Ops); AddCase(VectorFloatControlContractPreservesInfNan); AddCase(VectorFloatArithmeticOps); AddCase(VectorMinMaxF32NanAndSignedZeroEdges); @@ -36261,6 +36400,7 @@ std::vector MakeCases() { cases.push_back(VectorCmpxClassF16(32)); cases.push_back(VectorCmpxClassF16(64)); AddCase(VectorCompareF16Ops); + AddCase(VectorCompareI16U16Ops); AddCase(Wave32VccMasksPreserveOtherHalf); AddCase(Vop2SdwaCndmaskSourceModifier); AddCase(Vop2SdwaCndmaskCapturedByte3Source); @@ -41684,6 +41824,13 @@ int main(int argc, char **argv) { RunCase(&vulkan, VectorCompareF16Ops()); return 0; } + if (argc == 2 && std::strcmp(argv[1], "--int16-alu-only") == 0) { + VulkanHarness vulkan; + RunCase(&vulkan, VectorCompareI16U16Ops()); + RunCase(&vulkan, Vop3Int16Ops()); + RunCase(&vulkan, Vop3pInt16Ops()); + return 0; + } if (argc == 2 && std::strcmp(argv[1], "--buffer-format-store-only") == 0) { VulkanHarness vulkan; RunCase(&vulkan, BufferStoreFormatXyzwPackedUnormSkinningVectors());