shader: decode v_cmp_class_f16

This commit is contained in:
shadowbeat070
2026-09-19 15:15:40 +02:00
committed by nmzik
parent 9e666e4dd2
commit 7881c69a54
4 changed files with 89 additions and 1 deletions
+84
View File
@@ -19073,6 +19073,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
case Opcode::V_CMPX_NLT_F32:
case Opcode::V_CMP_CLASS_F32:
case Opcode::V_CMPX_CLASS_F32:
case Opcode::V_CMP_CLASS_F16:
case Opcode::V_CMPX_CLASS_F16:
case Opcode::V_CMP_LT_F16:
case Opcode::V_CMP_EQ_F16:
@@ -26468,6 +26469,79 @@ TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
return test;
}
TestCase VectorCmpClassF16(u32 wave_size) {
using O = ShaderOpcode;
constexpr std::array<u32, 10> values{
0x7c01u, 0x7e01u, 0xfc00u, 0xbc00u, 0x8001u,
0x8000u, 0x0000u, 0x0001u, 0x3c00u, 0x7c00u};
constexpr u32 guard = 0x87654321u;
TestCase test;
test.name = wave_size == 64 ? "VectorCmpClassF16Wave64" : "VectorCmpClassF16Wave32";
for (const auto value : values) {
test.initial.insert(test.initial.end(), {0xa55a0000u | value, (value << 16u) | 0x7e01u});
}
test.expected = test.initial;
auto &code = test.code;
const auto compare = [&](std::initializer_list<u32> words, u32 expected,
u32 dst = 106u, u32 exec = 1u) {
AppendSMovLiteral(&code, 106, 0x12345678u);
AppendSMovLiteral(&code, 107, guard);
AppendSMovLiteral(&code, dst + 1u, guard);
code.push_back(EncodeSopc(0x06, InlineU32(expected), InlineU32(0)));
code.insert(code.end(), words);
const u32 sources[] = {dst, dst + 1u, 126, 127, 253};
for (u32 i = 0; i < std::size(sources); ++i) {
code.push_back(EncodeSMovB32(30u + i, sources[i]));
}
code.push_back(EncodeSMovB32(126, InlineU32(1)));
const u32 results[] = {expected, wave_size == 32 ? guard : 0u, exec, 0u, 1u - expected};
for (u32 i = 0; i < std::size(results); ++i) {
AppendStoreSgpr(&code, 30u + i, static_cast<u32>(test.expected.size()));
test.expected.push_back(results[i]);
}
if (dst != 106u) {
AppendStoreSgpr(&code, 106, static_cast<u32>(test.expected.size()));
AppendStoreSgpr(&code, 107, static_cast<u32>(test.expected.size()) + 1u);
test.expected.insert(test.expected.end(), {0x12345678u, guard});
}
};
for (u32 index = 0; index < values.size(); ++index) {
AppendVMovU32(&code, 30, index * 8u);
AppendBufferLoadDword(&code, 0, 30);
AppendVMovU32(&code, 30, index * 8u + 4u);
AppendBufferLoadDword(&code, 2, 30);
for (u32 bit = 0; bit < 12; ++bit) {
AppendVMovU32(&code, 1, bit == 11 ? 0 : 1u << bit);
const u32 expected = bit == index ? 1u : 0u;
compare({EncodeVopc(0x8f, Vgpr(0), 1)}, expected);
compare({EncodeVop3Word0(0x8f, 20), EncodeVop3Word1(Vgpr(0), Vgpr(1))},
expected, 20);
}
// SDWA selects the high half, applies -abs, and writes an explicit SGPR pair.
compare({EncodeVopc(0x8f, 249, InlineU32(56)),
EncodeVopcSdwa(2, 20, 1, 5, 6, 0, 0, 1, 1, 0, 0, 0, 1)},
index >= 3 && index <= 8 ? 1u : 0u, 20);
compare({EncodeVop3Word0(0x8f, 20, 1),
EncodeVop3Word1(Vgpr(0), InlineU32(56), 0, 0, 1)},
index >= 3 && index <= 8 ? 1u : 0u, 20);
}
AppendVMovU32(&code, 1, 1u << 8u);
compare({EncodeVopc(0x8f, 242, 1)}, 1); // Inline 1.0 becomes half 0x3c00.
compare({EncodeVopc(0x8f, 255, 1), 0xdead3c00u}, 1); // Literal low half.
compare({EncodeVop3Word0(0x8f, 20), EncodeVop3Word1(242, 248)}, 1, 20);
// Inline INV_2PI supplies half bits 0x3118, including the positive-normal class.
code.push_back(EncodeSMovB32(126, InlineU32(0)));
compare({EncodeVopc(0x8f, 242, 1)}, 0, 106, 0); // Inactive lanes clear the result.
AppendEnd(&code);
test.initial.resize(test.expected.size());
test.opcodes = {O::V_MOV_B32, O::S_MOV_B32, O::S_CMP_EQ_U32, O::BUFFER_LOAD_DWORD,
O::V_CMP_CLASS_F16, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
test.decoded_counts = {{"V_CMP_CLASS_F16", 264u}};
test.compute_info.wave_size = wave_size;
test.has_compute_info = true;
return test;
}
TestCase VectorCmpxClassF16(u32 wave_size) {
using O = ShaderOpcode;
// One raw half value for each architectural class bit, in bit order.
@@ -35978,6 +36052,8 @@ std::vector<TestCase> MakeCases() {
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
AddCase(VectorCompareClassF32);
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
cases.push_back(VectorCmpClassF16(32));
cases.push_back(VectorCmpClassF16(64));
cases.push_back(VectorCmpxClassF16(32));
cases.push_back(VectorCmpxClassF16(64));
AddCase(VectorCompareF16Ops);
@@ -41474,6 +41550,14 @@ int main(int argc, char **argv) {
RunCase(&vulkan, VectorVopcSdwaCmpxClassF32CapturedExecMask());
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--class-f16-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, VectorCmpClassF16(32));
RunCase(&vulkan, VectorCmpClassF16(64));
RunCase(&vulkan, VectorCmpxClassF16(32));
RunCase(&vulkan, VectorCmpxClassF16(64));
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--cmpx-class-f16-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, VectorCmpxClassF16(32));