<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>