<div dir="auto"><div>I have a similar patch locally on my machine.</div><div dir="auto">s/list/set in the very last comment in the patch and it is:</div><div dir="auto"><br></div><div dir="auto">Reviewed-by: Thomas Helland <<a href="mailto:thomashelland90@gmail.com">thomashelland90@gmail.com</a>><br><div class="gmail_extra" dir="auto"><br></div><div class="gmail_extra" dir="auto">There are also similar situations in other areas where we can</div><div class="gmail_extra" dir="auto">do the same trick. Constant propagation I believe?</div><div class="gmail_extra" dir="auto">Afk, so can't check what other passes I looked at.</div><div class="gmail_extra" dir="auto"><br></div><div class="gmail_extra" dir="auto"><div class="gmail_quote" dir="auto">17. mar. 2017 14.41 skrev "Timothy Arceri" <<a href="mailto:tarceri@itsqueeze.com">tarceri@itsqueeze.com</a>>:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Previously each time we saw a variable we just created a duplicate<br>
entry in the list. This is particularly bad for loops were we add<br>
everything twice, and then throw nested loops into the mix and the<br>
list was growing expoentially.<br>
<br>
This stops the glsl-vs-unroll-explosion test which has 16 nested<br>
loops from reaching the tests mem usage limit in this pass. The<br>
test now hits the mem limit in opt_copy_propagation_elements(<wbr>)<br>
instead.<br>
<br>
I suspect this was also part of the reason this pass can be so<br>
slow with some shaders.<br>
---<br>
 src/compiler/glsl/opt_copy_<wbr>propagation.cpp | 65 +++++++++++++-----------------<br>
 1 file changed, 28 insertions(+), 37 deletions(-)<br>
<br>
diff --git a/src/compiler/glsl/opt_copy_<wbr>propagation.cpp b/src/compiler/glsl/opt_copy_<wbr>propagation.cpp<br>
index 2240421..c9c41f2 100644<br>
--- a/src/compiler/glsl/opt_copy_<wbr>propagation.cpp<br>
+++ b/src/compiler/glsl/opt_copy_<wbr>propagation.cpp<br>
@@ -31,48 +31,35 @@<br>
  * programs unless copy propagation is also done on the LIR, and may<br>
  * help anyway by triggering other optimizations that live in the HIR.<br>
  */<br>
<br>
 #include "ir.h"<br>
 #include "ir_visitor.h"<br>
 #include "ir_basic_block.h"<br>
 #include "ir_optimization.h"<br>
 #include "compiler/glsl_types.h"<br>
 #include "util/hash_table.h"<br>
+#include "util/set.h"<br>
<br>
 namespace {<br>
<br>
-class kill_entry : public exec_node<br>
-{<br>
-public:<br>
-   /* override operator new from exec_node */<br>
-   DECLARE_LINEAR_ZALLOC_CXX_<wbr>OPERATORS(kill_entry)<br>
-<br>
-   kill_entry(ir_variable *var)<br>
-   {<br>
-      assert(var);<br>
-      this->var = var;<br>
-   }<br>
-<br>
-   ir_variable *var;<br>
-};<br>
-<br>
 class ir_copy_propagation_visitor : public ir_hierarchical_visitor {<br>
 public:<br>
    ir_copy_propagation_visitor()<br>
    {<br>
       progress = false;<br>
       mem_ctx = ralloc_context(0);<br>
       lin_ctx = linear_alloc_parent(mem_ctx, 0);<br>
       acp = _mesa_hash_table_create(mem_<wbr>ctx, _mesa_hash_pointer,<br>
                                     _mesa_key_pointer_equal);<br>
-      this->kills = new(mem_ctx) exec_list;<br>
+      kills = _mesa_set_create(mem_ctx, _mesa_hash_pointer,<br>
+                               _mesa_key_pointer_equal);<br>
       killed_all = false;<br>
    }<br>
    ~ir_copy_propagation_visitor()<br>
    {<br>
       ralloc_free(mem_ctx);<br>
    }<br>
<br>
    virtual ir_visitor_status visit(class ir_dereference_variable *);<br>
    void handle_loop(class ir_loop *, bool keep_acp);<br>
    virtual ir_visitor_status visit_enter(class ir_loop *);<br>
@@ -81,56 +68,57 @@ public:<br>
    virtual ir_visitor_status visit_leave(class ir_assignment *);<br>
    virtual ir_visitor_status visit_enter(class ir_call *);<br>
    virtual ir_visitor_status visit_enter(class ir_if *);<br>
<br>
    void add_copy(ir_assignment *ir);<br>
    void kill(ir_variable *ir);<br>
    void handle_if_block(exec_list *instructions);<br>
<br>
    /** Hash of lhs->rhs: The available copies to propagate */<br>
    hash_table *acp;<br>
+<br>
    /**<br>
-    * List of kill_entry: The variables whose values were killed in this<br>
-    * block.<br>
+    * Set of kill_entry: The variables whose values were killed in this block.<br>
     */<br>
-   exec_list *kills;<br>
+   set *kills;<br>
<br>
    bool progress;<br>
<br>
    bool killed_all;<br>
<br>
    void *mem_ctx;<br>
    void *lin_ctx;<br>
 };<br>
<br>
 } /* unnamed namespace */<br>
