nir: handle u2u/i2i recursively in nir_def_bits_used

to get the number of bits actually used by the uses.

Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34489>
This commit is contained in:
Marek Olšák 2025-04-13 19:47:56 -04:00 committed by Marge Bot
parent 15369a792a
commit e38a0b9a05
2 changed files with 70 additions and 7 deletions

View file

@ -2145,18 +2145,25 @@ ssa_def_bits_used(const nir_def *def, int recur)
switch (use_alu->op) {
case nir_op_u2u8:
case nir_op_i2i8:
bits_used |= 0xff;
break;
case nir_op_u2u16:
case nir_op_i2i16:
bits_used |= all_bits & 0xffff;
break;
case nir_op_u2u32:
case nir_op_i2i32:
bits_used |= all_bits & 0xffffffff;
case nir_op_u2u64:
case nir_op_i2i64: {
uint64_t def_bits_used = ssa_def_bits_used(&use_alu->def, recur);
/* If one of the sign-extended bits is used, set the last src bit
* as used.
*/
if ((use_alu->op == nir_op_i2i8 || use_alu->op == nir_op_i2i16 ||
use_alu->op == nir_op_i2i32 || use_alu->op == nir_op_i2i64) &&
def_bits_used & ~all_bits)
def_bits_used |= BITFIELD64_BIT(def->bit_size - 1);
bits_used |= def_bits_used & all_bits;
break;
}
case nir_op_extract_u8:
case nir_op_extract_i8:

View file

@ -356,3 +356,59 @@ TEST_F(ssa_def_bits_used_test, ushr_ishr_ishl)
EXPECT_EQ(nir_def_bits_used(load2), BITFIELD_RANGE(11, 32 - 11));
EXPECT_EQ(nir_def_bits_used(load3), BITFIELD_RANGE(0, 32 - 13));
}
typedef nir_def *(*unary_op)(nir_builder *build, nir_def *src0);
TEST_F(ssa_def_bits_used_test, u2u_i2i_iand)
{
static const unary_op ops[] = {
nir_u2u8,
nir_i2i8,
nir_u2u16,
nir_i2i16,
nir_u2u32,
nir_i2i32,
};
nir_def *load[ARRAY_SIZE(ops)];
for (unsigned i = 0; i < ARRAY_SIZE(ops); i++) {
load[i] = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 64);
nir_def *alu = nir_iand_imm(b, ops[i](b, load[i]), 0x1020304050607080ull);
nir_store_global(b, nir_undef(b, 1, 64), 4, alu, 0x1);
}
EXPECT_EQ(nir_def_bits_used(load[0]), 0x80);
EXPECT_EQ(nir_def_bits_used(load[1]), 0x80);
EXPECT_EQ(nir_def_bits_used(load[2]), 0x7080);
EXPECT_EQ(nir_def_bits_used(load[3]), 0x7080);
EXPECT_EQ(nir_def_bits_used(load[4]), 0x50607080);
EXPECT_EQ(nir_def_bits_used(load[5]), 0x50607080);
}
TEST_F(ssa_def_bits_used_test, u2u_i2i_upcast_bits)
{
static const unary_op ops[] = {
nir_u2u16,
nir_i2i16,
nir_u2u32,
nir_i2i32,
nir_u2u64,
nir_i2i64,
};
nir_def *load[ARRAY_SIZE(ops)];
for (unsigned i = 0; i < ARRAY_SIZE(ops); i++) {
load[i] = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 8);
nir_def *upcast = ops[i](b, load[i]);
/* Using one of the sing-extended bits implies using the last bit. */
nir_def *alu = nir_iand_imm(b, upcast, BITFIELD64_BIT(upcast->bit_size - 1));
nir_store_global(b, nir_undef(b, 1, 64), 4, alu, 0x1);
}
EXPECT_EQ(nir_def_bits_used(load[0]), 0x0);
EXPECT_EQ(nir_def_bits_used(load[1]), 0x80);
EXPECT_EQ(nir_def_bits_used(load[2]), 0x0);
EXPECT_EQ(nir_def_bits_used(load[3]), 0x80);
EXPECT_EQ(nir_def_bits_used(load[4]), 0x0);
EXPECT_EQ(nir_def_bits_used(load[5]), 0x80);
}