pan/midgard: Imply next tags
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Wed, 12 Feb 2020 02:37:18 +0000 (21:37 -0500)
committerAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Sun, 16 Feb 2020 14:16:47 +0000 (09:16 -0500)
As long as we can disambiguate a few edge cases, we can imply next tags
entirely which cleans up the disassembly a fair bit (though not as much
as implying tags entirely would -- we'll get there!)

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3835>

src/panfrost/midgard/disassemble.c

index adbe1c7c3ff8cef430a358e91ae0b78a16389dce..34b36af713420c8e0740468ec62849a5f233e1f8 100644 (file)
@@ -1542,7 +1542,7 @@ disassemble_midgard(FILE *fp, uint8_t *code, size_t size, unsigned gpu_id, gl_sh
         while (i < num_words) {
                 unsigned tag = words[i] & 0xF;
                 unsigned next_tag = (words[i] >> 4) & 0xF;
-                fprintf(fp, "\t%X -> %X\n", tag, next_tag);
+                fprintf(fp, "\t%X\n", tag);
                 unsigned num_quad_words = midgard_tag_props[tag].size;
 
                 if (midg_tags[i] && midg_tags[i] != tag) {
@@ -1553,7 +1553,27 @@ disassemble_midgard(FILE *fp, uint8_t *code, size_t size, unsigned gpu_id, gl_sh
 
                 midg_tags[i] = tag;
 
-                /* Check the tag */
+                /* Check the tag. The idea is to ensure that next_tag is
+                 * *always* recoverable from the disassembly, such that we may
+                 * safely omit printing next_tag. To show this, we first
+                 * consider that next tags are semantically off-byone -- we end
+                 * up parsing tag n during step n+1. So, we ensure after we're
+                 * done disassembling the next tag of the final bundle is BREAK
+                 * and warn otherwise. We also ensure that the next tag is
+                 * never INVALID. Beyond that, since the last tag is checked
+                 * outside the loop, we can check one tag prior. If equal to
+                 * the current tag (which is unique), we're done. Otherwise, we
+                 * print if that tag was > TAG_BREAK, which implies the tag was
+                 * not TAG_BREAK or TAG_INVALID. But we already checked for
+                 * TAG_INVALID, so it's just if the last tag was TAG_BREAK that
+                 * we're silent. So we throw in a print for break-next on at
+                 * the end of the bundle (if it's not the final bundle, which
+                 * we already check for above), disambiguating this case as
+                 * well.  Hence in all cases we are unambiguous, QED. */
+
+                if (next_tag == TAG_INVALID)
+                        fprintf(fp, "\t/* XXX: invalid next tag */\n");
+
                 if (last_next_tag > TAG_BREAK && last_next_tag != tag) {
                         fprintf(fp, "\t/* XXX: TAG ERROR sequence, got %s expexted %s */\n",
                                         midgard_tag_props[tag].name,
@@ -1594,25 +1614,36 @@ disassemble_midgard(FILE *fp, uint8_t *code, size_t size, unsigned gpu_id, gl_sh
                         break;
                 }
 
-                if (next_tag == 1)
-                        fprintf(fp, "\n");
-
                 /* We are parsing per bundle anyway. Add before we start
                  * breaking out so we don't miss the final bundle. */
 
                 midg_stats.bundle_count++;
                 midg_stats.quadword_count += num_quad_words;
 
-                fprintf(fp, "\n");
-
-                unsigned next = (words[i] & 0xF0) >> 4;
+                /* Include a synthetic "break" instruction at the end of the
+                 * bundle to signify that if, absent a branch, the shader
+                 * execution will stop here. Stop disassembly at such a break
+                 * based on a heuristic */
+
+                if (next_tag == TAG_BREAK) {
+                        if (branch_forward) {
+                                fprintf(fp, "break\n");
+                        } else {
+                                fprintf(fp, "\n");
+                                break;
+                        }
+                }
 
-                if (i < num_words && next == 1 && !branch_forward)
-                        break;
+                fprintf(fp, "\n");
 
                 i += 4 * num_quad_words;
         }
 
+        if (last_next_tag != TAG_BREAK) {
+                fprintf(fp, "/* XXX: shader ended with tag %s */\n",
+                                midgard_tag_props[last_next_tag].name);
+        }
+
         free(midg_tags);
 
         /* We computed work_count as max_work_registers, so add one to get the