mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 05:08:08 +02:00
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:
parent
7050896be0
commit
0f2bf55c7e
1 changed files with 23 additions and 14 deletions
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue