shader: share one find-first-bit lowering for S_FF0/FF1/FLBIT_I32_B64 and remove FindUMsb64

This commit is contained in:
nmzik
2026-10-21 22:39:34 +02:00
parent 6e5167598e
commit 4a1440197f
7 changed files with 27 additions and 56 deletions
@@ -221,19 +221,21 @@ void Translator::V_XOR3_B32(const Decoder::Instruction& inst) {
WriteOperand(DestinationOperand(inst), result);
}
void Translator::S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero) {
void Translator::S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb) {
auto source = ReadU32Pair(inst.src0);
if (find_zero) {
source[0] = ir.BitwiseNot(source[0]);
source[1] = ir.BitwiseNot(source[1]);
for (auto& word: source) {
word = find_zero ? ir.BitwiseNot(word) : word;
}
const auto low_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]}));
const auto high_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]}));
const auto high_position = ir.IAdd(high_lsb, IR::U32(IR::Value(32u)));
const auto result = ir.Select(ir.INotEqual(source[0], IR::U32(IR::Value(0u))), low_lsb,
ir.Select(ir.INotEqual(source[1], IR::U32(IR::Value(0u))),
high_position, IR::U32(IR::Value(0xffffffffu))));
WriteOperand(DestinationOperand(inst), result);
if (from_msb) {
// The leading bit index is the trailing bit index of the bit-reversed 64-bit value.
source = {IR::U32(ir.Emit(IR::ValueOpcode::BitReverse32, {source[1]})),
IR::U32(ir.Emit(IR::ValueOpcode::BitReverse32, {source[0]}))};
}
// FindILsb returns ~0 for zero, so OR-ing 32 keeps a missing high bit at ~0 (-1).
const auto low = ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]});
const auto high = ir.BitwiseOr(IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]})),
IR::U32(IR::Value(32u)));
WriteOperand(DestinationOperand(inst), ir.Emit(IR::ValueOpcode::UMin32, {low, high}));
}
void Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) {
@@ -248,17 +250,6 @@ void Translator::V_FFBH_32(const Decoder::Instruction& inst, bool sign) {
WriteOperand(DestinationOperand(inst), result);
}
void Translator::S_FLBIT_I32_B64(const Decoder::Instruction& inst) {
const auto source = ReadU64(inst.src0);
const auto msb = IR::U32(ir.Emit(IR::ValueOpcode::FindUMsb64, {source}));
const auto position = ir.ISub(IR::U32(IR::Value(63u)), msb);
const auto nonzero =
IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64,
{source, ir.ConstructU64(IR::U32(IR::Value(0u)), IR::U32(IR::Value(0u)))}));
const auto result = ir.Select(nonzero, position, IR::U32(IR::Value(0xffffffffu)));
WriteOperand(DestinationOperand(inst), result);
}
void Translator::Integer24(const Decoder::Instruction& inst, bool sign, bool addend) {
const auto extract24 = [&](IR::U32 value) {
return IR::U32(
@@ -238,10 +238,10 @@ void Translator::EmitScalar(const Decoder::Instruction& inst) {
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseOr32, false, true, true);
case O::S_XNOR_B32:
return ComposedIntegerBinary(inst, IR::ValueOpcode::BitwiseXor32, false, true, true);
case O::S_FF0_I32_B64: return S_FF_I32_B64(inst, true);
case O::S_FF1_I32_B64: return S_FF_I32_B64(inst, false);
case O::S_FF0_I32_B64: return S_FF_I32_B64(inst, true, false);
case O::S_FF1_I32_B64: return S_FF_I32_B64(inst, false, false);
case O::S_FLBIT_I32_B32: return V_FFBH_32(inst, false);
case O::S_FLBIT_I32_B64: return S_FLBIT_I32_B64(inst);
case O::S_FLBIT_I32_B64: return S_FF_I32_B64(inst, false, true);
case O::S_BITSET0_B32: return S_BITSET_B32(inst, false);
case O::S_BITSET1_B32: return S_BITSET_B32(inst, true);
@@ -187,9 +187,8 @@ private:
void V_AND_OR_B32(const Decoder::Instruction& inst);
void V_OR3_B32(const Decoder::Instruction& inst);
void V_XOR3_B32(const Decoder::Instruction& inst);
void S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero);
void S_FF_I32_B64(const Decoder::Instruction& inst, bool find_zero, bool from_msb);
void V_FFBH_32(const Decoder::Instruction& inst, bool sign);
void S_FLBIT_I32_B64(const Decoder::Instruction& inst);
void Integer24(const Decoder::Instruction& inst, bool sign, bool addend);
void V_MAD_U64_U32(const Decoder::Instruction& inst);
void V_SAD_U32(const Decoder::Instruction& inst);