shader: write preserved SDWA fields with one bit-field insert and drop duplicate 16-bit masks

This commit is contained in:
nmzik
2026-10-21 22:52:14 +02:00
parent 10a852c2ac
commit aacf15fd0b
4 changed files with 15 additions and 16 deletions
@@ -89,7 +89,7 @@ void Translator::V_CVT_16_F16(const Decoder::Instruction& inst, bool signed_valu
if (signed_value) { if (signed_value) {
const auto converted = const auto converted =
ConvertF32ToI32Saturated(value, -32768.0f, 32768.0f, 32767.0f, 0xffff8000u, 0x7fffu); ConvertF32ToI32Saturated(value, -32768.0f, 32768.0f, 32767.0f, 0xffff8000u, 0x7fffu);
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(converted, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), converted);
return; return;
} }
Write16Bits(DestinationOperand(inst), Write16Bits(DestinationOperand(inst),
@@ -9,7 +9,7 @@ void Translator::Integer16Shift(const Decoder::Instruction& inst, IR::ValueOpcod
const auto value = ReadU16AsU32(inst.src1, arithmetic); const auto value = ReadU16AsU32(inst.src1, arithmetic);
const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u))); const auto count = ir.BitwiseAnd(ReadU16AsU32(inst.src0, false), IR::U32(IR::Value(15u)));
const auto result = IR::U32(ir.Emit(opcode, {value, count})); const auto result = IR::U32(ir.Emit(opcode, {value, count}));
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), result);
} }
void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
@@ -17,7 +17,7 @@ void Translator::Integer16Binary(const Decoder::Instruction& inst, IR::ValueOpco
const auto lhs = ReadU16AsU32(inst.src0, sign); const auto lhs = ReadU16AsU32(inst.src0, sign);
const auto rhs = ReadU16AsU32(inst.src1, sign); const auto rhs = ReadU16AsU32(inst.src1, sign);
const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs})); const auto result = IR::U32(ir.Emit(opcode, {lhs, rhs}));
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), result);
} }
void Translator::V_MAD_I16(const Decoder::Instruction& inst) { void Translator::V_MAD_I16(const Decoder::Instruction& inst) {
@@ -28,7 +28,7 @@ void Translator::V_MAD_I16(const Decoder::Instruction& inst) {
result = IR::U32(ir.Emit(IR::ValueOpcode::SMax32, {result, IR::Value(0xffff8000u)})); result = IR::U32(ir.Emit(IR::ValueOpcode::SMax32, {result, IR::Value(0xffff8000u)}));
result = IR::U32(ir.Emit(IR::ValueOpcode::SMin32, {result, IR::Value(0x7fffu)})); result = IR::U32(ir.Emit(IR::ValueOpcode::SMin32, {result, IR::Value(0x7fffu)}));
} }
Write16Bits(DestinationOperand(inst), ir.BitwiseAnd(result, IR::U32(IR::Value(0xffffu)))); Write16Bits(DestinationOperand(inst), result);
} }
void Translator::Integer16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, void Translator::Integer16Ternary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
@@ -296,15 +296,11 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) {
value = ir.ShiftLeftLogical(extended, IR::U32(IR::Value(offset))); value = ir.ShiftLeftLogical(extended, IR::U32(IR::Value(offset)));
break; break;
} }
case 2: { case 2:
const uint32_t field_mask = width == 32u ? 0xffffffffu : (1u << width) - 1u; value = IR::U32(ir.Emit(IR::ValueOpcode::BitFieldInsert,
const auto inserted = {ReadRawU32(PlainOperand(operand)), value, IR::Value(offset),
ir.ShiftLeftLogical(ir.BitwiseAnd(value, IR::U32(IR::Value(field_mask))), IR::Value(width)}));
IR::U32(IR::Value(offset))); break;
const auto cleared = ir.BitwiseAnd(ReadRawU32(PlainOperand(operand)),
IR::U32(IR::Value(~(field_mask << offset))));
value = ir.BitwiseOr(cleared, inserted);
} break;
default: EXIT("reserved SDWA DST_U mode"); default: EXIT("reserved SDWA DST_U mode");
} }
} }
@@ -453,7 +449,10 @@ void Translator::Write16Bits(const Decoder::Operand& operand, IR::U32 value) {
destination.omod = 0u; destination.omod = 0u;
destination.op_sel = false; destination.op_sel = false;
destination.clamp = false; destination.clamp = false;
WriteRawU32(destination, ir.BitwiseAnd(value, IR::U32(IR::Value(0xffffu)))); // A field selector keeps only the field's bits; a full-dword SDWA selector zero-extends.
WriteRawU32(destination, destination.sdwa_sel == 6u
? ir.BitwiseAnd(value, IR::U32(IR::Value(0xffffu)))
: value);
} }
void Translator::WriteF16(const Decoder::Operand& operand, IR::F32 value) { void Translator::WriteF16(const Decoder::Operand& operand, IR::F32 value) {
+2 -2
View File
@@ -24676,7 +24676,7 @@ TestCase Vop1SdwaMovByteDestinations() {
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_MOV_B32, O::BUFFER_STORE_DWORD, test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_MOV_B32, O::BUFFER_STORE_DWORD,
O::S_ENDPGM}; O::S_ENDPGM};
test.decoded_counts = {{"V_MOV_B32 v1.sdwa(sel=2,sext=0), 0", 1}}; test.decoded_counts = {{"V_MOV_B32 v1.sdwa(sel=2,sext=0), 0", 1}};
test.required_spirv = {"OpBitFieldInsert", "OpBitFieldSExtract", "OpBitwiseOr"}; test.required_spirv = {"OpBitFieldInsert", "OpBitFieldSExtract"};
return test; return test;
} }
@@ -24793,7 +24793,7 @@ TestCase Vop2SdwaAddNcCapturedHighWordDestination() {
test.expected = {0x00010002u, 0x0006c3d4u}; test.expected = {0x00010002u, 0x0006c3d4u};
test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_READFIRSTLANE_B32, O::V_MOV_B32, test.opcodes = {O::BUFFER_LOAD_DWORD, O::V_READFIRSTLANE_B32, O::V_MOV_B32,
O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; O::V_ADD_NC_U32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
test.required_spirv = {"OpIAdd", "OpShiftLeftLogical", "OpBitwiseOr"}; test.required_spirv = {"OpIAdd", "OpBitFieldInsert"};
return test; return test;
} }