freedreno/rddecompiler: Decode ELSE branches using NOPs

In newer traces, in any cases where instructions need to be executed
for both cases of a predicate, such as for GMEM/sysmem. The proprietary
driver emits the TRUE and FALSE body one after another with a NOP at
the end of the TRUE condition body so the CP skips over the FALSE body.

Currently, the NOP skips over all instructions in the ELSE body which
results in them not being decoded whatsoever. This commit checks if
we encounter any NOPs while in a conditional block and appropriately
parses out them out into their own ELSE scope when we do.

Signed-off-by: Mark Collins <mark@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26465>
This commit is contained in:
Mark Collins
2023-12-01 12:02:36 +00:00
committed by Marge Bot
parent cfc2a85b89
commit fa735aacbf

View File

@@ -369,7 +369,7 @@ decompile_domain(uint32_t pkt, uint32_t *dwords, uint32_t sizedwords,
}
static void
decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level)
decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level, uint32_t *cond_count)
{
int dwords_left = sizedwords;
uint32_t count = 0; /* dword count including packet header */
@@ -396,7 +396,7 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level)
printlvl(level + 1, "begin_ib();\n");
uint32_t *ptr = hostptr(ibaddr);
decompile_commands(ptr, ibsize, level + 1);
decompile_commands(ptr, ibsize, level + 1, NULL);
printlvl(level + 1, "end_ib();\n");
printlvl(level, "}\n");
@@ -412,7 +412,7 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level)
printlvl(level + 1, "begin_draw_state();\n");
uint32_t *ptr = hostptr(ibaddr);
decompile_commands(ptr, state_count, level + 1);
decompile_commands(ptr, state_count, level + 1, NULL);
printlvl(level + 1, "end_draw_state(%u);\n", unchanged);
printlvl(level, "}\n");
@@ -466,11 +466,41 @@ decompile_commands(uint32_t *dwords, uint32_t sizedwords, int level)
printlvl(level, "{\n");
printlvl(level + 1, "/* BEGIN COND (%d DWORDS) */\n", cond_count);
decompile_commands(dwords + count, cond_count, level + 1);
decompile_commands(dwords + count, cond_count, level + 1, &cond_count);
count += cond_count;
printlvl(level + 1, "/* END COND */\n");
printlvl(level, "}\n");
} else if (val == CP_NOP) {
/* Prop will often use NOP past the end of cond execs
* which basically create an else path for the cond exec
*/
const char *packet_name = pktname(val);
const char *dom_name = packet_name;
if (count > dwords_left) {
int else_cond_count = count - dwords_left;
assert(cond_count);
*cond_count += else_cond_count;
printlvl(level, "pkt7(cs, %s, %u);\n", packet_name, count - 1);
for (int i = 1; i < dwords_left; i++) {
printlvl(level, "pkt(cs, 0x%x);\n", dwords[i]);
}
printlvl(level, "/* TO ELSE COND */\n");
printlvl(level - 1, "}\n");
printlvl(level - 1, "{\n");
printlvl(level, "/* ELSE COND (%d DWORDS) */\n", else_cond_count);
decompile_commands(dwords + dwords_left, else_cond_count, level, NULL);
return;
} else {
decompile_domain(val, dwords + 1, count - 1, dom_name, packet_name,
level);
}
} else {
const char *packet_name = pktname(val);
const char *dom_name = packet_name;
@@ -596,7 +626,7 @@ handle_file(const char *filename, uint32_t submit_to_decompile)
parse_addr(ps.buf, ps.sz, &sizedwords, &gpuaddr);
if (submit == submit_to_decompile) {
decompile_commands(hostptr(gpuaddr), sizedwords, 0);
decompile_commands(hostptr(gpuaddr), sizedwords, 0, NULL);
}
submit++;