<div dir="ltr">Reviewed-by: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Oct 27, 2017 at 5:05 PM, Francisco Jerez <span dir="ltr"><<a href="mailto:currojerez@riseup.net" target="_blank">currojerez@riseup.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">This makes the dataflow propagation logic of the copy propagation pass<br>
more intelligent in cases where the destination of a copy is known to<br>
be undefined for some incoming CFG edges, building upon the<br>
definedness information provided by the last patch.  Helps a few<br>
programs, and avoids a handful shader-db regressions from the next<br>
patch.<br>
<br>
shader-db results on ILK:<br>
<br>
  total instructions in shared programs: 6541547 -> 6541523 (-0.00%)<br>
  instructions in affected programs: 360 -> 336 (-6.67%)<br>
  helped: 8<br>
  HURT: 0<br>
<br>
  LOST:   0<br>
  GAINED: 10<br>
<br>
shader-db results on BDW:<br>
<br>
  total instructions in shared programs: 8174323 -> 8173882 (-0.01%)<br>
  instructions in affected programs: 7730 -> 7289 (-5.71%)<br>
  helped: 5<br>
  HURT: 2<br>
<br>
  LOST:   0<br>
  GAINED: 4<br>
<br>
shader-db results on SKL:<br>
<br>
  total instructions in shared programs: 8185669 -> 8184598 (-0.01%)<br>
  instructions in affected programs: 10364 -> 9293 (-10.33%)<br>
  helped: 5<br>
  HURT: 2<br>
<br>
  LOST:   0<br>
  GAINED: 2<br>
---<br>
 src/intel/compiler/brw_fs_<wbr>copy_propagation.cpp | 50 ++++++++++++++++++++++++--<br>
 1 file changed, 47 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/src/intel/compiler/brw_fs_<wbr>copy_propagation.cpp b/src/intel/compiler/brw_fs_<wbr>copy_propagation.cpp<br>
index cb117396089..5897cff35be 100644<br>
--- a/src/intel/compiler/brw_fs_<wbr>copy_propagation.cpp<br>
+++ b/src/intel/compiler/brw_fs_<wbr>copy_propagation.cpp<br>
@@ -36,9 +36,12 @@<br>
<br>
 #include "util/bitset.h"<br>
 #include "brw_fs.h"<br>
+#include "brw_fs_live_variables.h"<br>
 #include "brw_cfg.h"<br>
 #include "brw_eu.h"<br>
