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 &&