Mesa (master): nir/from_ssa: Respect and populate divergence information
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon Feb 1 08:28:55 UTC 2021
Module: Mesa
Branch: master
Commit: c7fc44f9ebbe93f7aefc010aea4e13e29d0d67fd
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=c7fc44f9ebbe93f7aefc010aea4e13e29d0d67fd
Author: Jason Ekstrand <jason at jlekstrand.net>
Date: Tue Oct 15 16:14:39 2019 -0500
nir/from_ssa: Respect and populate divergence information
Reviewed-by: Arcady Goldmints-Orlov <agoldmints at igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7726>
---
src/compiler/nir/nir.h | 12 ++++++++----
src/compiler/nir/nir_from_ssa.c | 41 +++++++++++++++++++++++++++++++++++------
2 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 5d8de704520..d70e91b980f 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -718,6 +718,12 @@ typedef struct nir_register {
/* The bit-size of each channel; must be one of 8, 16, 32, or 64 */
uint8_t bit_size;
+ /**
+ * True if this register may have different values in different SIMD
+ * invocations of the shader.
+ */
+ bool divergent;
+
/** generic register index. */
unsigned index;
@@ -967,8 +973,7 @@ nir_src_is_const(nir_src src)
static inline bool
nir_src_is_divergent(nir_src src)
{
- assert(src.is_ssa);
- return src.ssa->divergent;
+ return src.is_ssa ? src.ssa->divergent : src.reg.reg->divergent;
}
static inline unsigned
@@ -986,8 +991,7 @@ nir_dest_num_components(nir_dest dest)
static inline bool
nir_dest_is_divergent(nir_dest dest)
{
- assert(dest.is_ssa);
- return dest.ssa.divergent;
+ return dest.is_ssa ? dest.ssa.divergent : dest.reg.reg->divergent;
}
/* Are all components the same, ie. .xxxx */
diff --git a/src/compiler/nir/nir_from_ssa.c b/src/compiler/nir/nir_from_ssa.c
index fcaf156d218..3e98f317140 100644
--- a/src/compiler/nir/nir_from_ssa.c
+++ b/src/compiler/nir/nir_from_ssa.c
@@ -106,6 +106,7 @@ typedef struct {
typedef struct merge_set {
struct exec_list nodes;
unsigned size;
+ bool divergent;
nir_register *reg;
} merge_set;
@@ -144,6 +145,7 @@ get_merge_node(nir_ssa_def *def, struct from_ssa_state *state)
merge_set *set = ralloc(state->dead_ctx, merge_set);
exec_list_make_empty(&set->nodes);
set->size = 1;
+ set->divergent = def->divergent;
set->reg = NULL;
merge_node *node = ralloc(state->dead_ctx, merge_node);
@@ -186,6 +188,7 @@ merge_merge_sets(merge_set *a, merge_set *b)
a->size += b->size;
b->size = 0;
+ a->divergent |= b->divergent;
return a;
}
@@ -358,6 +361,7 @@ isolate_phi_nodes_block(nir_block *block, void *dead_ctx)
nir_ssa_dest_init(&pcopy->instr, &entry->dest,
phi->dest.ssa.num_components,
phi->dest.ssa.bit_size, src->src.ssa->name);
+ entry->dest.ssa.divergent = nir_src_is_divergent(src->src);
exec_list_push_tail(&pcopy->entries, &entry->node);
assert(src->src.is_ssa);
@@ -372,6 +376,7 @@ isolate_phi_nodes_block(nir_block *block, void *dead_ctx)
nir_ssa_dest_init(&block_pcopy->instr, &entry->dest,
phi->dest.ssa.num_components, phi->dest.ssa.bit_size,
phi->dest.ssa.name);
+ entry->dest.ssa.divergent = phi->dest.ssa.divergent;
exec_list_push_tail(&block_pcopy->entries, &entry->node);
nir_ssa_def_rewrite_uses(&phi->dest.ssa,
@@ -432,6 +437,12 @@ aggressive_coalesce_parallel_copy(nir_parallel_copy_instr *pcopy,
if (src_node->set == dest_node->set)
continue;
+ /* TODO: We can probably do better here but for now we should be safe if
+ * we just don't coalesce things with different divergence.
+ */
+ if (dest_node->set->divergent != src_node->set->divergent)
+ continue;
+
if (!merge_sets_interfere(src_node->set, dest_node->set))
merge_merge_sets(src_node->set, dest_node->set);
}
@@ -493,8 +504,10 @@ rewrite_ssa_def(nir_ssa_def *def, void *void_state)
* the things in the merge set should be the same so it doesn't
* matter which node's definition we use.
*/
- if (node->set->reg == NULL)
+ if (node->set->reg == NULL) {
node->set->reg = create_reg_for_ssa_def(def, state->builder.impl);
+ node->set->reg->divergent = node->set->divergent;
+ }
reg = node->set->reg;
} else {
@@ -562,6 +575,8 @@ emit_copy(nir_builder *b, nir_src src, nir_src dest_src)
dest_src.reg.indirect == NULL &&
dest_src.reg.base_offset == 0);
+ assert(!nir_src_is_divergent(src) || nir_src_is_divergent(dest_src));
+
if (src.is_ssa)
assert(src.ssa->num_components >= dest_src.reg.reg->num_components);
else
@@ -699,13 +714,26 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy,
/* b has been filled, mark it as not needing to be copied */
pred[b] = -1;
- /* If a needs to be filled... */
- if (pred[a] != -1) {
- /* If any other copies want a they can find it at b */
+ /* The next bit only applies if the source and destination have the
+ * same divergence. If they differ (it must be convergent ->
+ * divergent), then we can't guarantee we won't need the convergent
+ * version of again.
+ */
+ if (nir_src_is_divergent(values[a]) ==
+ nir_src_is_divergent(values[b])) {
+ /* If any other copies want a they can find it at b but only if the
+ * two have the same divergence.
+ */
loc[a] = b;
- /* It's ready for copying now */
- ready[++ready_idx] = a;
+ /* If a needs to be filled... */
+ if (pred[a] != -1) {
+ /* If any other copies want a they can find it at b */
+ loc[a] = b;
+
+ /* It's ready for copying now */
+ ready[++ready_idx] = a;
+ }
}
}
int b = to_do[to_do_idx--];
@@ -732,6 +760,7 @@ resolve_parallel_copy(nir_parallel_copy_instr *pcopy,
reg->num_components = values[b].reg.reg->num_components;
reg->bit_size = values[b].reg.reg->bit_size;
}
+ reg->divergent = nir_src_is_divergent(values[b]);
values[num_vals].is_ssa = false;
values[num_vals].reg.reg = reg;
More information about the mesa-commit
mailing list