nir/lcssa: fix nondeterminism in predecessor iteration

set_foreach()'s order on a list of nir_block * isn't deterministic, so we
need to sort the predecessor list.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3364>
This commit is contained in:
Rhys Perry 2020-01-13 14:32:18 +00:00 committed by Marge Bot
parent 7050896be0
commit 0f2bf55c7e

View file

@ -45,6 +45,8 @@ typedef struct {
/* The loop we store information for */
nir_loop *loop;
nir_block *block_after_loop;
nir_block **exit_blocks;
/* Whether to skip loop invariant variables */
bool skip_invariants;
@ -201,12 +203,9 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
return true;
}
nir_block *block_after_loop =
nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
nir_foreach_use(use, def) {
if (use->parent_instr->type == nir_instr_type_phi &&
use->parent_instr->block == block_after_loop) {
use->parent_instr->block == state->block_after_loop) {
continue;
}
@ -233,15 +232,16 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
/* Create a phi node with as many sources pointing to the same ssa_def as
* the block has predecessors.
*/
set_foreach(block_after_loop->predecessors, entry) {
uint32_t num_exits = state->block_after_loop->predecessors->entries;
for (uint32_t i = 0; i < num_exits; i++) {
nir_phi_src *phi_src = ralloc(phi, nir_phi_src);
phi_src->src = nir_src_for_ssa(def);
phi_src->pred = (nir_block *) entry->key;
phi_src->pred = state->exit_blocks[i];
exec_list_push_tail(&phi->srcs, &phi_src->node);
}
nir_instr_insert_before_block(block_after_loop, &phi->instr);
nir_instr_insert_before_block(state->block_after_loop, &phi->instr);
nir_ssa_def *dest = &phi->dest.ssa;
/* deref instructions need a cast after the phi */
@ -258,7 +258,7 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
nir_ssa_dest_init(&cast->instr, &cast->dest,
phi->dest.ssa.num_components,
phi->dest.ssa.bit_size, NULL);
nir_instr_insert(nir_after_phis(block_after_loop), &cast->instr);
nir_instr_insert(nir_after_phis(state->block_after_loop), &cast->instr);
dest = &cast->dest.ssa;
}
@ -267,7 +267,7 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
*/
nir_foreach_use_safe(use, def) {
if (use->parent_instr->type == nir_instr_type_phi &&
block_after_loop == use->parent_instr->block) {
state->block_after_loop == use->parent_instr->block) {
continue;
}
@ -286,6 +286,17 @@ convert_loop_exit_for_ssa(nir_ssa_def *def, void *void_state)
return true;
}
static void
setup_loop_state(lcssa_state *state, nir_loop *loop)
{
state->loop = loop;
state->block_after_loop =
nir_cf_node_as_block(nir_cf_node_next(&loop->cf_node));
ralloc_free(state->exit_blocks);
state->exit_blocks = nir_block_get_predecessors_sorted(state->block_after_loop, state);
}
static void
convert_to_lcssa(nir_cf_node *cf_node, lcssa_state *state)
{
@ -313,7 +324,7 @@ convert_to_lcssa(nir_cf_node *cf_node, lcssa_state *state)
foreach_list_typed(nir_cf_node, nested_node, node, &loop->body)
convert_to_lcssa(nested_node, state);
state->loop = loop;
setup_loop_state(state, loop);
/* mark loop-invariant instructions */
if (state->skip_invariants) {
@ -346,9 +357,7 @@ convert_to_lcssa(nir_cf_node *cf_node, lcssa_state *state)
end:
/* For outer loops, the LCSSA-phi should be considered not invariant */
if (state->skip_invariants) {
nir_block *block_after_loop =
nir_cf_node_as_block(nir_cf_node_next(&state->loop->cf_node));
nir_foreach_instr(instr, block_after_loop) {
nir_foreach_instr(instr, state->block_after_loop) {
if (instr->type == nir_instr_type_phi)
instr->pass_flags = not_invariant;
else
@ -370,7 +379,7 @@ nir_convert_loop_to_lcssa(nir_loop *loop)
nir_metadata_require(impl, nir_metadata_block_index);
lcssa_state *state = rzalloc(NULL, lcssa_state);
state->loop = loop;
setup_loop_state(state, loop);
state->shader = impl->function->shader;
state->skip_invariants = false;
state->skip_bool_invariants = false;