shader: V_MUL_LO_U16

This commit is contained in:
nmzik committed 2026-09-18 11:21:57 +04:00
1 parent c2b7b0b58c
commit 394e638905
4 files changed
+56

No files matched your search

@@ -300,6 +300,7 @@ enum class Opcode {
V_SUBREV_NC_U32, V_SUBREV_NC_U32,
V_ADD_NC_U16, V_ADD_NC_U16,
V_SUB_NC_U16, V_SUB_NC_U16,
V_MUL_LO_U16,
V_MAX_U16, V_MAX_U16,
V_MAX_I16, V_MAX_I16,
V_MIN_U16, V_MIN_U16,
@@ -295,6 +295,7 @@ constexpr OpcodeMap VOP3_OPCODE_LIST[] = {
{0x300u, Opcode::V_LSHRREV_B64}, {0x300u, Opcode::V_LSHRREV_B64},
{0x303u, Opcode::V_ADD_NC_U16}, {0x303u, Opcode::V_ADD_NC_U16},
{0x304u, Opcode::V_SUB_NC_U16}, {0x304u, Opcode::V_SUB_NC_U16},
{0x305u, Opcode::V_MUL_LO_U16},
{0x307u, Opcode::V_LSHRREV_B16}, {0x307u, Opcode::V_LSHRREV_B16},
{0x308u, Opcode::V_ASHRREV_I16}, {0x308u, Opcode::V_ASHRREV_I16},
{0x309u, Opcode::V_MAX_U16}, {0x309u, Opcode::V_MAX_U16},
@@ -430,6 +431,7 @@ bool IsNativeVop3B16BinaryOpcode(Opcode opcode) {
switch (opcode) { switch (opcode) {
case Opcode::V_ADD_NC_U16: case Opcode::V_ADD_NC_U16:
case Opcode::V_SUB_NC_U16: case Opcode::V_SUB_NC_U16:
case Opcode::V_MUL_LO_U16:
case Opcode::V_MAX_U16: case Opcode::V_MAX_U16:
case Opcode::V_MAX_I16: case Opcode::V_MAX_I16:
case Opcode::V_MIN_U16: case Opcode::V_MIN_U16:
@@ -1174,6 +1176,7 @@ uint32_t NativeVop3SourceCount(Opcode opcode) {
case Opcode::V_MUL_I32_I24: case Opcode::V_MUL_I32_I24:
case Opcode::V_ADD_NC_U16: case Opcode::V_ADD_NC_U16:
case Opcode::V_SUB_NC_U16: case Opcode::V_SUB_NC_U16:
case Opcode::V_MUL_LO_U16:
case Opcode::V_MAX_U16: case Opcode::V_MAX_U16:
case Opcode::V_MAX_I16: case Opcode::V_MAX_I16:
case Opcode::V_MIN_U16: case Opcode::V_MIN_U16:
@@ -324,6 +324,7 @@ bool Translator::EmitVector(const Decoder::Instruction& inst) {
case O::V_ADD_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::IAdd32, false); case O::V_ADD_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::IAdd32, false);
case O::V_SUB_NC_U16: case O::V_SUB_NC_U16:
case O::V_SUB_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::ISub32, false); case O::V_SUB_NC_I16: return Integer16Binary(inst, IR::ValueOpcode::ISub32, false);
case O::V_MUL_LO_U16: return Integer16Binary(inst, IR::ValueOpcode::IMul32, false);
case O::V_MED3_I16: return V_MED3_I16(inst); case O::V_MED3_I16: return V_MED3_I16(inst);
case O::V_MIN_I16: return Integer16Binary(inst, IR::ValueOpcode::SMin32, true); case O::V_MIN_I16: return Integer16Binary(inst, IR::ValueOpcode::SMin32, true);
case O::V_MAX_I16: return Integer16Binary(inst, IR::ValueOpcode::SMax32, true); case O::V_MAX_I16: return Integer16Binary(inst, IR::ValueOpcode::SMax32, true);
+51
View File
@@ -18159,6 +18159,51 @@ TestCase Vop3CvtPkI16I32Captured() {
return test; return test;
} }
TestCase Vop3MulLoU16CapturedAndSelectors() {
using O = ShaderOpcode;
TestCase test;
test.name = "Vop3MulLoU16CapturedAndSelectors";
// Distinct runtime halves expose source selection and prevent constant folding.
test.initial = {0x00138001u, 0x0005ffffu, 0xffffffffu};
test.expected = {0x00138001u, 0x0005ffffu, 0xffffffffu,
0xa5a57fffu, 0xa5a5ffedu, 0xa5a58005u, 0xa5a5005fu,
0x7fff1234u, 0xffed1234u, 0x80051234u, 0x005f1234u,
0xffff0001u, 0x00231234u};
auto &code = test.code;
AppendBufferLoadDword(&code, 12, 30);
AppendVMovU32(&code, 30, 4);
AppendBufferLoadDword(&code, 24, 30);
u32 output = 3;
for (u32 selectors : {0u, 1u, 2u, 3u, 8u, 9u, 10u, 11u}) {
AppendVMovLiteral(&code, 2, 0xa5a51234u);
if (selectors == 8u) {
code.push_back(0xd7054002u);
code.push_back(0x0002310cu); // Captured v_mul_lo_u16 v2.hi, v12.lo, v24.lo.
} else {
AppendVop3(&code, 0x305, 2, Vgpr(12), Vgpr(24), 0, 0, selectors);
}
AppendStoreVgpr(&code, 2, output++);
}
// 0xffff * 0xffff wraps to 1; aliasing preserves the original high half.
AppendVMovU32(&code, 30, 8);
AppendBufferLoadDword(&code, 12, 30);
AppendVop3(&code, 0x305, 12, Vgpr(12), Vgpr(12), 0, 0, 1);
AppendStoreVgpr(&code, 12, output++);
AppendVMovLiteral(&code, 2, 0xa5a51234u);
AppendVop3(&code, 0x305, 2, 255, Vgpr(24), 0, 0, 11);
code.push_back(0x0007deadu); // Select literal high half: 7 * 5 = 35.
AppendStoreVgpr(&code, 2, output);
AppendEnd(&code);
test.opcodes = {O::V_MOV_B32, O::BUFFER_LOAD_DWORD, O::V_MUL_LO_U16,
O::BUFFER_STORE_DWORD, O::S_ENDPGM};
test.decoded_counts = {{"V_MUL_LO_U16", 10}};
test.required_spirv = {"OpIMul"};
return test;
}
TestCase Vop3Med3I16Captured() { TestCase Vop3Med3I16Captured() {
using O = ShaderOpcode; using O = ShaderOpcode;
@@ -26909,6 +26954,7 @@ std::vector<TestCase> MakeCases() {
AddCase(Vop2SdwaLshrrevCapturedByte1Source); AddCase(Vop2SdwaLshrrevCapturedByte1Source);
AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations); AddCase(Vop2SdwaSubNcPreservesByteAndWordDestinations);
AddCase(Vop3CvtPkI16I32Captured); AddCase(Vop3CvtPkI16I32Captured);
AddCase(Vop3MulLoU16CapturedAndSelectors);
AddCase(Vop3Med3I16Captured); AddCase(Vop3Med3I16Captured);
AddCase(Vop2SdwaMinU32PreservesWordDestination); AddCase(Vop2SdwaMinU32PreservesWordDestination);
AddCase(VectorShiftCountsMaskLowBits); AddCase(VectorShiftCountsMaskLowBits);
@@ -31913,6 +31959,11 @@ int main(int argc, char **argv) {
RunCase(&vulkan, Vop3Med3I16Captured()); RunCase(&vulkan, Vop3Med3I16Captured());
return 0; return 0;
} }
if (argc == 2 && std::strcmp(argv[1], "--mul-lo-u16-only") == 0) {
VulkanHarness vulkan;
RunCase(&vulkan, Vop3MulLoU16CapturedAndSelectors());
return 0;
}
if (argc == 2 && std::strcmp(argv[1], "--waitcnt-depctr-only") == 0) { if (argc == 2 && std::strcmp(argv[1], "--waitcnt-depctr-only") == 0) {
VulkanHarness vulkan; VulkanHarness vulkan;
RunCase(&vulkan, ScalarWaitcntDepctrCapturedVmVsrc()); RunCase(&vulkan, ScalarWaitcntDepctrCapturedVmVsrc());