diff --git a/src/compiler/nir/nir_opt_dead_cf.c b/src/compiler/nir/nir_opt_dead_cf.c index 33f3565c564..bf86ba280e3 100644 --- a/src/compiler/nir/nir_opt_dead_cf.c +++ b/src/compiler/nir/nir_opt_dead_cf.c @@ -27,6 +27,7 @@ #include "nir.h" #include "nir_control_flow.h" +#include "nir_loop_analyze.h" /* * This file implements an optimization that deletes statically @@ -173,6 +174,42 @@ def_only_used_in_cf_node(nir_ssa_def *def, void *_node) return true; } +static bool +find_loop_terminators(struct exec_list *list) +{ + foreach_list_typed(nir_cf_node, cur, node, list) { + switch (cur->type) { + case nir_cf_node_block: { + nir_block *block = nir_cf_node_as_block(cur); + if (nir_block_ends_in_break(block)) + return true; + + break; + } + case nir_cf_node_if: { + nir_if *if_stmt = nir_cf_node_as_if(cur); + if (find_loop_terminators(&if_stmt->then_list)) + return true; + + if (find_loop_terminators(&if_stmt->else_list)) + return true; + + break; + } + case nir_cf_node_loop: { + nir_loop *loop = nir_cf_node_as_loop(cur); + if (find_loop_terminators(&loop->body)) + return true; + + break; + } + default: + unreachable("unknown cf node type"); + } + } + return false; +} + /* * Test if a loop node is dead. Such nodes are dead if: * @@ -206,6 +243,10 @@ node_is_dead(nir_cf_node *node) nir_function_impl *impl = nir_cf_node_get_function(node); nir_metadata_require(impl, nir_metadata_block_index); + bool interruptible = true; + if(node->type == nir_cf_node_loop) + interruptible = find_loop_terminators(&nir_cf_node_as_loop(node)->body); + nir_foreach_block_in_cf_node(block, node) { bool inside_loop = node->type == nir_cf_node_loop; for (nir_cf_node *n = &block->cf_node; @@ -236,7 +277,8 @@ node_is_dead(nir_cf_node *node) return false; } - if (!nir_foreach_ssa_def(instr, def_only_used_in_cf_node, node)) + if (!nir_foreach_ssa_def(instr, def_only_used_in_cf_node, node) && + interruptible) return false; } }