From 2fe13aa2ad7367d83a19da2332d9ec55cb3a3a6f Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Fri, 16 Apr 2021 13:18:33 +0100 Subject: [PATCH] nir/dce: fix DCE of loops with a halt or return instruction in the pre-header If there is a halt or return instruction right before a loop with a single continue, we would have taken the fast path intended for loops without continues. Signed-off-by: Rhys Perry Reviewed-by: Ian Romanick Reviewed-by: Jason Ekstrand Tested-by: Lionel Landwerlin Fixes: 71a985d80b1 ("nir/dce: perform DCE for unlooped instructions in a single pass") Part-of: --- src/compiler/nir/nir_opt_dce.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/compiler/nir/nir_opt_dce.c b/src/compiler/nir/nir_opt_dce.c index 532ad4ff95d..49e7ac015c2 100644 --- a/src/compiler/nir/nir_opt_dce.c +++ b/src/compiler/nir/nir_opt_dce.c @@ -166,18 +166,21 @@ dce_cf_list(struct exec_list *cf_list, BITSET_WORD *defs_live, case nir_cf_node_loop: { nir_loop *loop = nir_cf_node_as_loop(cf_node); + struct loop_state inner_state; + inner_state.preheader = nir_cf_node_as_block(nir_cf_node_prev(cf_node)); + inner_state.header_phis_changed = false; + /* Fast path if the loop has no continues: we can remove instructions * as we mark the others live. */ - if (nir_loop_first_block(loop)->predecessors->entries == 1) { + struct set *predecessors = nir_loop_first_block(loop)->predecessors; + if (predecessors->entries == 1 && + _mesa_set_next_entry(predecessors, NULL)->key == inner_state.preheader) { progress |= dce_cf_list(&loop->body, defs_live, parent_loop); break; } /* Mark instructions as live until there is no more progress. */ - struct loop_state inner_state; - inner_state.preheader = nir_cf_node_as_block(nir_cf_node_prev(cf_node)); - inner_state.header_phis_changed = false; do { /* dce_cf_list() resets inner_state.header_phis_changed itself, so * it doesn't have to be done here.