[Mesa-dev] [PATCH 2/3] nir/algebraic: support for power-of-two optimizations

Ilia Mirkin imirkin at alum.mit.edu
Mon May 9 17:01:13 UTC 2016


On Mon, May 9, 2016 at 12:52 PM, Rob Clark <robdclark at gmail.com> wrote:
> From: Rob Clark <robclark at freedesktop.org>
>
> It was kinda sad that we couldn't optimize imul/idiv by power-of-two.
> So I bashed my head against python for a while and this is what I came
> up with.  In the search expression, you can use "#a^2" to only match
> constants which are a power of two.  The rest is taken care of w/ normal
> replacement expression.
>
> Signed-off-by: Rob Clark <robclark at freedesktop.org>
> ---
>  src/compiler/nir/nir_algebraic.py     |  9 +++++++--
>  src/compiler/nir/nir_opt_algebraic.py |  5 +++++
>  src/compiler/nir/nir_search.c         | 26 ++++++++++++++++++++++++++
>  src/compiler/nir/nir_search.h         |  7 +++++++
>  4 files changed, 45 insertions(+), 2 deletions(-)
>
> diff --git a/src/compiler/nir/nir_algebraic.py b/src/compiler/nir/nir_algebraic.py
> index 285f853..9bfd3f2 100644
> --- a/src/compiler/nir/nir_algebraic.py
> +++ b/src/compiler/nir/nir_algebraic.py
> @@ -83,6 +83,7 @@ static const ${val.c_type} ${val.name} = {
>  % elif isinstance(val, Variable):
>     ${val.index}, /* ${val.var_name} */
>     ${'true' if val.is_constant else 'false'},
> +   ${'true' if val.is_power_of_two else 'false'},
>     ${val.type() or 'nir_type_invalid' },
>  % elif isinstance(val, Expression):
>     ${'true' if val.inexact else 'false'},
> @@ -113,7 +114,7 @@ static const ${val.c_type} ${val.name} = {
>                                      Variable=Variable,
>                                      Expression=Expression)
>
> -_constant_re = re.compile(r"(?P<value>[^@]+)(?:@(?P<bits>\d+))?")
> +_constant_re = re.compile(r"(?P<value>[^@\^]+)(?P<PoT>\^2)?(?:@(?P<bits>\d+))?")
>
>  class Constant(Value):
>     def __init__(self, val, name):
> @@ -123,6 +124,7 @@ class Constant(Value):
>           m = _constant_re.match(val)
>           self.value = ast.literal_eval(m.group('value'))
>           self.bit_size = int(m.group('bits')) if m.group('bits') else 0
> +         self.power_of_two = m.group('PoT') is not None
>        else:
>           self.value = val
>           self.bit_size = 0
> @@ -149,7 +151,7 @@ class Constant(Value):
>        elif isinstance(self.value, float):
>           return "nir_type_float"
>
> -_var_name_re = re.compile(r"(?P<const>#)?(?P<name>\w+)"
> +_var_name_re = re.compile(r"(?P<const>#)?(?P<name>\w+)(?P<PoT>\^2)?"
>                            r"(?:@(?P<type>int|uint|bool|float)?(?P<bits>\d+)?)?")
>
>  class Variable(Value):
> @@ -161,6 +163,9 @@ class Variable(Value):
>
>        self.var_name = m.group('name')
>        self.is_constant = m.group('const') is not None
> +      self.is_power_of_two = m.group('PoT') is not None
> +      if self.is_power_of_two:
> +         assert self.is_constant
>        self.required_type = m.group('type')
>        self.bit_size = int(m.group('bits')) if m.group('bits') else 0
>
> diff --git a/src/compiler/nir/nir_opt_algebraic.py b/src/compiler/nir/nir_opt_algebraic.py
> index 0a95725..c92e76d 100644
> --- a/src/compiler/nir/nir_opt_algebraic.py
> +++ b/src/compiler/nir/nir_opt_algebraic.py
> @@ -62,6 +62,11 @@ d = 'd'
>  # constructed value should have that bit-size.
>
>  optimizations = [
> +
> +   (('imul', a, '#b^2 at 32'), ('ishl', a, ('find_lsb', b))),
> +   (('udiv', a, '#b^2 at 32'), ('ishr', a, ('find_lsb', b))),

ushr

(A little frightening that there aren't tests that are hit by this...)

> +   (('umod', a, '#b^2'),    ('iand', a, ('isub', b, 1))),
> +
>     (('fneg', ('fneg', a)), a),
>     (('ineg', ('ineg', a)), a),
>     (('fabs', ('fabs', a)), ('fabs', a)),
> diff --git a/src/compiler/nir/nir_search.c b/src/compiler/nir/nir_search.c
> index 2c2fd92..6578088 100644
> --- a/src/compiler/nir/nir_search.c
> +++ b/src/compiler/nir/nir_search.c
> @@ -70,6 +70,13 @@ alu_instr_is_bool(nir_alu_instr *instr)
>     }
>  }
>
> +/* helper for this somewhere? */
> +static bool
> +is_power_of_two(unsigned int x)
> +{
> +   return ((x != 0) && !(x & (x - 1)));
> +}
> +
>  static bool
>  match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
>              unsigned num_components, const uint8_t *swizzle,
> @@ -127,6 +134,25 @@ match_value(const nir_search_value *value, nir_alu_instr *instr, unsigned src,
>               instr->src[src].src.ssa->parent_instr->type != nir_instr_type_load_const)
>              return false;
>
> +         if (var->is_power_of_two) {
> +            assert(var->is_constant);
> +            nir_const_value *val = nir_src_as_const_value(instr->src[src].src);
> +            for (unsigned i = 0; i < num_components; i++) {
> +               switch (nir_op_infos[instr->op].input_types[src]) {
> +               case nir_type_int:
> +                  if (!is_power_of_two(val->i32[new_swizzle[i]]))
> +                     return false;
> +                  break;
> +               case nir_type_uint:
> +                  if (!is_power_of_two(val->u32[new_swizzle[i]]))
> +                     return false;
> +                  break;
> +               default:
> +                  return false;
> +               }
> +            }
> +         }
> +
>           if (var->type != nir_type_invalid) {
>              if (instr->src[src].src.ssa->parent_instr->type != nir_instr_type_alu)
>                 return false;
> diff --git a/src/compiler/nir/nir_search.h b/src/compiler/nir/nir_search.h
> index a500feb..32ed538 100644
> --- a/src/compiler/nir/nir_search.h
> +++ b/src/compiler/nir/nir_search.h
> @@ -57,6 +57,13 @@ typedef struct {
>      */
>     bool is_constant;
>
> +   /** Indicates that the given constant is a power of two
> +    *
> +    * This is only allowed in search expressions, and only for constant
> +    * variables.
> +    */
> +   bool is_power_of_two;
> +
>     /** Indicates that the given variable must have a certain type
>      *
>      * This is only allowed in search expressions and indicates that the
> --
> 2.5.5
>


More information about the mesa-dev mailing list