nir/nir_opt_copy_prop_vars: remove extra loop

The fix in 947f7b452a introduced an extra loop over the copies
array to find the correct entry in the case it had been moved.

The problem is these loops can be iterated over millions of times
so lets simply update the entry pointer in the case we change its
location in the array.

Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20381>
This commit is contained in:
Timothy Arceri
2022-12-21 10:29:45 +11:00
committed by Marge Bot
parent 4e09d37f3b
commit 8f6f5730f6
+20 -22
View File
@@ -327,10 +327,20 @@ copy_entry_create(struct util_dynarray *copies,
*/
static void
copy_entry_remove(struct util_dynarray *copies,
struct copy_entry *entry)
struct copy_entry *entry,
struct copy_entry **relocated_entry)
{
const struct copy_entry *src =
util_dynarray_pop_ptr(copies, struct copy_entry);
/* Because we're removing elements from an array, pointers to those
* elements are not stable as we modify the array.
* If relocated_entry != NULL, it's points to an entry we saved off earlier
* and want to keep pointing to the right spot.
*/
if (relocated_entry && *relocated_entry == src)
*relocated_entry = entry;
if (src != entry)
*entry = *src;
}
@@ -377,14 +387,14 @@ lookup_entry_and_kill_aliases(struct copy_prop_var_state *state,
{
/* TODO: Take into account the write_mask. */
nir_deref_instr *dst_match = NULL;
struct copy_entry *entry = 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 */
nir_deref_compare_result result =
nir_compare_derefs_and_paths(state->mem_ctx, &iter->src.deref, deref);
if (result & nir_derefs_may_alias_bit) {
copy_entry_remove(copies, iter);
copy_entry_remove(copies, iter, &entry);
continue;
}
}
@@ -393,26 +403,14 @@ lookup_entry_and_kill_aliases(struct copy_prop_var_state *state,
nir_compare_derefs_and_paths(state->mem_ctx, &iter->dst, deref);
if (comp & nir_derefs_equal_bit) {
/* 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.instr;
/* Make sure it is unique. */
assert(!entry);
entry = iter;
} else if (comp & nir_derefs_may_alias_bit) {
copy_entry_remove(copies, iter);
copy_entry_remove(copies, iter, &entry);
}
}
struct copy_entry *entry = NULL;
if (dst_match) {
util_dynarray_foreach(copies, struct copy_entry, iter) {
if (iter->dst.instr == dst_match) {
entry = iter;
break;
}
}
assert(entry);
}
return entry;
}
@@ -427,7 +425,7 @@ kill_aliases(struct copy_prop_var_state *state,
struct copy_entry *entry =
lookup_entry_and_kill_aliases(state, copies, deref, write_mask);
if (entry)
copy_entry_remove(copies, entry);
copy_entry_remove(copies, entry, NULL);
}
static struct copy_entry *
@@ -454,7 +452,7 @@ apply_barrier_for_modes(struct util_dynarray *copies,
util_dynarray_foreach_reverse(copies, struct copy_entry, iter) {
if (nir_deref_mode_may_be(iter->dst.instr, modes) ||
(!iter->src.is_ssa && nir_deref_mode_may_be(iter->src.deref.instr, modes)))
copy_entry_remove(copies, iter);
copy_entry_remove(copies, iter, NULL);
}
}
@@ -754,7 +752,7 @@ invalidate_copies_for_cf_node(struct copy_prop_var_state *state,
if (written->modes) {
util_dynarray_foreach_reverse(copies, struct copy_entry, entry) {
if (nir_deref_mode_may_be(entry->dst.instr, written->modes))
copy_entry_remove(copies, entry);
copy_entry_remove(copies, entry, NULL);
}
}