pan/midgard: Imply next tags

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>
This commit is contained in:
Alyssa Rosenzweig 2020-02-11 21:37:18 -05:00
parent 453c64663c
commit 57a84278fd
1 changed files with 41 additions and 10 deletions

View 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;
/* 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;
}
}
fprintf(fp, "\n");
unsigned next = (words[i] & 0xF0) >> 4;
if (i < num_words && next == 1 && !branch_forward)
break;
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