pan/bi: Use canonical flow control enum
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Fri, 2 Oct 2020 19:03:58 +0000 (15:03 -0400)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Sat, 10 Oct 2020 20:53:12 +0000 (16:53 -0400)
Merges multiple bits and adds some new combinations. The semantics are
the compiler are evidently wrong, we'll fix that next.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7081>

src/panfrost/bifrost/bi_pack.c
src/panfrost/bifrost/bi_print_common.c
src/panfrost/bifrost/bi_print_common.h
src/panfrost/bifrost/bifrost.h
src/panfrost/bifrost/disassemble.c

index 01c4a79..500566d 100644 (file)
@@ -45,8 +45,9 @@ bi_pack_header(bi_clause *clause, bi_clause *next_1, bi_clause *next_2, bool is_
         dependency_wait |= next_2 ? next_2->dependencies : 0;
 
         struct bifrost_header header = {
-                .back_to_back = clause->back_to_back,
-                .no_end_of_shader = (next_1 != NULL),
+                .flow_control =
+                        (next_1 == NULL) ? BIFROST_FLOW_END :
+                        (clause->back_to_back ? BIFROST_FLOW_NBTB : BIFROST_FLOW_NBTB_UNCONDITIONAL),
                 .terminate_discarded_threads = is_fragment,
                 .next_clause_prefetch = clause->next_clause_prefetch,
                 .staging_barrier = clause->staging_barrier,
index 5c645eb..e0f8b3f 100644 (file)
@@ -98,3 +98,19 @@ bi_interp_mode_name(enum bifrost_interp_mode mode)
         default: return ".unknown";
         }
 }
+
+const char *
+bi_flow_control_name(enum bifrost_flow mode)
+{
+        switch (mode) {
+        case BIFROST_FLOW_END: return "eos";
+        case BIFROST_FLOW_NBTB_PC: return "nbb br_pc";
+        case BIFROST_FLOW_NBTB_UNCONDITIONAL: return "nbb r_uncond";
+        case BIFROST_FLOW_NBTB: return "nbb";
+        case BIFROST_FLOW_BTB_UNCONDITIONAL: return "bb r_uncond";
+        case BIFROST_FLOW_BTB_NONE: return "bb";
+        case BIFROST_FLOW_WE_UNCONDITIONAL: return "we r_uncond";
+        case BIFROST_FLOW_WE: return "we";
+        default: return "XXX";
+        }
+}
index 55c0318..2c27ab3 100644 (file)
@@ -35,5 +35,6 @@ const char * bi_output_mod_name(enum bifrost_outmod mod);
 const char * bi_minmax_mode_name(enum bifrost_minmax_mode mod);
 const char * bi_round_mode_name(enum bifrost_roundmode mod);
 const char * bi_interp_mode_name(enum bifrost_interp_mode mode);
+const char * bi_flow_control_name(enum bifrost_flow mode);
 
 #endif
index 497dc3b..7638c5b 100644 (file)
@@ -67,6 +67,48 @@ enum bifrost_exceptions {
         BIFROST_EXCEPTIONS_PRECISE_SQRT = 3,
 };
 
+/* Describes clause flow control, with respect to control flow and branch
+ * reconvergence.
+ *
+ * Control flow may be considered back-to-back (execute clauses back-to-back),
+ * non-back-to-back (switch warps after clause before the next clause), write
+ * elision (back-to-back and elide register slot #3 write from the clause), or
+ * end of shader.
+ *
+ * Branch reconvergence may be disabled, enabled unconditionally, or enabled
+ * based on the program counter. A clause requires reconvergence if it has a
+ * successor that can be executed without first executing the clause itself.
+ * Separate iterations of a loop are treated separately here, so it is also the
+ * case for a loop exit where the iteration count is not warp-invariant.
+ *
+ */
+
+enum bifrost_flow {
+        /* End-of-shader */
+        BIFROST_FLOW_END = 0,
+
+        /* Non back-to-back, PC-encoded reconvergence */
+        BIFROST_FLOW_NBTB_PC = 1,
+
+        /* Non back-to-back, unconditional reconvergence */
+        BIFROST_FLOW_NBTB_UNCONDITIONAL = 2,
+
+        /* Non back-to-back, no reconvergence */
+        BIFROST_FLOW_NBTB = 3,
+
+        /* Back-to-back, unconditional reconvergence */
+        BIFROST_FLOW_BTB_UNCONDITIONAL = 4,
+
+        /* Back-to-back, no reconvergence */
+        BIFROST_FLOW_BTB_NONE = 5,
+
+        /* Write elision, unconditional reconvergence */
+        BIFROST_FLOW_WE_UNCONDITIONAL = 6,
+
+        /* Write elision, no reconvergence */
+        BIFROST_FLOW_WE = 7,
+};
+
 struct bifrost_header {
         /* Reserved */
         unsigned zero1 : 5;
@@ -84,11 +126,12 @@ struct bifrost_header {
         /* Floating-point excception handling mode */
         enum bifrost_exceptions float_exceptions : 2;
 
-        // true if the execution mask of the next clause is the same as the mask of
-        // the current clause.
-        unsigned back_to_back : 1;
-        unsigned no_end_of_shader: 1;
-        unsigned unk2 : 2;
+        /* Enum describing the flow control, which matters for handling
+         * divergence and reconvergence efficiently */
+        enum bifrost_flow flow_control : 3;
+
+        /* Reserved */
+        unsigned zero2 : 1;
 
         /* Terminate discarded threads, rather than continuing execution. Set
          * for fragment shaders for standard GL behaviour of DISCARD. */
index 3183d3a..5702e07 100644 (file)
@@ -89,12 +89,7 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose)
         if (header.staging_barrier)
                 fprintf(fp, "osrb ");
 
-        if (!header.no_end_of_shader)
-                fprintf(fp, "eos ");
-
-        if (!header.back_to_back) {
-                fprintf(fp, "nbb ");
-        }
+        fprintf(fp, "%s ", bi_flow_control_name(header.flow_control));
 
         if (header.suppress_inf)
                 fprintf(fp, "inf_suppress ");
@@ -109,6 +104,7 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose)
                 fprintf(fp, "ftz_au ");
 
         assert(!header.zero1);
+        assert(!header.zero2);
 
         if (header.float_exceptions == BIFROST_EXCEPTIONS_DISABLED)
                 fprintf(fp, "fpe_ts ");
@@ -120,9 +116,6 @@ static void dump_header(FILE *fp, struct bifrost_header header, bool verbose)
         if (header.message_type)
                 fprintf(fp, "%s ", bi_message_type_name(header.next_message_type));
 
-        if  (header.unk2)
-                fprintf(fp, "unk2 ");
-
         if (header.terminate_discarded_threads)
                 fprintf(fp, "td ");
 
@@ -663,7 +656,7 @@ static bool dump_clause(FILE *fp, uint32_t *words, unsigned *size, unsigned offs
         struct bifrost_header header;
         memcpy((char *) &header, (char *) &header_bits, sizeof(struct bifrost_header));
         dump_header(fp, header, verbose);
-        if (!header.no_end_of_shader)
+        if (header.flow_control == BIFROST_FLOW_END)
                 stopbit = true;
 
         fprintf(fp, "{\n");