diff --git a/src/compiler/nir/nir_range_analysis.c b/src/compiler/nir/nir_range_analysis.c index c1e3e1bcd80..e84717f85a4 100644 --- a/src/compiler/nir/nir_range_analysis.c +++ b/src/compiler/nir/nir_range_analysis.c @@ -2212,6 +2212,39 @@ ssa_def_bits_used(const nir_def *def, int recur) return all_bits; } + case nir_op_ibfe: + case nir_op_ubfe: + if (src_idx == 0 && nir_src_is_const(use_alu->src[1].src)) { + uint64_t def_bits_used = ssa_def_bits_used(&use_alu->def, recur); + unsigned bit_size = use_alu->def.bit_size; + unsigned offset = nir_alu_src_as_uint(use_alu->src[1]) & (bit_size - 1); + unsigned bits = nir_src_is_const(use_alu->src[2].src) ? + nir_alu_src_as_uint(use_alu->src[2]) & (bit_size - 1) : + /* Worst case if bits is not constant. */ + (bit_size - offset); + uint64_t field_bitmask = BITFIELD64_MASK(bits); + + /* If one of the sign-extended bits is used, set the last src + * bit as used. + * If bits is not constant, all bits can be the last one. + */ + if (use_alu->op == nir_op_ibfe && + (def_bits_used >> offset) & ~field_bitmask) { + if (nir_alu_src_as_uint(use_alu->src[2])) + def_bits_used |= BITFIELD64_BIT(bits - 1); + else + def_bits_used |= field_bitmask; + } + + bits_used |= (field_bitmask & def_bits_used) << offset; + break; + } else if (src_idx == 1 || src_idx == 2) { + bits_used |= use_alu->src[0].src.ssa->bit_size - 1; + break; + } else { + return all_bits; + } + default: /* We don't know what this op does */ return all_bits; diff --git a/src/compiler/nir/tests/range_analysis_tests.cpp b/src/compiler/nir/tests/range_analysis_tests.cpp index cc0c2afda5c..fcaeb0d8dfe 100644 --- a/src/compiler/nir/tests/range_analysis_tests.cpp +++ b/src/compiler/nir/tests/range_analysis_tests.cpp @@ -291,3 +291,36 @@ TEST_F(unsigned_upper_bound_test, loop_phi_bcsel) EXPECT_EQ(nir_unsigned_upper_bound(b->shader, range_ht, scalar, NULL), 2); _mesa_hash_table_destroy(range_ht, NULL); } + +TEST_F(ssa_def_bits_used_test, ubfe_ibfe) +{ + nir_def *load1 = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 32); + nir_def *load2 = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 32); + + nir_def *alu1 = nir_ubfe_imm(b, load1, 14, 3); + nir_def *alu2 = nir_ibfe_imm(b, load2, 12, 7); + + nir_store_global(b, nir_undef(b, 1, 64), 4, alu1, 0x1); + nir_store_global(b, nir_undef(b, 1, 64), 4, alu2, 0x1); + + EXPECT_EQ(nir_def_bits_used(load1), BITFIELD_RANGE(14, 3)); + EXPECT_EQ(nir_def_bits_used(load2), BITFIELD_RANGE(12, 7)); +} + +TEST_F(ssa_def_bits_used_test, ibfe_iand) +{ + nir_def *load = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 32); + nir_def *alu = nir_iand_imm(b, nir_ibfe_imm(b, load, 14, 3), 0x80000000); + nir_store_global(b, nir_undef(b, 1, 64), 4, alu, 0x1); + + EXPECT_EQ(nir_def_bits_used(load), BITFIELD_BIT(16)); +} + +TEST_F(ssa_def_bits_used_test, ubfe_iand) +{ + nir_def *load = nir_load_global(b, nir_undef(b, 1, 64), 4, 1, 32); + nir_def *alu = nir_iand_imm(b, nir_ubfe_imm(b, load, 14, 3), 0x2); + nir_store_global(b, nir_undef(b, 1, 64), 4, alu, 0x1); + + EXPECT_EQ(nir_def_bits_used(load), BITFIELD_BIT(15)); +}