<br>
 ir_visitor_status<br>
 ir_copy_propagation_visitor::<wbr>visit_enter(ir_function_<wbr>signature *ir)<br>
 {<br>
    /* Treat entry into a function signature as a completely separate<br>
     * block.  Any instructions at global scope will be shuffled into<br>
     * main() at link time, so they're irrelevant to us.<br>
     */<br>
    hash_table *orig_acp = this->acp;<br>
-   exec_list *orig_kills = this->kills;<br>
+   set *orig_kills = this->kills;<br>
    bool orig_killed_all = this->killed_all;<br>
<br>
    acp = _mesa_hash_table_create(NULL, _mesa_hash_pointer,<br>
                                  _mesa_key_pointer_equal);<br>
-   this->kills = new(mem_ctx) exec_list;<br>
+   kills = _mesa_set_create(NULL, _mesa_hash_pointer,<br>
+                            _mesa_key_pointer_equal);<br>
    this->killed_all = false;<br>
<br>
    visit_list_elements(this, &ir->body);<br>
<br>
    _mesa_hash_table_destroy(acp, NULL);<br>
-   ralloc_free(this->kills);<br>
+   _mesa_set_destroy(kills, NULL);<br>
<br>
    this->kills = orig_kills;<br>
    this->acp = orig_acp;<br>
    this->killed_all = orig_killed_all;<br>
<br>
    return visit_continue_with_parent;<br>
 }<br>
<br>
 ir_visitor_status<br>
 ir_copy_propagation_visitor::<wbr>visit_leave(ir_assignment *ir)<br>
@@ -215,101 +203,105 @@ ir_copy_propagation_visitor::<wbr>visit_enter(ir_call *ir)<br>
       }<br>
    }<br>
<br>
    return visit_continue_with_parent;<br>
 }<br>
