diff --git a/src/compiler/nir/nir_range_analysis.c b/src/compiler/nir/nir_range_analysis.c index 5d29164b54f..9e5a5c53539 100644 --- a/src/compiler/nir/nir_range_analysis.c +++ b/src/compiler/nir/nir_range_analysis.c @@ -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: diff --git a/src/compiler/nir/tests/range_analysis_tests.cpp b/src/compiler/nir/tests/range_analysis_tests.cpp index 539d16bc9fd..4a7a591be23 100644 --- a/src/compiler/nir/tests/range_analysis_tests.cpp +++ b/src/compiler/nir/tests/range_analysis_tests.cpp @@ -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); +}