From 19c560da04d938d84b1fa5f2de2110aa2084d6c9 Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Mon, 28 Oct 2024 10:14:45 +0100 Subject: [PATCH] ir3: fix physical edges of predicated branches The algorithm for adding extra physical edges works by finding edges that jump over reconvergence points. Since predicated branches don't introduce reconvergence points, we wouldn't add a physical edge from the true block to the false block. However, this physical edge is still needed as control flow does fall though here. This patch fixes this by manually adding the physical edge so that we don't need to insert a reconvergence point for it. Signed-off-by: Job Noorman Fixes: 39088571f08 ("ir3: add support for predication") Part-of: --- src/freedreno/ir3/ir3_reconvergence.c | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/freedreno/ir3/ir3_reconvergence.c b/src/freedreno/ir3/ir3_reconvergence.c index d1d65f77653..03ab14815a2 100644 --- a/src/freedreno/ir3/ir3_reconvergence.c +++ b/src/freedreno/ir3/ir3_reconvergence.c @@ -154,6 +154,41 @@ ir3_calc_reconvergence(struct ir3_shader_variant *so) uinterval_tree_insert(&backward_edges, &edges[edge++].node); } + } else { + struct ir3_instruction *terminator = + ir3_block_get_terminator(block); + + /* We don't want to mark targets of predicated branches as + * reconvergence points below because they don't need the + * branchstack: + * |-- i --| + * | ... | + * | predt | + * |-------| + * succ0 / \ succ1 + * |-- i+1 --| |-- i+2 --| + * | tblock | | fblock | + * | predf | | jump | + * |---------| |---------| + * succ0 \ / succ0 + * |-- j --| + * | ... | + * |-------| + * Here, neither block i+2 nor block j need (jp). However, block i+1 + * still needs a physical edge to block i+2 (control flow will fall + * through here) but the code below won't add it unless block i+2 is + * a reconvergence point. Therefore, we add it manually here. + * + * Note: we are here because the current block has only one + * successor which means that, if there is a predicated terminator, + * block will be block i+1 in the diagram above. + */ + if (terminator && (terminator->opc == OPC_PREDT || + terminator->opc == OPC_PREDF)) { + struct ir3_block *next = + list_entry(block->node.next, struct ir3_block, node); + ir3_block_link_physical(block, next); + } } } }