summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <[email protected]>2018-12-14 16:10:32 -0800
committerCaio Marcelo de Oliveira Filho <[email protected]>2018-12-19 09:33:36 -0800
commit947f7b452a550c66cfb9a8c9518e35635eb25947 (patch)
tree952302c5c33db3b7f1ac2f77d2d8ad6410bbce27 /src/compiler
parent9d8395bf0e4bfa6ef1344dbc9aebcf183aa9f9b5 (diff)
nir: properly find the entry to keep in copy_prop_vars
When copy propagation handles a store/copy, it iterates the current copy entries to remove aliases, but keeps the "equal" entry (if exists) to be updated. The removal step may swap the entries around (to ensure there are no holes), invalidating previous iteration pointers. The bug was saving such pointer to use later. Change the code to first perform the removals and then find the remaining right entry. This was causing updates to be lost since they were being made to an entry that was not part of the current copies. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108624 Fixes: b3c61469255 "nir: Copy propagation between blocks" Cc: [email protected] Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/nir/nir_opt_copy_prop_vars.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/compiler/nir/nir_opt_copy_prop_vars.c b/src/compiler/nir/nir_opt_copy_prop_vars.c
index ce106be8de3..771f125650e 100644
--- a/src/compiler/nir/nir_opt_copy_prop_vars.c
+++ b/src/compiler/nir/nir_opt_copy_prop_vars.c
@@ -280,7 +280,7 @@ lookup_entry_and_kill_aliases(struct util_dynarray *copies,
{
/* TODO: Take into account the write_mask. */
- struct copy_entry *entry = NULL;
+ nir_deref_instr *dst_match = NULL;
util_dynarray_foreach_reverse(copies, struct copy_entry, iter) {
if (!iter->src.is_ssa) {
/* If this write aliases the source of some entry, get rid of it */
@@ -293,13 +293,26 @@ lookup_entry_and_kill_aliases(struct util_dynarray *copies,
nir_deref_compare_result comp = nir_compare_derefs(iter->dst, deref);
if (comp & nir_derefs_equal_bit) {
- assert(entry == NULL);
- entry = iter;
+ /* Removing entries invalidate previous iter pointers, so we'll
+ * collect the matching entry later. Just make sure it is unique.
+ */
+ assert(!dst_match);
+ dst_match = iter->dst;
} else if (comp & nir_derefs_may_alias_bit) {
copy_entry_remove(copies, iter);
}
}
+ struct copy_entry *entry = NULL;
+ if (dst_match) {
+ util_dynarray_foreach(copies, struct copy_entry, iter) {
+ if (iter->dst == dst_match) {
+ entry = iter;
+ break;
+ }
+ }
+ assert(entry);
+ }
return entry;
}