Mesa (master): nir/opt_vectorize: use a single instruction per hash entry instead of a vector
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Dec 31 17:03:11 UTC 2020
Module: Mesa
Branch: master
Commit: ad37e4df734f6d818ea3c7297a4757b5266b1468
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=ad37e4df734f6d818ea3c7297a4757b5266b1468
Author: Daniel Schürmann <daniel at schuermann.dev>
Date: Wed Sep 23 15:08:13 2020 +0100
nir/opt_vectorize: use a single instruction per hash entry instead of a vector
This drastically simplifies vectorization but may potentially
lead to slightly worse vectorizations.
Reviewed-by: Connor Abbott <cwabbott0 at gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6666>
---
src/compiler/nir/nir_opt_vectorize.c | 139 ++++++-----------------------------
1 file changed, 24 insertions(+), 115 deletions(-)
diff --git a/src/compiler/nir/nir_opt_vectorize.c b/src/compiler/nir/nir_opt_vectorize.c
index 80115be0ce5..2231651ea5e 100644
--- a/src/compiler/nir/nir_opt_vectorize.c
+++ b/src/compiler/nir/nir_opt_vectorize.c
@@ -62,8 +62,9 @@ hash_alu(uint32_t hash, const nir_alu_instr *instr)
}
static uint32_t
-hash_instr(const nir_instr *instr)
+hash_instr(const void *data)
{
+ const nir_instr *instr = (nir_instr *) data;
uint32_t hash = 0;
switch (instr->type) {
@@ -96,8 +97,10 @@ alu_srcs_equal(const nir_alu_src *src1, const nir_alu_src *src2)
}
static bool
-instrs_equal(const nir_instr *instr1, const nir_instr *instr2)
+instrs_equal(const void *data1, const void *data2)
{
+ const nir_instr *instr1 = (nir_instr *) data1;
+ const nir_instr *instr2 = (nir_instr *) data2;
switch (instr1->type) {
case nir_instr_type_alu: {
nir_alu_instr *alu1 = nir_instr_as_alu(instr1);
@@ -315,78 +318,10 @@ instr_try_combine(struct nir_shader *nir, nir_instr *instr1, nir_instr *instr2,
return &new_alu->instr;
}
-/*
- * Use an array to represent a stack of instructions that are equivalent.
- *
- * We push and pop instructions off the stack in dominance order. The first
- * element dominates the second element which dominates the third, etc. When
- * trying to add to the stack, first we try and combine the instruction with
- * each of the instructions on the stack and, if successful, replace the
- * instruction on the stack with the newly-combined instruction.
- */
-
-static struct util_dynarray *
-vec_instr_stack_create(void *mem_ctx)
-{
- struct util_dynarray *stack = ralloc(mem_ctx, struct util_dynarray);
- util_dynarray_init(stack, mem_ctx);
- return stack;
-}
-
-/* returns true if we were able to successfully replace the instruction */
-
-static bool
-vec_instr_stack_push(struct nir_shader *nir, struct util_dynarray *stack,
- nir_instr *instr,
- nir_opt_vectorize_cb filter, void *data)
-{
- /* Walk the stack from child to parent to make live ranges shorter by
- * matching the closest thing we can
- */
- util_dynarray_foreach_reverse(stack, nir_instr *, stack_instr) {
- nir_instr *new_instr = instr_try_combine(nir, *stack_instr, instr,
- filter, data);
- if (new_instr) {
- *stack_instr = new_instr;
- return true;
- }
- }
-
- util_dynarray_append(stack, nir_instr *, instr);
- return false;
-}
-
-static void
-vec_instr_stack_pop(struct util_dynarray *stack, nir_instr *instr)
-{
- ASSERTED nir_instr *last = util_dynarray_pop(stack, nir_instr *);
- assert(last == instr);
-}
-
-static bool
-cmp_func(const void *data1, const void *data2)
-{
- const struct util_dynarray *arr1 = data1;
- const struct util_dynarray *arr2 = data2;
-
- const nir_instr *instr1 = *(nir_instr **)util_dynarray_begin(arr1);
- const nir_instr *instr2 = *(nir_instr **)util_dynarray_begin(arr2);
-
- return instrs_equal(instr1, instr2);
-}
-
-static uint32_t
-hash_stack(const void *data)
-{
- const struct util_dynarray *stack = data;
- const nir_instr *first = *(nir_instr **)util_dynarray_begin(stack);
- return hash_instr(first);
-}
-
static struct set *
vec_instr_set_create(void)
{
- return _mesa_set_create(NULL, hash_stack, cmp_func);
+ return _mesa_set_create(NULL, hash_instr, instrs_equal);
}
static void
@@ -403,54 +338,22 @@ vec_instr_set_add_or_rewrite(struct nir_shader *nir, struct set *instr_set,
if (!instr_can_rewrite(instr))
return false;
- struct util_dynarray *new_stack = vec_instr_stack_create(instr_set);
- vec_instr_stack_push(nir, new_stack, instr, filter, data);
-
- struct set_entry *entry = _mesa_set_search(instr_set, new_stack);
-
+ struct set_entry *entry = _mesa_set_search(instr_set, instr);
if (entry) {
- ralloc_free(new_stack);
- struct util_dynarray *stack = (struct util_dynarray *) entry->key;
- return vec_instr_stack_push(nir, stack, instr, filter, data);
+ nir_instr *old_instr = (nir_instr *) entry->key;
+ _mesa_set_remove(instr_set, entry);
+ nir_instr *new_instr = instr_try_combine(nir, old_instr, instr,
+ filter, data);
+ if (new_instr) {
+ _mesa_set_add(instr_set, new_instr);
+ return true;
+ }
}
- _mesa_set_add(instr_set, new_stack);
+ _mesa_set_add(instr_set, instr);
return false;
}
-static void
-vec_instr_set_remove(struct nir_shader *nir, struct set *instr_set,
- nir_instr *instr, nir_opt_vectorize_cb filter, void *data)
-{
- if (!instr_can_rewrite(instr))
- return;
-
- /*
- * It's pretty unfortunate that we have to do this, but it's a side effect
- * of the hash set interfaces. The hash set assumes that we're only
- * interested in storing one equivalent element at a time, and if we try to
- * insert a duplicate element it will remove the original. We could hack up
- * the comparison function to "know" which input is an instruction we
- * passed in and which is an array that's part of the entry, but that
- * wouldn't work because we need to pass an array to _mesa_set_add() in
- * vec_instr_add_or_rewrite() above, and _mesa_set_add() will call our
- * comparison function as well.
- */
- struct util_dynarray *temp = vec_instr_stack_create(instr_set);
- vec_instr_stack_push(nir, temp, instr, filter, data);
- struct set_entry *entry = _mesa_set_search(instr_set, temp);
- ralloc_free(temp);
-
- if (entry) {
- struct util_dynarray *stack = (struct util_dynarray *) entry->key;
-
- if (util_dynarray_num_elements(stack, nir_instr *) > 1)
- vec_instr_stack_pop(stack, instr);
- else
- _mesa_set_remove(instr_set, entry);
- }
-}
-
static bool
vectorize_block(struct nir_shader *nir, nir_block *block,
struct set *instr_set,
@@ -468,8 +371,14 @@ vectorize_block(struct nir_shader *nir, nir_block *block,
progress |= vectorize_block(nir, child, instr_set, filter, data);
}
- nir_foreach_instr_reverse(instr, block)
- vec_instr_set_remove(nir, instr_set, instr, filter, data);
+ nir_foreach_instr_reverse(instr, block) {
+ if (instr->type != nir_instr_type_alu)
+ continue;
+
+ struct set_entry *entry = _mesa_set_search(instr_set, instr);
+ if (entry)
+ _mesa_set_remove(instr_set, entry);
+ }
return progress;
}
More information about the mesa-commit
mailing list