nir/cf: have nir_remove_after_cf_node remove phis at the start too

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Backport-to: 25.1
Reviewed-by: Georg Lehmann <dadschoorse@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35975>
(cherry picked from commit f45026751f)
This commit is contained in:
Rhys Perry 2025-07-07 14:47:22 +01:00 committed by Eric Engestrom
parent a48b57c2dc
commit 9ab1e75853
4 changed files with 71 additions and 12 deletions

View file

@ -3204,7 +3204,7 @@
"description": "nir/cf: have nir_remove_after_cf_node remove phis at the start too",
"nominated": true,
"nomination_type": 4,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -861,6 +861,28 @@ nir_cf_delete(nir_cf_list *cf_list)
}
}
void
nir_remove_after_cf_node(nir_cf_node *node)
{
nir_cf_node *end = node;
while (!nir_cf_node_is_last(end))
end = nir_cf_node_next(end);
nir_cursor begin = nir_after_cf_node(node);
if (begin.option == nir_cursor_before_block) {
/* nir_cf_extract() would ignore these phis */
nir_function_impl *impl = nir_cf_node_get_function(node);
nir_foreach_phi_safe(phi, begin.block) {
replace_ssa_def_uses(&phi->def, impl);
nir_instr_remove_v(&phi->instr);
}
}
nir_cf_list list;
nir_cf_extract(&list, begin, nir_after_cf_node(end));
nir_cf_delete(&list);
}
struct block_index {
nir_block *block;
uint32_t index;

View file

@ -171,17 +171,8 @@ nir_cf_node_remove(nir_cf_node *node)
nir_cf_delete(&list);
}
static inline void
nir_remove_after_cf_node(nir_cf_node *node)
{
nir_cf_node *end = node;
while (!nir_cf_node_is_last(end))
end = nir_cf_node_next(end);
nir_cf_list list;
nir_cf_extract(&list, nir_after_cf_node(node), nir_after_cf_node(end));
nir_cf_delete(&list);
}
/** removes instructions after a control flow node, also removing any phis immediately after it */
void nir_remove_after_cf_node(nir_cf_node *node);
/** inserts undef phi sources from predcessor into phis of the block */
void nir_insert_phi_undef(nir_block *block, nir_block *pred);

View file

@ -137,3 +137,49 @@ TEST_F(nir_opt_dead_cf_test, jump_before_constant_if)
nir_validate_shader(b->shader, NULL);
}
TEST_F(nir_opt_dead_cf_test, unreachable_phi)
{
/*
* Test that nir_opt_dead_cf/nir_remove_after_cf_node removes phis at the start of dead code.
*
* block b0: // preds:
* 32 %0 = deref_var &cond (shader_in bool)
* 1 %1 = @load_deref (%0) (access=none)
* // succs: b1 b2
* if %1 {
* block b1:// preds: b0
* return
* // succs: b4
* } else {
* block b2:// preds: b0
* return
* // succs: b4
* }
* block b3: // preds:
* 32 %2 = phi
* 32 %3 = deref_var &out (shader_out int)
* @store_deref (%3, %2) (wrmask=x, access=none)
* // succs: b4
* block b4:
*/
nir_variable *cond = nir_variable_create(b->shader, nir_var_shader_in, glsl_bool_type(), "cond");
nir_variable *var = nir_variable_create(b->shader, nir_var_shader_out, glsl_int_type(), "out");
nir_push_if(b, nir_load_var(b, cond));
nir_jump(b, nir_jump_return);
nir_push_else(b, NULL);
nir_jump(b, nir_jump_return);
nir_pop_if(b, NULL);
nir_phi_instr *phi = nir_phi_instr_create(b->shader);
nir_def_init(&phi->instr, &phi->def, 1, 32);
nir_builder_instr_insert(b, &phi->instr);
nir_store_var(b, var, &phi->def, 0x1);
ASSERT_TRUE(nir_opt_dead_cf(b->shader));
nir_validate_shader(b->shader, NULL);
ASSERT_TRUE(exec_list_is_empty(&nir_impl_last_block(b->impl)->instr_list));
ASSERT_FALSE(nir_opt_dead_cf(b->shader));
}