pan/bi: Handle loops when ingesting CFG
Not very useful without also handling breaks and continues, of course.
We use the strategy from v3d (vir_to_nir) instead of Midgard's, since
the latter is mildly insane. I mean, it passes deqp but...
Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4097>
diff --git a/src/panfrost/bifrost/bifrost_compile.c b/src/panfrost/bifrost/bifrost_compile.c
index 361c8fc..01f20c4 100644
--- a/src/panfrost/bifrost/bifrost_compile.c
+++ b/src/panfrost/bifrost/bifrost_compile.c
@@ -174,6 +174,36 @@
bi_block_add_successor(end_else_block, ctx->after_block); /* fallthrough */
}
+static void
+emit_loop(bi_context *ctx, nir_loop *nloop)
+{
+ /* Remember where we are */
+ bi_block *start_block = ctx->current_block;
+
+ bi_block *saved_break = ctx->break_block;
+ bi_block *saved_continue = ctx->continue_block;
+
+ ctx->continue_block = create_empty_block(ctx);
+ ctx->break_block = create_empty_block(ctx);
+ ctx->after_block = ctx->continue_block;
+
+ /* Emit the body itself */
+ emit_cf_list(ctx, &nloop->body);
+
+ /* Branch back to loop back */
+ bi_instruction *br_back = bi_emit_branch(ctx);
+ br_back->branch.target = ctx->continue_block;
+ bi_block_add_successor(start_block, ctx->continue_block);
+ bi_block_add_successor(ctx->current_block, ctx->continue_block);
+
+ ctx->after_block = ctx->break_block;
+
+ /* Pop off */
+ ctx->break_block = saved_break;
+ ctx->continue_block = saved_continue;
+ ++ctx->loop_count;
+}
+
static bi_block *
emit_cf_list(bi_context *ctx, struct exec_list *list)
{
@@ -194,11 +224,9 @@
emit_if(ctx, nir_cf_node_as_if(node));
break;
-#if 0
case nir_cf_node_loop:
emit_loop(ctx, nir_cf_node_as_loop(node));
break;
-#endif
default:
unreachable("Unknown control flow");