ir3/legalize: prevent infinite loop when inserting (ss)nop

We need to insert a (ss)nop when an instruction that doesn't support
(ss) needs it. However, when this happens in a block that needs to be
legalized more than once (e.g., because it is in a loop), the (ss)nop
would be inserted every iteration, causing an infinite loop.

Fix this by checking if the previous instructions is a nop and applying
(ss) there.

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Fixes: 5993723471 ("freedreno/a3xx/compiler: scheduling/legalize fixes")
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36440>
(cherry picked from commit c8f9990733)
This commit is contained in:
Job Noorman 2025-07-29 13:04:19 +02:00 committed by Eric Engestrom
parent c3272431d1
commit fd859840f7
2 changed files with 14 additions and 6 deletions

View file

@ -6444,7 +6444,7 @@
"description": "ir3/legalize: prevent infinite loop when inserting (ss)nop",
"nominated": true,
"nomination_type": 2,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": "5993723471a81003bd82d189836ccdd8d085a7b5",
"notes": null

View file

@ -561,12 +561,20 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
* this should be a pretty rare case:
*/
if ((n->flags & IR3_INSTR_SS) && !supports_ss(n)) {
struct ir3_instruction *nop;
nop = ir3_NOP(&build);
nop->flags |= IR3_INSTR_SS;
if (last_n && last_n->opc == OPC_NOP) {
/* Note that reusing the previous nop isn't just an optimization
* but prevents infinitely adding nops when this block is in a loop
* and needs to be legalized more than once.
*/
last_n->flags |= IR3_INSTR_SS;
} else {
struct ir3_instruction *nop = ir3_NOP(&build);
nop->flags |= IR3_INSTR_SS;
last_n = nop;
cycle++;
}
n->flags &= ~IR3_INSTR_SS;
last_n = nop;
cycle++;
}
unsigned delay = delay_calc(ctx, state, n, cycle);