<br>
+using namespace brw;<br>
+<br>
 namespace { /* avoid conflict with opt_copy_propagation_elements */<br>
 struct acp_entry : public exec_node {<br>
    fs_reg dst;<br>
@@ -77,12 +80,19 @@ struct block_data {<br>
     * course of this block.<br>
     */<br>
    BITSET_WORD *kill;<br>
+<br>
+   /**<br>
+    * Which entries in the fs_copy_prop_dataflow acp table are guaranteed to<br>
+    * have a fully uninitialized destination at the end of this block.<br>
+    */<br>
+   BITSET_WORD *undef;<br>
 };<br>
<br>
 class fs_copy_prop_dataflow<br>
 {<br>
 public:<br>
    fs_copy_prop_dataflow(void *mem_ctx, cfg_t *cfg,<br>
+                         const fs_live_variables *live,<br>
                          exec_list *out_acp[ACP_HASH_SIZE]);<br>
<br>
    void setup_initial_values();<br>
@@ -92,6 +102,7 @@ public:<br>
<br>
    void *mem_ctx;<br>
    cfg_t *cfg;<br>
+   const fs_live_variables *live;<br>
<br>
    acp_entry **acp;<br>
    int num_acp;<br>
@@ -102,8 +113,9 @@ public:<br>
 } /* anonymous namespace */<br>
<br>
 fs_copy_prop_dataflow::fs_<wbr>copy_prop_dataflow(void *mem_ctx, cfg_t *cfg,<br>
+                                             const fs_live_variables *live,<br>
                                              exec_list *out_acp[ACP_HASH_SIZE])<br>
-   : mem_ctx(mem_ctx), cfg(cfg)<br>
+   : mem_ctx(mem_ctx), cfg(cfg), live(live)<br>
 {<br>
    bd = rzalloc_array(mem_ctx, struct block_data, cfg->num_blocks);<br>
<br>
@@ -124,6 +136,7 @@ fs_copy_prop_dataflow::fs_<wbr>copy_prop_dataflow(void *mem_ctx, cfg_t *cfg,<br>
       bd[block->num].liveout = rzalloc_array(bd, BITSET_WORD, bitset_words);<br>
       bd[block->num].copy = rzalloc_array(bd, BITSET_WORD, bitset_words);<br>
       bd[block->num].kill = rzalloc_array(bd, BITSET_WORD, bitset_words);<br>
+      bd[block->num].undef = rzalloc_array(bd, BITSET_WORD, bitset_words);<br>
<br>
       for (int i = 0; i < ACP_HASH_SIZE; i++) {<br>
          foreach_in_list(acp_entry, entry, &out_acp[block->num][i]) {<br>
@@ -189,6 +202,18 @@ fs_copy_prop_dataflow::setup_<wbr>initial_values()<br>
          }<br>
       }<br>
    }<br>
+<br>
+   /* Initialize the undef set. */<br>
+   foreach_block (block, cfg) {<br>
+      for (int i = 0; i < num_acp; i++) {<br>
+         BITSET_SET(bd[block->num].<wbr>undef, i);<br>
+         for (unsigned off = 0; off < acp[i]->size_written; off += REG_SIZE) {<br>
+            if (BITSET_TEST(live->block_data[<wbr>block->num].defout,<br>
+                            live->var_from_reg(byte_<wbr>offset(acp[i]->dst, off))))<br>
+               BITSET_CLEAR(bd[block->num].<wbr>undef, i);<br>
+         }<br>
+      }<br>
+   }<br>
 }<br>
<br>
 /**<br>
@@ -229,13 +254,30 @@ fs_copy_prop_dataflow::run()<br>
<br>
          for (int i = 0; i < bitset_words; i++) {<br>
             const BITSET_WORD old_livein = bd[block->num].livein[i];<br>
+            BITSET_WORD livein_from_any_block = 0;<br>
<br>
             bd[block->num].livein[i] = ~0u;<br>
             foreach_list_typed(bblock_<wbr>link, parent_link, link, &block->parents) {<br>
                bblock_t *parent = parent_link->block;<br>
-               bd[block->num].livein[i] &= bd[parent->num].liveout[i];<br>
+               /* Consider ACP entries with a known-undefined destination to<br>
+                * be available from the parent.  This is valid because we're<br>
+                * free to set the undefined variable equal to the source of<br>
+                * the ACP entry without breaking the application's<br>
+                * expectations, since the variable is undefined.<br>
+                */<br>
+               bd[block->num].livein[i] &= (bd[parent->num].liveout[i] |<br>
+                                            bd[parent->num].undef[i]);<br>
+               livein_from_any_block |= bd[parent->num].liveout[i];<br>
             }<br>
<br>
+            /* Limit to the set of ACP entries that can possibly be available<br>
+             * at the start of the block, since propagating from a variable<br>
+             * which is guaranteed to be undefined (rather than potentially<br>
+             * undefined for some dynamic control-flow paths) doesn't seem<br>
+             * particularly useful.<br>
+             */<br>
+            bd[block->num].livein[i] &= livein_from_any_block;<br>
+<br>
             if (old_livein != bd[block->num].livein[i])<br>
                progress = true;<br>
          }<br>
@@ -830,6 +872,8 @@ fs_visitor::opt_copy_<wbr>propagation()<br>
    for (int i = 0; i < cfg->num_blocks; i++)<br>
       out_acp[i] = new exec_list [ACP_HASH_SIZE];<br>
<br>
+   calculate_live_intervals();<br>
+<br>
    /* First, walk through each block doing local copy propagation and getting<br>
     * the set of copies available at the end of the block.<br>
     */<br>
@@ -839,7 +883,7 @@ fs_visitor::opt_copy_<wbr>propagation()<br>
    }<br>
<br>
    /* Do dataflow analysis for those available copies. */<br>
-   fs_copy_prop_dataflow dataflow(copy_prop_ctx, cfg, out_acp);<br>
+   fs_copy_prop_dataflow dataflow(copy_prop_ctx, cfg, live_intervals, out_acp);<br>
<br>
    /* Next, re-run local copy propagation, this time with the set of copies<br>
     * provided by the dataflow analysis available at the start of a block.<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.14.2<br>
<br>
</font></span></blockquote></div><br></div>