diff --git a/.pick_status.json b/.pick_status.json index a2a3f8e5054..92e7138f909 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -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 diff --git a/src/freedreno/ir3/ir3_legalize.c b/src/freedreno/ir3/ir3_legalize.c index 21d1e16e78e..649764b2525 100644 --- a/src/freedreno/ir3/ir3_legalize.c +++ b/src/freedreno/ir3/ir3_legalize.c @@ -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);