[Mesa-dev] [PATCH 2/5] nir: shuffle constants to the top

Jason Ekstrand jason at jlekstrand.net
Thu Jan 19 01:22:08 UTC 2017


On Tue, Jan 17, 2017 at 6:12 PM, Timothy Arceri <
timothy.arceri at collabora.com> wrote:

> If one of the inputs to and mul/add  is the result of an another
> mul/add there is a chance that we can reuse the result of that
> mul/add in other calls if we do the multiplication in the right
> order.
>
> Also by attempting to move all constants to the top we increase
> the chance of constant folding.
>
> For example it is a fairly common pattern for shaders to do something
> similar to this:
>
>   const float a = 0.5;
>   in vec4 b;
>   in float c;
>
>   ...
>
>   b.x = b.x * c;
>   b.y = b.y * c;
>
>   ...
>
>   b.x = b.x * a + a;
>   b.y = b.y * a + a;
>
> So by simply detecting that constant a is part of the multiplication
> in ffma and switching it with previous fmul that updates b we end up
> with:
>
>   ...
>
>   c = a * c;
>
>   ...
>
>   b.x = b.x * c + a;
>   b.y = b.y * c + a;
>
> Shader-db results BDW:
>
> total instructions in shared programs: 13007456 -> 12964294 (-0.33%)
> instructions in affected programs: 4117749 -> 4074587 (-1.05%)
> helped: 17740
> HURT: 1342
>
> total cycles in shared programs: 246765094 -> 246454280 (-0.13%)
> cycles in affected programs: 167300168 -> 166989354 (-0.19%)
> helped: 18541
> HURT: 7955
>
> total spills in shared programs: 14937 -> 14560 (-2.52%)
> spills in affected programs: 9331 -> 8954 (-4.04%)
> helped: 284
> HURT: 33
>
> total fills in shared programs: 20211 -> 19671 (-2.67%)
> fills in affected programs: 12586 -> 12046 (-4.29%)
> helped: 286
> HURT: 33
>
> LOST:   40
> GAINED: 34
>
> Some of the hurt will go away when we shuffle things back down to the
> bottom in the following patch. It's also noteworthy that almost all of the
> spill changes as in Deus Ex both hurt and helped.
> ---
>  src/compiler/nir/nir_opt_algebraic.py |  8 +++++++-
>  src/compiler/nir/nir_search_helpers.h | 12 ++++++++++++
>  2 files changed, 19 insertions(+), 1 deletion(-)
>
> diff --git a/src/compiler/nir/nir_opt_algebraic.py
> b/src/compiler/nir/nir_opt_algebraic.py
> index 2c8ad64..797fc4b 100644
> --- a/src/compiler/nir/nir_opt_algebraic.py
> +++ b/src/compiler/nir/nir_opt_algebraic.py
> @@ -326,8 +326,14 @@ optimizations = [
>     (('fmul', ('fneg', a), b), ('fneg', ('fmul', a, b))),
>     (('imul', ('ineg', a), b), ('ineg', ('imul', a, b))),
>
> +   # Propagate constants up multiplication chains
> +   (('fmul(is_used_once)', ('fmul(is_used_once)', 'a(is_not_const)',
> 'b(is_not_const)'), '#c'), ('fmul', ('fmul', a, c), b)),
>

This needs to be tagged as an inexact optimization.  Do so by prefixing the
first fmul with "~"


> +   (('imul(is_used_once)', ('imul(is_used_once)', 'a(is_not_const)',
> 'b(is_not_const)'), '#c'), ('imul', ('imul', a, c), b)),
> +   (('fadd(is_used_once)', ('fadd(is_used_once)', 'a(is_not_const)',
> 'b(is_not_const)'), '#c'), ('fadd', ('fadd', a, c), b)),
>

Same here.

That will fix your dEQP and CTS regressions. :-)


> +   (('iadd(is_used_once)', ('iadd(is_used_once)', 'a(is_not_const)',
> 'b(is_not_const)'), '#c'), ('iadd', ('iadd', a, c), b)),
> +
>     # Reassociate constants in add/mul chains so they can be folded
> together.
> -   # For now, we only handle cases where the constants are separated by
> +   # For now, we mostly only handle cases where the constants are
> separated by
>     # a single non-constant.  We could do better eventually.
>     (('~fmul', '#a', ('fmul', b, '#c')), ('fmul', ('fmul', a, c), b)),
>     (('imul', '#a', ('imul', b, '#c')), ('imul', ('imul', a, c), b)),
> diff --git a/src/compiler/nir/nir_search_helpers.h
> b/src/compiler/nir/nir_search_helpers.h
> index 05bd317..09ae137 100644
> --- a/src/compiler/nir/nir_search_helpers.h
> +++ b/src/compiler/nir/nir_search_helpers.h
> @@ -115,6 +115,18 @@ is_zero_to_one(nir_alu_instr *instr, unsigned src,
> unsigned num_components,
>  }
>
>  static inline bool
> +is_not_const(nir_alu_instr *instr, unsigned src, unsigned num_components,
> +             const uint8_t *swizzle)
> +{
> +   nir_const_value *val = nir_src_as_const_value(instr->src[src].src);
> +
> +   if (val)
> +      return false;
> +
> +   return true;
> +}
> +
> +static inline bool
>  is_used_more_than_once(nir_alu_instr *instr)
>  {
>     bool zero_if_use = list_empty(&instr->dest.dest.ssa.if_uses);
> --
> 2.9.3
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170118/226a766f/attachment.html>


More information about the mesa-dev mailing list