From da1594f8bbef81929fae4caa7f208bcc9f65f484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Sch=C3=BCrmann?= Date: Wed, 21 Jan 2026 23:20:12 +0100 Subject: [PATCH] aco: introduce notion of block_kind_loop_latch A block annotated with block_kind_loop_latch denotes a block the re-entry point for a loop back-edge. It is emitted after the loop preheader and (potentially) before the loop header. Part-of: --- src/amd/compiler/aco_ir.h | 1 + src/amd/compiler/aco_print_ir.cpp | 4 +++- src/amd/compiler/instruction_selection/aco_isel_cfg.cpp | 9 ++++++--- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/amd/compiler/aco_ir.h b/src/amd/compiler/aco_ir.h index 9d7b44dac01..7dca48cb7cc 100644 --- a/src/amd/compiler/aco_ir.h +++ b/src/amd/compiler/aco_ir.h @@ -2145,6 +2145,7 @@ enum block_kind { block_kind_export_end = 1 << 13, block_kind_end_with_regs = 1 << 14, block_kind_contains_call = 1 << 15, + block_kind_loop_latch = 1 << 16, }; /* CFG */ diff --git a/src/amd/compiler/aco_print_ir.cpp b/src/amd/compiler/aco_print_ir.cpp index be7febbb93f..388dc490694 100644 --- a/src/amd/compiler/aco_print_ir.cpp +++ b/src/amd/compiler/aco_print_ir.cpp @@ -826,7 +826,7 @@ print_vopd_instr(enum amd_gfx_level gfx_level, const Instruction* instr, FILE* o } static void -print_block_kind(uint16_t kind, FILE* output) +print_block_kind(uint32_t kind, FILE* output) { if (kind & block_kind_uniform) fprintf(output, "uniform, "); @@ -836,6 +836,8 @@ print_block_kind(uint16_t kind, FILE* output) fprintf(output, "loop-preheader, "); if (kind & block_kind_loop_header) fprintf(output, "loop-header, "); + else if (kind & block_kind_loop_latch) + fprintf(output, "loop-latch, "); if (kind & block_kind_loop_exit) fprintf(output, "loop-exit, "); if (kind & block_kind_continue) diff --git a/src/amd/compiler/instruction_selection/aco_isel_cfg.cpp b/src/amd/compiler/instruction_selection/aco_isel_cfg.cpp index a2a323ceb0e..6da46a38317 100644 --- a/src/amd/compiler/instruction_selection/aco_isel_cfg.cpp +++ b/src/amd/compiler/instruction_selection/aco_isel_cfg.cpp @@ -152,24 +152,27 @@ end_loop(isel_context* ctx, loop_context* lc) * divergent control flow requires WQM. */ assert(!ctx->cf_info.exec.potentially_empty_discard); + Block& header = ctx->program->blocks[ctx->cf_info.parent_loop.header_idx]; /* Add the trivial continue. */ if (!ctx->cf_info.has_branch) { - unsigned loop_header_idx = ctx->cf_info.parent_loop.header_idx; Builder bld(ctx->program, ctx->block); ctx->block->kind |= (block_kind_continue | block_kind_uniform); if (!ctx->cf_info.has_divergent_branch) { append_logical_end(ctx); - add_edge(ctx->block->index, &ctx->program->blocks[loop_header_idx]); + add_edge(ctx->block->index, &header); } else { - add_linear_edge(ctx->block->index, &ctx->program->blocks[loop_header_idx]); + add_linear_edge(ctx->block->index, &header); } bld.reset(ctx->block); bld.branch(aco_opcode::p_branch); } + if (header.linear_preds.size() > 1) + header.kind |= block_kind_loop_latch; + /* emit loop successor block */ ctx->program->next_loop_depth--; ctx->block = ctx->program->insert_block(std::move(lc->loop_exit));