<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Jan 17, 2017 at 6:12 PM, Timothy Arceri <span dir="ltr"><<a href="mailto:timothy.arceri@collabora.com" target="_blank">timothy.arceri@collabora.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">If one of the inputs to and mul/add  is the result of an another<br>
mul/add there is a chance that we can reuse the result of that<br>
mul/add in other calls if we do the multiplication in the right<br>
order.<br>
<br>
Also by attempting to move all constants to the top we increase<br>
the chance of constant folding.<br>
<br>
For example it is a fairly common pattern for shaders to do something<br>
similar to this:<br>
<br>
  const float a = 0.5;<br>
  in vec4 b;<br>
  in float c;<br>
<br>
  ...<br>
<br>
  b.x = b.x * c;<br>
  b.y = b.y * c;<br>
<br>
  ...<br>
<br>
  b.x = b.x * a + a;<br>
  b.y = b.y * a + a;<br>
<br>
So by simply detecting that constant a is part of the multiplication<br>
in ffma and switching it with previous fmul that updates b we end up<br>
with:<br>
<br>
  ...<br>
<br>
  c = a * c;<br>
<br>
  ...<br>
<br>
  b.x = b.x * c + a;<br>
  b.y = b.y * c + a;<br>
<br>
Shader-db results BDW:<br>
<br>
total instructions in shared programs: 13007456 -> 12964294 (-0.33%)<br>
instructions in affected programs: 4117749 -> 4074587 (-1.05%)<br>
helped: 17740<br>
HURT: 1342<br>
<br>
total cycles in shared programs: 246765094 -> 246454280 (-0.13%)<br>
cycles in affected programs: 167300168 -> 166989354 (-0.19%)<br>
helped: 18541<br>
HURT: 7955<br>
<br>
total spills in shared programs: 14937 -> 14560 (-2.52%)<br>
spills in affected programs: 9331 -> 8954 (-4.04%)<br>
helped: 284<br>
HURT: 33<br>
<br>
total fills in shared programs: 20211 -> 19671 (-2.67%)<br>
fills in affected programs: 12586 -> 12046 (-4.29%)<br>
helped: 286<br>
HURT: 33<br>
<br>
LOST:   40<br>
GAINED: 34<br>
<br>
Some of the hurt will go away when we shuffle things back down to the<br>
bottom in the following patch. It's also noteworthy that almost all of the<br>
spill changes as in Deus Ex both hurt and helped.<br>
---<br>
 src/compiler/nir/nir_opt_<wbr>algebraic.py |  8 +++++++-<br>
 src/compiler/nir/nir_search_<wbr>helpers.h | 12 ++++++++++++<br>
 2 files changed, 19 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/compiler/nir/nir_opt_<wbr>algebraic.py b/src/compiler/nir/nir_opt_<wbr>algebraic.py<br>
index 2c8ad64..797fc4b 100644<br>
--- a/src/compiler/nir/nir_opt_<wbr>algebraic.py<br>
+++ b/src/compiler/nir/nir_opt_<wbr>algebraic.py<br>
@@ -326,8 +326,14 @@ optimizations = [<br>
    (('fmul', ('fneg', a), b), ('fneg', ('fmul', a, b))),<br>
    (('imul', ('ineg', a), b), ('ineg', ('imul', a, b))),<br>
<br>
+   # Propagate constants up multiplication chains<br>
+   (('fmul(is_used_once)', ('fmul(is_used_once)', 'a(is_not_const)', 'b(is_not_const)'), '#c'), ('fmul', ('fmul', a, c), b)),<br></blockquote><div><br></div><div>This needs to be tagged as an inexact optimization.  Do so by prefixing the first fmul with "~"<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   (('imul(is_used_once)', ('imul(is_used_once)', 'a(is_not_const)', 'b(is_not_const)'), '#c'), ('imul', ('imul', a, c), b)),<br>
+   (('fadd(is_used_once)', ('fadd(is_used_once)', 'a(is_not_const)', 'b(is_not_const)'), '#c'), ('fadd', ('fadd', a, c), b)),<br></blockquote><div><br></div><div>Same here.<br><br></div><div>That will fix your dEQP and CTS regressions. :-)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+   (('iadd(is_used_once)', ('iadd(is_used_once)', 'a(is_not_const)', 'b(is_not_const)'), '#c'), ('iadd', ('iadd', a, c), b)),<br>
+<br>
    # Reassociate constants in add/mul chains so they can be folded together.<br>
-   # For now, we only handle cases where the constants are separated by<br>
+   # For now, we mostly only handle cases where the constants are separated by<br>
    # a single non-constant.  We could do better eventually.<br>
    (('~fmul', '#a', ('fmul', b, '#c')), ('fmul', ('fmul', a, c), b)),<br>
    (('imul', '#a', ('imul', b, '#c')), ('imul', ('imul', a, c), b)),<br>
diff --git a/src/compiler/nir/nir_search_<wbr>helpers.h b/src/compiler/nir/nir_search_<wbr>helpers.h<br>
index 05bd317..09ae137 100644<br>
--- a/src/compiler/nir/nir_search_<wbr>helpers.h<br>
+++ b/src/compiler/nir/nir_search_<wbr>helpers.h<br>
@@ -115,6 +115,18 @@ is_zero_to_one(nir_alu_instr *instr, unsigned src, unsigned num_components,<br>
 }<br>
<br>
 static inline bool<br>
+is_not_const(nir_alu_instr *instr, unsigned src, unsigned num_components,<br>
+             const uint8_t *swizzle)<br>
+{<br>
+   nir_const_value *val = nir_src_as_const_value(instr-><wbr>src[src].src);<br>
+<br>
+   if (val)<br>
+      return false;<br>
+<br>
+   return true;<br>
+}<br>
+<br>
+static inline bool<br>
 is_used_more_than_once(nir_<wbr>alu_instr *instr)<br>
 {<br>
    bool zero_if_use = list_empty(&instr->dest.dest.<wbr>ssa.if_uses);<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.9.3<br>
<br>
______________________________<wbr>_________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>