Mesa (main): nir/dce: fix DCE of loops with a halt or return instruction in the pre-header

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Nov 29 22:58:14 UTC 2021


Module: Mesa
Branch: main
Commit: 2fe13aa2ad7367d83a19da2332d9ec55cb3a3a6f
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=2fe13aa2ad7367d83a19da2332d9ec55cb3a3a6f

Author: Rhys Perry <pendingchaos02 at gmail.com>
Date:   Fri Apr 16 13:18:33 2021 +0100

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 <pendingchaos02 at gmail.com>
Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
Reviewed-by: Jason Ekstrand <jason at jlekstrand.net>
Tested-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
Fixes: 71a985d80b1 ("nir/dce: perform DCE for unlooped instructions in a single pass")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10284>

---

 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.



More information about the mesa-commit mailing list