<br>
 void<br>
 ir_copy_propagation_visitor::<wbr>handle_if_block(exec_list *instructions)<br>
 {<br>
    hash_table *orig_acp = this->acp;<br>
-   exec_list *orig_kills = this->kills;<br>
+   set *orig_kills = this->kills;<br>
    bool orig_killed_all = this->killed_all;<br>
<br>
    acp = _mesa_hash_table_create(NULL, _mesa_hash_pointer,<br>
                                  _mesa_key_pointer_equal);<br>
-   this->kills = new(mem_ctx) exec_list;<br>
+   kills = _mesa_set_create(NULL, _mesa_hash_pointer,<br>
+                            _mesa_key_pointer_equal);<br>
    this->killed_all = false;<br>
<br>
    /* Populate the initial acp with a copy of the original */<br>
    struct hash_entry *entry;<br>
    hash_table_foreach(orig_acp, entry) {<br>
       _mesa_hash_table_insert(acp, entry->key, entry->data);<br>
    }<br>
<br>
    visit_list_elements(this, instructions);<br>
<br>
    if (this->killed_all) {<br>
       _mesa_hash_table_clear(orig_<wbr>acp, NULL);<br>
    }<br>
<br>
-   exec_list *new_kills = this->kills;<br>
+   set *new_kills = this->kills;<br>
    this->kills = orig_kills;<br>
    _mesa_hash_table_destroy(acp, NULL);<br>
    this->acp = orig_acp;<br>
    this->killed_all = this->killed_all || orig_killed_all;<br>
<br>
-   foreach_in_list(kill_entry, k, new_kills) {<br>
-      kill(k->var);<br>
+   struct set_entry *s_entry;<br>
+   set_foreach(new_kills, s_entry) {<br>
+      kill((ir_variable *) s_entry->key);<br>
    }<br>
<br>
-   ralloc_free(new_kills);<br>
+   _mesa_set_destroy(new_kills, NULL);<br>
 }<br>
<br>
 ir_visitor_status<br>
 ir_copy_propagation_visitor::<wbr>visit_enter(ir_if *ir)<br>
 {<br>
    ir->condition->accept(this);<br>
<br>
    handle_if_block(&ir->then_<wbr>instructions);<br>
    handle_if_block(&ir->else_<wbr>instructions);<br>
<br>
    /* handle_if_block() already descended into the children. */<br>
    return visit_continue_with_parent;<br>
 }<br>
<br>
 void<br>
 ir_copy_propagation_visitor::<wbr>handle_loop(ir_loop *ir, bool keep_acp)<br>
 {<br>
    hash_table *orig_acp = this->acp;<br>
-   exec_list *orig_kills = this->kills;<br>
+   set *orig_kills = this->kills;<br>
    bool orig_killed_all = this->killed_all;<br>
<br>
    acp = _mesa_hash_table_create(NULL, _mesa_hash_pointer,<br>
                                  _mesa_key_pointer_equal);<br>
-   this->kills = new(mem_ctx) exec_list;<br>
+   kills = _mesa_set_create(NULL, _mesa_hash_pointer,<br>
+                            _mesa_key_pointer_equal);<br>
    this->killed_all = false;<br>
<br>
    if (keep_acp) {<br>
       struct hash_entry *entry;<br>
       hash_table_foreach(orig_acp, entry) {<br>
          _mesa_hash_table_insert(acp, entry->key, entry->data);<br>
       }<br>
    }<br>
<br>
    visit_list_elements(this, &ir->body_instructions);<br>
<br>
    if (this->killed_all) {<br>
       _mesa_hash_table_clear(orig_<wbr>acp, NULL);<br>
    }<br>
<br>
-   exec_list *new_kills = this->kills;<br>
+   set *new_kills = this->kills;<br>
    this->kills = orig_kills;<br>
    _mesa_hash_table_destroy(acp, NULL);<br>
    this->acp = orig_acp;<br>
    this->killed_all = this->killed_all || orig_killed_all;<br>
<br>
-   foreach_in_list(kill_entry, k, new_kills) {<br>
-      kill(k->var);<br>
+   struct set_entry *entry;<br>
+   set_foreach(new_kills, entry) {<br>
+      kill((ir_variable *) entry->key);<br>
    }<br>
<br>
-   ralloc_free(new_kills);<br>
+   _mesa_set_destroy(new_kills, NULL);<br>
 }<br>
<br>
 ir_visitor_status<br>
 ir_copy_propagation_visitor::<wbr>visit_enter(ir_loop *ir)<br>
 {<br>
    /* Make a conservative first pass over the loop with an empty ACP set.<br>
     * This also removes any killed entries from the original ACP set.<br>
     */<br>
    handle_loop(ir, false);<br>
<br>
@@ -332,23 +324,22 @@ ir_copy_propagation_visitor::<wbr>kill(ir_variable *var)<br>
    if (entry) {<br>
       _mesa_hash_table_remove(acp, entry);<br>
    }<br>
<br>
    hash_table_foreach(acp, entry) {<br>
       if (var == (ir_variable *) entry->data) {<br>
          _mesa_hash_table_remove(acp, entry);<br>
       }<br>
    }<br>
<br>
-   /* Add the LHS variable to the list of killed variables in this block.<br>
-    */<br>
-   this->kills->push_tail(new(<wbr>this->lin_ctx) kill_entry(var));<br>
+   /* Add the LHS variable to the list of killed variables in this block. */<br>
+   _mesa_set_add(kills, var);<br>
 }<br>
<br>
 /**<br>
  * Adds an entry to the available copy list if it's a plain assignment<br>
  * of a variable to a variable.<br>
  */<br>
 void<br>
 ir_copy_propagation_visitor::<wbr>add_copy(ir_assignment *ir)<br>
 {<br>
    if (ir->condition)<br>
<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></blockquote></div><br></div></div></div>