agx: Augment if/else/while_cmp with a target
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Wed, 30 Aug 2023 19:43:51 +0000 (15:43 -0400)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sun, 1 Oct 2023 16:32:11 +0000 (12:32 -0400)
Add an optional pointer to a target block for these instructions. This does NOT
act like a logical branch, and does NOT get added to the logical control flow.
It is ignored wholesale until after RA, when physical edges may be inserted by a
pass we add later in this series.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
src/asahi/compiler/agx_builder.h.py
src/asahi/compiler/agx_compile.c
src/asahi/compiler/agx_compiler.h
src/asahi/compiler/agx_lower_pseudo.c
src/asahi/compiler/agx_opcodes.py
src/asahi/compiler/agx_opt_break_if.c
src/asahi/compiler/test/test-optimizer.cpp

index 4594d5c..4ae5f5a 100644 (file)
@@ -131,7 +131,7 @@ agx_fmov_to(agx_builder *b, agx_index dst0, agx_index src0)
 static inline agx_instr *
 agx_push_exec(agx_builder *b, unsigned n)
 {
-   return agx_if_fcmp(b, agx_zero(), agx_zero(), n, AGX_FCOND_EQ, false);
+   return agx_if_fcmp(b, agx_zero(), agx_zero(), n, AGX_FCOND_EQ, false, NULL);
 }
 
 static inline agx_instr *
index 6939815..ff255ad 100644 (file)
@@ -1788,7 +1788,7 @@ agx_emit_jump(agx_builder *b, nir_jump_instr *instr)
       agx_block_add_successor(ctx->current_block, ctx->break_block);
    }
 
-   agx_break(b, nestings);
+   agx_break(b, nestings, ctx->break_block);
    ctx->current_block->unconditional_jumps = true;
 }
 
@@ -1941,7 +1941,8 @@ emit_if(agx_context *ctx, nir_if *nif)
    agx_builder _b = agx_init_builder(ctx, agx_after_block(first_block));
    agx_index cond = agx_src_index(&nif->condition);
 
-   agx_if_icmp(&_b, cond, agx_zero(), 1, AGX_ICOND_UEQ, true);
+   agx_instr *if_ = agx_if_icmp(&_b, cond, agx_zero(), 1, AGX_ICOND_UEQ, true,
+                                NULL /* filled in later */);
    ctx->loop_nesting++;
    ctx->total_nesting++;
 
@@ -1954,11 +1955,16 @@ emit_if(agx_context *ctx, nir_if *nif)
    agx_block *else_block = emit_cf_list(ctx, &nif->else_list);
    agx_block *end_else = ctx->current_block;
 
+   /* If the "if" fails, we fallthrough to the else */
+   if_->target = else_block;
+
    /* Insert an else instruction at the beginning of the else block. We use
     * "else_fcmp 0.0, 0.0, eq" as unconditional else, matching the blob.
+    *
+    * If it fails, we fall through to the logical end of the last else block.
     */
    _b.cursor = agx_before_block(else_block);
-   agx_else_fcmp(&_b, agx_zero(), agx_zero(), 1, AGX_FCOND_EQ, false);
+   agx_else_fcmp(&_b, agx_zero(), agx_zero(), 1, AGX_FCOND_EQ, false, end_else);
 
    ctx->after_block = agx_create_block(ctx);
 
@@ -2019,8 +2025,11 @@ emit_loop(agx_context *ctx, nir_loop *nloop)
     */
    _b.cursor = agx_after_block(ctx->current_block);
 
-   if (ctx->loop_continues)
-      agx_while_icmp(&_b, agx_zero(), agx_zero(), 2, AGX_ICOND_UEQ, false);
+   if (ctx->loop_continues) {
+      agx_while_icmp(
+         &_b, agx_zero(), agx_zero(), 2, AGX_ICOND_UEQ, false,
+         NULL /* no semantic target, used purely for side effects */);
+   }
 
    agx_jmp_exec_any(&_b, start_block);
    agx_pop_exec(&_b, ctx->loop_continues ? 2 : 1);
