From 46c734ff02b93a361b98f353eabf9c9f3ef26223 Mon Sep 17 00:00:00 2001 From: Rhys Perry Date: Thu, 21 Mar 2024 14:37:06 +0000 Subject: [PATCH] aco: ensure loop exits exist in NIR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This simplifies instruction selection and fixes the case where the loop ends with a continue instruction. Signed-off-by: Rhys Perry Reviewed-by: Daniel Schürmann Part-of: --- src/amd/compiler/aco_instruction_selection.cpp | 14 -------------- .../aco_instruction_selection_setup.cpp | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/amd/compiler/aco_instruction_selection.cpp b/src/amd/compiler/aco_instruction_selection.cpp index 592ca14b6d2..21a9906176e 100644 --- a/src/amd/compiler/aco_instruction_selection.cpp +++ b/src/amd/compiler/aco_instruction_selection.cpp @@ -10202,7 +10202,6 @@ end_loop(isel_context* ctx, loop_context* lc) ctx->cf_info.has_branch = false; ctx->program->next_loop_depth--; - // TODO: if the loop has not a single exit, we must add one °° /* emit loop successor block */ ctx->block = ctx->program->insert_block(std::move(lc->loop_exit)); append_logical_start(ctx->block); @@ -10459,19 +10458,6 @@ visit_loop(isel_context* ctx, nir_loop* loop) } } - /* NIR seems to allow this, and even though the loop exit has no predecessors, SSA defs from the - * loop header are live. Handle this without complicating the ACO IR by creating a dummy break. - */ - if (nir_cf_node_cf_tree_next(&loop->cf_node)->predecessors->entries == 0) { - Builder bld(ctx->program, ctx->block); - Temp cond = bld.copy(bld.def(s1, scc), Operand::zero()); - if_context ic; - begin_uniform_if_then(ctx, &ic, cond); - emit_loop_break(ctx); - begin_uniform_if_else(ctx, &ic); - end_uniform_if(ctx, &ic); - } - end_loop(ctx, &lc); } diff --git a/src/amd/compiler/aco_instruction_selection_setup.cpp b/src/amd/compiler/aco_instruction_selection_setup.cpp index 511902213bc..c8f1ecdd304 100644 --- a/src/amd/compiler/aco_instruction_selection_setup.cpp +++ b/src/amd/compiler/aco_instruction_selection_setup.cpp @@ -124,6 +124,24 @@ sanitize_cf_list(nir_function_impl* impl, struct exec_list* cf_list) nir_loop* loop = nir_cf_node_as_loop(cf_node); assert(!nir_loop_has_continue_construct(loop)); progress |= sanitize_cf_list(impl, &loop->body); + + /* NIR seems to allow this, and even though the loop exit has no predecessors, SSA defs from the + * loop header are live. Handle this without complicating the ACO IR by creating a dummy break. + */ + if (nir_cf_node_cf_tree_next(&loop->cf_node)->predecessors->entries == 0) { + nir_builder b = nir_builder_create(impl); + b.cursor = nir_after_block_before_jump(nir_loop_last_block(loop)); + + nir_def *cond = nir_imm_false(&b); + /* We don't use block divergence information, so just this is enough. */ + cond->divergent = false; + + nir_push_if(&b, cond); + nir_jump(&b, nir_jump_break); + nir_pop_if(&b, NULL); + + progress = true; + } break; } case nir_cf_node_function: unreachable("Invalid cf type");