diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index c3f22aa0c95..49bfabb6767 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -595,6 +595,12 @@ optimizations.extend([ (('ushr', ('iand', a, ('bfm', c, b)), b), ('ubfe', a, b, c), 'options->has_bfe'), + (('ushr@32', ('iand(is_used_once)', a, '#b(is_const_bfm)'), '#c'), + ('bcsel', ('ilt', ('find_lsb', b), ('iand', c, 0x1f)), + ('ushr', ('ubfe', a, ('find_lsb', b), ('bit_count', b)), ('isub', c, ('find_lsb', b))), + ('ishl', ('ubfe', a, ('find_lsb', b), ('bit_count', b)), ('isub', ('find_lsb', b), c))), + 'options->has_bfe && !options->avoid_ternary_with_two_constants'), + # Collapse two bitfield extracts with constant operands into a single one. (('ubfe', ('ubfe', a, '#b', '#c'), '#d', '#e'), ubfe_ubfe(a, b, c, d, e)), diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index ecbfbf9a6b0..e45a78f06f1 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -809,6 +809,30 @@ is_const_bitmask(UNUSED struct hash_table *ht, const nir_alu_instr *instr, return true; } +/** + * Returns whether an operand is a non zero constant + * that can be created by nir_op_bfm. + */ +static inline bool +is_const_bfm(UNUSED struct hash_table *ht, const nir_alu_instr *instr, + unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + if (nir_src_as_const_value(instr->src[src].src) == NULL) + return false; + + for (unsigned i = 0; i < num_components; i++) { + const unsigned bit_size = instr->src[src].src.ssa->bit_size; + const uint64_t c = nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); + const unsigned num_bits = util_bitcount64(c); + const unsigned offset = ffsll(c) - 1; + if (c == 0 || c != (BITFIELD64_MASK(num_bits) << offset) || num_bits == bit_size) + return false; + } + + return true; +} + /** * Returns whether the 5 LSBs of an operand are non-zero. */