index 072d7c4..b430081 100644 (file)
@@ -275,6 +275,12 @@ typedef struct {
    uint8_t nr_dests;
    uint8_t nr_srcs;
 
+   /* TODO: More efficient */
+   union {
+      enum agx_icond icond;
+      enum agx_fcond fcond;
+   };
+
    union {
       uint64_t imm;
       uint32_t writeout;
@@ -285,8 +291,6 @@ typedef struct {
       uint16_t pixel_offset;
       uint16_t zs;
       enum agx_sr sr;
-      enum agx_icond icond;
-      enum agx_fcond fcond;
       enum agx_round round;
       enum agx_atomic_opc atomic_opc;
       enum agx_lod_mode lod_mode;
index 093f360..02b9585 100644 (file)
@@ -14,10 +14,10 @@ while_for_break_if(agx_builder *b, agx_instr *I)
 {
    if (I->op == AGX_OPCODE_BREAK_IF_FCMP) {
       return agx_while_fcmp(b, I->src[0], I->src[1], I->nest, I->fcond,
-                            !I->invert_cond);
+                            !I->invert_cond, NULL);
    } else {
       return agx_while_icmp(b, I->src[0], I->src[1], I->nest, I->icond,
-                            !I->invert_cond);
+                            !I->invert_cond, NULL);
    }
 }
 
index 443853e..b0b5620 100644 (file)
@@ -350,7 +350,7 @@ for is_float in [False, True]:
       name = "{}_{}cmp".format(cf, "f" if is_float else "i")
       exact = 0x42 | (0x0 if is_float else 0x10) | (cf_op << 9)
       mask = 0x7F | (0x3 << 9) | mod_mask | (0x3 << 44)
-      imms = [NEST, FCOND if is_float else ICOND, INVERT_COND]
+      imms = [NEST, FCOND if is_float else ICOND, INVERT_COND, TARGET]
 
       op(name, (exact, mask, 6, _), dests = 0, srcs = 2, can_eliminate = False,
             imms = imms, is_float = is_float,
@@ -426,10 +426,10 @@ op("preload", _, srcs = 1, schedule_class = "preload")
 
 # Pseudo-instructions to set the nesting counter. Lowers to r0l writes after RA.
 op("begin_cf", _, dests = 0, can_eliminate = False)
-op("break", _, dests = 0, imms = [NEST], can_eliminate = False,
+op("break", _, dests = 0, imms = [NEST, TARGET], can_eliminate = False,
    schedule_class = "invalid")
 
 for (name, is_float) in [("break_if_icmp", False), ("break_if_fcmp", True)]:
     op(name, _, dests = 0, srcs = 2,
-       imms = [NEST, INVERT_COND, FCOND if is_float else ICOND],
+       imms = [NEST, INVERT_COND, FCOND if is_float else ICOND, TARGET],
        can_eliminate = False, schedule_class = "invalid")
index 473af81..bcc0dc8 100644 (file)
@@ -61,10 +61,10 @@ match_block(agx_context *ctx, agx_block *block)
 
    if (if_->op == AGX_OPCODE_IF_FCMP) {
       agx_break_if_fcmp(&b, if_->src[0], if_->src[1], new_nest,
-                        if_->invert_cond, if_->fcond);
+                        if_->invert_cond, if_->fcond, break_->target);
    } else {
       agx_break_if_icmp(&b, if_->src[0], if_->src[1], new_nest,
-                        if_->invert_cond, if_->icond);
+                        if_->invert_cond, if_->icond, break_->target);
    }
 
    agx_remove_instruction(if_);
index bc0d84e..47fc4c8 100644 (file)
@@ -203,16 +203,16 @@ TEST_F(Optimizer, NoConversionsOn16BitALU)
 TEST_F(Optimizer, IfCondition)
 {
    CASE_NO_RETURN(agx_if_icmp(b, agx_icmp(b, wx, wy, AGX_ICOND_UEQ, true),
-                              agx_zero(), 1, AGX_ICOND_UEQ, true),
-                  agx_if_icmp(b, wx, wy, 1, AGX_ICOND_UEQ, true));
+                              agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
+                  agx_if_icmp(b, wx, wy, 1, AGX_ICOND_UEQ, true, NULL));
 
    CASE_NO_RETURN(agx_if_icmp(b, agx_fcmp(b, wx, wy, AGX_FCOND_EQ, true),
-                              agx_zero(), 1, AGX_ICOND_UEQ, true),
-                  agx_if_fcmp(b, wx, wy, 1, AGX_FCOND_EQ, true));
+                              agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
+                  agx_if_fcmp(b, wx, wy, 1, AGX_FCOND_EQ, true, NULL));
 
    CASE_NO_RETURN(agx_if_icmp(b, agx_fcmp(b, hx, hy, AGX_FCOND_LT, false),
-                              agx_zero(), 1, AGX_ICOND_UEQ, true),
-                  agx_if_fcmp(b, hx, hy, 1, AGX_FCOND_LT, false));
+                              agx_zero(), 1, AGX_ICOND_UEQ, true, NULL),
+                  agx_if_fcmp(b, hx, hy, 1, AGX_FCOND_LT, false, NULL));
 }
 
 TEST_F(Optimizer, SelectCondition)