From b6e59297f7f7628aab1374a603678686642f8e8a Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Wed, 20 Aug 2025 16:48:55 +0200 Subject: [PATCH] ir3: emit descriptor prefetch in block dominated by its sources Descriptor prefetches may be generated for instructions in control flow. This means we cannot simply emit prefetches at the end of the preamble because that may not be dominated by all their sources. This commit uses the helpers introduced by e7ac1094f69 ("ir3: rematerialize preamble defs in block dominated by sources") to find the correct block to insert prefetches. Fixes NIR validation errors in Dying Light 2. Signed-off-by: Job Noorman Fixes: 4e2a0a5ad09 ("ir3: Add descriptor prefetching optimization on a7xx") Part-of: (cherry picked from commit 24cdb0b636dc6b6a7eee4e9175c61459b0bc88dd) --- .pick_status.json | 2 +- src/freedreno/ir3/ir3_nir_opt_preamble.c | 53 +++++++++++++++++++----- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index 0d73d4685e4..44216e92a1d 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -6474,7 +6474,7 @@ "description": "ir3: emit descriptor prefetch in block dominated by its sources", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "4e2a0a5ad097ef2cbbcf38f7a4f508061a5f9c0c", "notes": null diff --git a/src/freedreno/ir3/ir3_nir_opt_preamble.c b/src/freedreno/ir3/ir3_nir_opt_preamble.c index 64ae33846cf..d27a8e5051b 100644 --- a/src/freedreno/ir3/ir3_nir_opt_preamble.c +++ b/src/freedreno/ir3/ir3_nir_opt_preamble.c @@ -391,18 +391,15 @@ struct find_insert_block_state { }; static bool -find_dominated_src(nir_src *src, void *data) +find_dominated_block(nir_block *block, struct find_insert_block_state *state) { - struct find_insert_block_state *state = data; - nir_block *src_block = src->ssa->parent_instr->block; - if (!state->insert_block) { - state->insert_block = src_block; + state->insert_block = block; return true; - } else if (nir_block_dominates(state->insert_block, src_block)) { - state->insert_block = src_block; + } else if (nir_block_dominates(state->insert_block, block)) { + state->insert_block = block; return true; - } else if (nir_block_dominates(src_block, state->insert_block)) { + } else if (nir_block_dominates(block, state->insert_block)) { return true; } else { state->insert_block = NULL; @@ -410,6 +407,14 @@ find_dominated_src(nir_src *src, void *data) } } +static bool +find_dominated_src(nir_src *src, void *data) +{ + struct find_insert_block_state *state = data; + nir_block *src_block = src->ssa->parent_instr->block; + return find_dominated_block(src_block, state); +} + /* Find the block where instr can be inserted. This is the block that is * dominated by all its sources. If instr doesn't have any sources, return dflt. */ @@ -427,6 +432,22 @@ find_insert_block(nir_instr *instr, nir_block *dflt) return NULL; } +static nir_block * +find_insert_block_for_defs(nir_def *defs[], unsigned n) +{ + struct find_insert_block_state state = { + .insert_block = NULL, + }; + + for (unsigned i = 0; i < n; i++) { + if (!find_dominated_block(defs[i]->parent_instr->block, &state)) { + return NULL; + } + } + + return state.insert_block; +} + static bool dominates(const nir_instr *old_instr, const nir_instr *new_instr) { @@ -598,6 +619,20 @@ static bool emit_descriptor_prefetch(nir_builder *b, nir_instr *instr, nir_def **descs, struct prefetch_state *state) { + nir_block *insert_block = descs[0]->parent_instr->block; + + if (descs[1]) { + insert_block = find_insert_block_for_defs(descs, 2); + + /* Since the preamble control flow was reconstructed from the original + * one, and the two descriptor defs were used by the same instruction, we + * must be able to find a legal place to insert the prefetch. + */ + assert(insert_block); + } + + b->cursor = nir_after_block(insert_block); + if (instr->type == nir_instr_type_tex) { nir_tex_instr *tex = nir_instr_as_tex(instr); int sampler_index = @@ -771,8 +806,6 @@ ir3_nir_opt_prefetch_descriptors(nir_shader *nir, struct ir3_shader_variant *v) preamble_defs); } - /* ir3_rematerialize_def_for_preamble may have moved the cursor. */ - b.cursor = nir_after_impl(preamble); progress |= emit_descriptor_prefetch(&b, instr, preamble_descs, &state); if (state.sampler.num_prefetches == MAX_PREFETCHES &&