diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 3620dde1a30..ec841c43536 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -3160,6 +3160,8 @@ typedef struct nir_shader_compiler_options { bool lower_bit_count; /** Lowers ifind_msb to compare and ufind_msb */ bool lower_ifind_msb; + /** Lowers ifind_msb and ufind_msb to reverse variants */ + bool lower_find_msb_to_reverse; /** Lowers find_lsb to ufind_msb and logic ops */ bool lower_find_lsb; bool lower_uadd_carry; diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py index 854f7562635..012c7bfea09 100644 --- a/src/compiler/nir/nir_opcodes.py +++ b/src/compiler/nir/nir_opcodes.py @@ -454,6 +454,16 @@ for (int bit = bit_size - 1; bit >= 0; bit--) { } """) +unop_convert("ufind_msb_rev", tint32, tuint, """ +dst = -1; +for (int bit = 0; bit < bit_size; bit++) { + if ((src0 << bit) & 0x80000000) { + dst = bit; + break; + } +} +""") + unop("uclz", tuint32, """ int bit; for (bit = bit_size - 1; bit >= 0; bit--) { @@ -477,6 +487,22 @@ for (int bit = 31; bit >= 0; bit--) { } """) +unop_convert("ifind_msb_rev", tint32, tuint, """ +dst = -1; +if (src0 != 0 || src0 != -1) { + for (int bit = 0; bit < 31; bit++) { + /* If src0 < 0, we're looking for the first 0 bit. + * if src0 >= 0, we're looking for the first 1 bit. + */ + if ((((src0 << bit) & 0x40000000) && (src0 >= 0)) || + ((!((src0 << bit) & 0x40000000)) && (src0 < 0))) { + dst = bit; + break; + } + } +} +""") + unop_convert("find_lsb", tint32, tint, """ dst = -1; for (unsigned bit = 0; bit < bit_size; bit++) { diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py index 5938561735e..32d1dab1743 100644 --- a/src/compiler/nir/nir_opt_algebraic.py +++ b/src/compiler/nir/nir_opt_algebraic.py @@ -1523,6 +1523,18 @@ optimizations.extend([ ('ufind_msb', ('bcsel', ('ilt', 'value', 0), ('inot', 'value'), 'value')), 'options->lower_ifind_msb'), + (('ifind_msb', 'value'), + ('bcsel', ('ige', ('ifind_msb_rev', 'value'), 0), + ('isub', 31, ('ifind_msb_rev', 'value')), + ('ifind_msb_rev', 'value')), + 'options->lower_find_msb_to_reverse'), + + (('ufind_msb', 'value'), + ('bcsel', ('ige', ('ufind_msb_rev', 'value'), 0), + ('isub', 31, ('ufind_msb_rev', 'value')), + ('ufind_msb_rev', 'value')), + 'options->lower_find_msb_to_reverse'), + (('find_lsb', 'value'), ('ufind_msb', ('iand', 'value', ('ineg', 'value'))), 'options->lower_find_lsb'),