diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index 6e6c1ed1356..58d5ee29ae5 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -408,6 +408,11 @@ for size, mask in ((8, 0xff), (16, 0xffff), (32, 0xffffffff), (64, 0xfffffffffff (('ushr', ('ishl', a_sz, '#b'), b), ('iand', a, ('ushr', mask, b))), ]) +optimizations.extend([ + (('iand', ('ishl', 'a@32', '#b(is_first_5_bits_uge_2)'), -4), ('ishl', a, b)), + (('iand', ('imul', a, '#b(is_unsigned_multiple_of_4)'), -4), ('imul', a, b)), +]) + for log2 in range(1, 7): # powers of two from 2 to 64 v = 1 << log2 mask = 0xffffffff & ~(v - 1) diff --git a/src/compiler/nir/nir_search_helpers.h b/src/compiler/nir/nir_search_helpers.h index 1188b50ed2d..63531291c96 100644 --- a/src/compiler/nir/nir_search_helpers.h +++ b/src/compiler/nir/nir_search_helpers.h @@ -226,6 +226,27 @@ is_ult_0xfffc07fc(UNUSED struct hash_table *ht, const nir_alu_instr *instr, return true; } +/** Is the first 5 bits of value unsigned greater than or equal 2? */ +static inline bool +is_first_5_bits_uge_2(UNUSED struct hash_table *ht, const nir_alu_instr *instr, + unsigned src, unsigned num_components, + const uint8_t *swizzle) +{ + /* only constant srcs: */ + if (!nir_src_is_const(instr->src[src].src)) + return false; + + for (unsigned i = 0; i < num_components; i++) { + const unsigned val = + nir_src_comp_as_uint(instr->src[src].src, swizzle[i]); + + if ((val & 0x1f) < 2) + return false; + } + + return true; +} + static inline bool is_not_const(UNUSED struct hash_table *ht, const nir_alu_instr *instr, unsigned src, UNUSED unsigned num_components,