1 |
From bcfca5b35cfec467ef36487116a56dce85c589db Mon Sep 17 00:00:00 2001 |
2 |
From: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com> |
3 |
Date: Fri, 14 Dec 2018 16:10:32 -0800 |
4 |
Subject: [PATCH 31/78] nir: properly find the entry to keep in copy_prop_vars |
5 |
|
6 |
When copy propagation handles a store/copy, it iterates the current |
7 |
copy entries to remove aliases, but keeps the "equal" entry (if |
8 |
exists) to be updated. |
9 |
|
10 |
The removal step may swap the entries around (to ensure there are no |
11 |
holes), invalidating previous iteration pointers. The bug was saving |
12 |
such pointer to use later. Change the code to first perform the |
13 |
removals and then find the remaining right entry. |
14 |
|
15 |
This was causing updates to be lost since they were being made to an |
16 |
entry that was not part of the current copies. |
17 |
|
18 |
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108624 |
19 |
Fixes: b3c61469255 "nir: Copy propagation between blocks" |
20 |
Cc: mesa-stable@lists.freedesktop.org |
21 |
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> |
22 |
(cherry picked from commit 947f7b452a550c66cfb9a8c9518e35635eb25947) |
23 |
--- |
24 |
src/compiler/nir/nir_opt_copy_prop_vars.c | 19 ++++++++++++++++--- |
25 |
1 file changed, 16 insertions(+), 3 deletions(-) |
26 |
|
27 |
diff --git a/src/compiler/nir/nir_opt_copy_prop_vars.c b/src/compiler/nir/nir_opt_copy_prop_vars.c |
28 |
index 1e6158bf51..29b2caba89 100644 |
29 |
--- a/src/compiler/nir/nir_opt_copy_prop_vars.c |
30 |
+++ b/src/compiler/nir/nir_opt_copy_prop_vars.c |
31 |
@@ -265,7 +265,7 @@ lookup_entry_and_kill_aliases(struct util_dynarray *copies, |
32 |
{ |
33 |
/* TODO: Take into account the write_mask. */ |
34 |
|
35 |
- struct copy_entry *entry = NULL; |
36 |
+ nir_deref_instr *dst_match = NULL; |
37 |
util_dynarray_foreach_reverse(copies, struct copy_entry, iter) { |
38 |
if (!iter->src.is_ssa) { |
39 |
/* If this write aliases the source of some entry, get rid of it */ |
40 |
@@ -278,13 +278,26 @@ lookup_entry_and_kill_aliases(struct util_dynarray *copies, |
41 |
nir_deref_compare_result comp = nir_compare_derefs(iter->dst, deref); |
42 |
|
43 |
if (comp & nir_derefs_equal_bit) { |
44 |
- assert(entry == NULL); |
45 |
- entry = iter; |
46 |
+ /* Removing entries invalidate previous iter pointers, so we'll |
47 |
+ * collect the matching entry later. Just make sure it is unique. |
48 |
+ */ |
49 |
+ assert(!dst_match); |
50 |
+ dst_match = iter->dst; |
51 |
} else if (comp & nir_derefs_may_alias_bit) { |
52 |
copy_entry_remove(copies, iter); |
53 |
} |
54 |
} |
55 |
|
56 |
+ struct copy_entry *entry = NULL; |
57 |
+ if (dst_match) { |
58 |
+ util_dynarray_foreach(copies, struct copy_entry, iter) { |
59 |
+ if (iter->dst == dst_match) { |
60 |
+ entry = iter; |
61 |
+ break; |
62 |
+ } |
63 |
+ } |
64 |
+ assert(entry); |
65 |
+ } |
66 |
return entry; |
67 |
} |
68 |
|
69 |
-- |
70 |
2.20.1 |
71 |
|