aco/isel: remove loop nest information from exec_info

Since we never enter loops with an empty exec mask, and the
control flow is structured, we don't need to consider the
loop nest depth.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33206>
This commit is contained in:
Daniel Schürmann 2025-01-24 11:15:51 +01:00 committed by Marge Bot
parent a77258346c
commit 583c3586fe
2 changed files with 16 additions and 44 deletions

View file

@ -9744,24 +9744,11 @@ update_exec_info(isel_context* ctx)
if (!ctx->block->loop_nest_depth && !ctx->cf_info.parent_if.is_divergent)
ctx->cf_info.exec.potentially_empty_discard = false;
ctx->cf_info.exec.potentially_empty_break &=
ctx->block->loop_nest_depth >= ctx->cf_info.exec.potentially_empty_break_depth;
ctx->cf_info.exec.potentially_empty_continue &=
ctx->block->loop_nest_depth >= ctx->cf_info.exec.potentially_empty_continue_depth;
if (ctx->block->loop_nest_depth == ctx->cf_info.exec.potentially_empty_break_depth &&
!ctx->cf_info.parent_if.is_divergent && !ctx->cf_info.parent_loop.has_divergent_continue) {
if (!ctx->cf_info.parent_if.is_divergent && !ctx->cf_info.parent_loop.has_divergent_continue)
ctx->cf_info.exec.potentially_empty_break = false;
}
if (ctx->block->loop_nest_depth == ctx->cf_info.exec.potentially_empty_continue_depth &&
!ctx->cf_info.parent_if.is_divergent) {
ctx->cf_info.exec.potentially_empty_continue = false;
}
if (!ctx->cf_info.exec.potentially_empty_break)
ctx->cf_info.exec.potentially_empty_break_depth = UINT16_MAX;
if (!ctx->cf_info.exec.potentially_empty_continue)
ctx->cf_info.exec.potentially_empty_continue_depth = UINT16_MAX;
if (!ctx->cf_info.parent_if.is_divergent)
ctx->cf_info.exec.potentially_empty_continue = false;
}
void
@ -9777,11 +9764,7 @@ end_loop(isel_context* ctx, loop_context* lc)
/* No need to check exec.potentially_empty_break/continue originating inside the loop. In the
* only case where it's possible at this point (divergent break after divergent continue), we
* should continue anyway. */
if (ctx->cf_info.exec.potentially_empty_discard ||
(ctx->cf_info.exec.potentially_empty_break &&
ctx->cf_info.exec.potentially_empty_break_depth < ctx->block->loop_nest_depth) ||
(ctx->cf_info.exec.potentially_empty_continue &&
ctx->cf_info.exec.potentially_empty_continue_depth < ctx->block->loop_nest_depth)) {
if (ctx->cf_info.exec.potentially_empty_discard) {
/* Discards can result in code running with an empty exec mask.
* This would result in divergent breaks not ever being taken. As a
* workaround, break the loop when the loop mask is empty instead of
@ -9822,16 +9805,15 @@ end_loop(isel_context* ctx, loop_context* lc)
bld.branch(aco_opcode::p_branch);
}
ctx->cf_info.has_branch = false;
ctx->cf_info.has_divergent_branch = false;
ctx->program->next_loop_depth--;
/* emit loop successor block */
ctx->program->next_loop_depth--;
ctx->block = ctx->program->insert_block(std::move(lc->loop_exit));
append_logical_start(ctx->block);
ctx->cf_info.parent_loop = lc->cf_info_old.parent_loop;
ctx->cf_info.parent_if = lc->cf_info_old.parent_if;
/* Propagate information about discards and restore previous CF info. */
lc->cf_info_old.exec.potentially_empty_discard |= ctx->cf_info.exec.potentially_empty_discard;
lc->cf_info_old.had_divergent_discard |= ctx->cf_info.had_divergent_discard;
ctx->cf_info = lc->cf_info_old;
update_exec_info(ctx);
}
@ -9859,10 +9841,8 @@ emit_loop_jump(isel_context* ctx, bool is_break)
}
ctx->cf_info.has_divergent_branch = true;
if (!ctx->cf_info.exec.potentially_empty_break) {
if (!ctx->cf_info.exec.potentially_empty_break)
ctx->cf_info.exec.potentially_empty_break = true;
ctx->cf_info.exec.potentially_empty_break_depth = ctx->block->loop_nest_depth;
}
} else {
logical_target = &ctx->program->blocks[ctx->cf_info.parent_loop.header_idx];
add_logical_edge(idx, logical_target);
@ -9888,10 +9868,8 @@ emit_loop_jump(isel_context* ctx, bool is_break)
we must ensure that they are handled correctly */
ctx->cf_info.parent_loop.has_divergent_continue = true;
if (!ctx->cf_info.exec.potentially_empty_continue) {
if (!ctx->cf_info.exec.potentially_empty_continue)
ctx->cf_info.exec.potentially_empty_continue = true;
ctx->cf_info.exec.potentially_empty_continue_depth = ctx->block->loop_nest_depth;
}
}
}

View file

@ -38,24 +38,18 @@ struct shader_io_state {
struct exec_info {
/* Set to false when loop_nest_depth==0 && parent_if.is_divergent==false */
bool potentially_empty_discard = false;
uint16_t potentially_empty_break_depth = UINT16_MAX;
/* Set to false when loop_nest_depth==exec_potentially_empty_break_depth,
* parent_if.is_divergent==false and parent_loop.has_divergent_continue==false. Also set to
* false if loop_nest_depth<exec_potentially_empty_break_depth. */
/* Set to false when leaving the loop, or if parent_if.is_divergent==false and
* parent_loop.has_divergent_continue==false. */
bool potentially_empty_break = false;
uint16_t potentially_empty_continue_depth = UINT16_MAX;
/* Set to false when loop_nest_depth==exec_potentially_empty_break_depth
* and parent_if.is_divergent==false. */
/* Set to false when leaving the loop, or if parent_if.is_divergent==false. */
bool potentially_empty_continue = false;
void combine(struct exec_info& other)
{
potentially_empty_discard |= other.potentially_empty_discard;
potentially_empty_break_depth =
std::min(potentially_empty_break_depth, other.potentially_empty_break_depth);
potentially_empty_break |= other.potentially_empty_break;
potentially_empty_continue_depth =
std::min(potentially_empty_continue_depth, other.potentially_empty_continue_depth);
potentially_empty_continue |= other.potentially_empty_continue;
}