From a89a9b65f82c7be8f41edcacd3aae82bb4cc9df9 Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Wed, 13 Nov 2024 22:58:16 +0000 Subject: [PATCH] pco: re-indexing debug option and additional vector and component tracking Signed-off-by: Simon Perretta Acked-by: Frank Binns Part-of: --- docs/envvars.rst | 3 + src/imagination/pco/pco.c | 2 +- src/imagination/pco/pco_debug.c | 1 + src/imagination/pco/pco_index.c | 61 +++++++++++++-------- src/imagination/pco/pco_internal.h | 14 ++++- src/imagination/pco/pco_ir.c | 3 + src/imagination/pco/pco_opt.c | 8 --- src/imagination/pco/pco_ra.c | 2 - src/imagination/pco/pco_schedule.c | 3 - src/imagination/pco/pco_trans_nir.c | 85 +++++++++++++++++++++-------- 10 files changed, 119 insertions(+), 63 deletions(-) diff --git a/docs/envvars.rst b/docs/envvars.rst index b4e7c23c1bb..a8bf3067428 100644 --- a/docs/envvars.rst +++ b/docs/envvars.rst @@ -1998,6 +1998,9 @@ PowerVR driver environment variables ``val_skip`` Skip IR validation. + ``reindex`` + Reindex IR at the end of each pass. + .. envvar:: PCO_SKIP_PASSES A comma-separated list of passes to skip. diff --git a/src/imagination/pco/pco.c b/src/imagination/pco/pco.c index b27d7daf266..f0732530b78 100644 --- a/src/imagination/pco/pco.c +++ b/src/imagination/pco/pco.c @@ -160,7 +160,7 @@ pco_func *pco_func_create(pco_shader *shader, rzalloc_array_size(func, sizeof(*func->params), num_params); } - func->vec_comps = _mesa_hash_table_u64_create(func); + func->vec_infos = _mesa_hash_table_u64_create(func); return func; } diff --git a/src/imagination/pco/pco_debug.c b/src/imagination/pco/pco_debug.c index 3da94998345..26635563b94 100644 --- a/src/imagination/pco/pco_debug.c +++ b/src/imagination/pco/pco_debug.c @@ -24,6 +24,7 @@ static const struct debug_named_value pco_debug_options[] = { { "val_skip", PCO_DEBUG_VAL_SKIP, "Skip IR validation." }, + { "reindex", PCO_DEBUG_REINDEX, "Reindex IR at the end of each pass." }, DEBUG_NAMED_VALUE_END, }; diff --git a/src/imagination/pco/pco_index.c b/src/imagination/pco/pco_index.c index 8e88ee34691..eb26342b00c 100644 --- a/src/imagination/pco/pco_index.c +++ b/src/imagination/pco/pco_index.c @@ -23,48 +23,62 @@ * \brief Indexes all shader child structures. * * \param[in,out] shader PCO shader. + * \param[in] skip_ssa Whether to skip SSA indexing. * \return True if the pass made progress. */ -bool pco_index(pco_shader *shader) +bool pco_index(pco_shader *shader, bool skip_ssa) { - assert(!shader->is_grouped); + /* TODO */ + if (shader->is_grouped) + return false; shader->next_func = 0; pco_foreach_func_in_shader (func, shader) { - unsigned *ssa_idx_map = - rzalloc_array_size(NULL, sizeof(*ssa_idx_map), func->next_ssa); + unsigned *ssa_idx_map = NULL; + if (!skip_ssa) { + ssa_idx_map = + rzalloc_array_size(NULL, sizeof(*ssa_idx_map), func->next_ssa); + } func->index = shader->next_func++; - func->next_ssa = 0; func->next_instr = 0; func->next_block = 0; - struct hash_table_u64 *vec_comps = _mesa_hash_table_u64_create(func); + struct hash_table_u64 *vec_infos = NULL; + if (!skip_ssa) { + func->next_ssa = 0; + vec_infos = _mesa_hash_table_u64_create(func); + } pco_foreach_block_in_func (block, func) { block->index = func->next_block++; pco_foreach_instr_in_block (instr, block) { instr->index = func->next_instr++; - pco_foreach_instr_dest_ssa (pdest, instr) { - ssa_idx_map[pdest->val] = func->next_ssa++; - if (instr->op == PCO_OP_VEC) { - pco_instr **comps = - _mesa_hash_table_u64_search(func->vec_comps, pdest->val); + if (!skip_ssa) { + pco_foreach_instr_dest_ssa (pdest, instr) { + ssa_idx_map[pdest->val] = func->next_ssa++; + if (instr->op == PCO_OP_VEC) { + pco_vec_info *vec_info = + _mesa_hash_table_u64_search(func->vec_infos, + pdest->val); - ralloc_steal(vec_comps, comps); + ralloc_steal(vec_infos, vec_info); - _mesa_hash_table_u64_insert(vec_comps, - ssa_idx_map[pdest->val], - comps); + _mesa_hash_table_u64_insert(vec_infos, + ssa_idx_map[pdest->val], + vec_info); + } + pdest->val = ssa_idx_map[pdest->val]; } - pdest->val = ssa_idx_map[pdest->val]; } } } - pco_foreach_instr_in_func (instr, func) { - pco_foreach_instr_src_ssa (psrc, instr) { - psrc->val = ssa_idx_map[psrc->val]; + if (!skip_ssa) { + pco_foreach_instr_in_func (instr, func) { + pco_foreach_instr_src_ssa (psrc, instr) { + psrc->val = ssa_idx_map[psrc->val]; + } } } @@ -72,10 +86,11 @@ bool pco_index(pco_shader *shader) /* pco_foreach_if_in_func */ /* pco_foreach_loop_in_func */ - _mesa_hash_table_u64_destroy(func->vec_comps); - func->vec_comps = vec_comps; - - ralloc_free(ssa_idx_map); + if (!skip_ssa) { + _mesa_hash_table_u64_destroy(func->vec_infos); + func->vec_infos = vec_infos; + ralloc_free(ssa_idx_map); + } } return true; diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 4a23919e179..99598369c7b 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -50,6 +50,7 @@ void pco_setup_nir_options(const struct pvr_device_info *dev_info, /* Debug. */ enum pco_debug { PCO_DEBUG_VAL_SKIP = BITFIELD64_BIT(0), + PCO_DEBUG_REINDEX = BITFIELD64_BIT(1), }; extern uint64_t pco_debug; @@ -279,6 +280,15 @@ typedef struct _pco_loop { unsigned index; /** Loop index. */ } pco_loop; +#define VEC_USER_MULTI ((void *)(~0ULL)) + +/** PCO vector information. */ +typedef struct _pco_vec_info { + pco_instr *instr; /** Vector producer. */ + pco_instr **comps; /** Array of vector components. */ + pco_instr *vec_user; /** Vector user, or none, or multi. */ +} pco_vec_info; + /** PCO function. */ typedef struct _pco_func { struct list_head link; /** Link in pco_shader::funcs. */ @@ -295,7 +305,7 @@ typedef struct _pco_func { unsigned num_params; pco_ref *params; - struct hash_table_u64 *vec_comps; + struct hash_table_u64 *vec_infos; unsigned next_ssa; /** Next SSA node index. */ unsigned next_instr; /** Next instruction index. */ @@ -1095,7 +1105,7 @@ bool pco_const_imms(pco_shader *shader); bool pco_dce(pco_shader *shader); bool pco_end(pco_shader *shader); bool pco_group_instrs(pco_shader *shader); -bool pco_index(pco_shader *shader); +bool pco_index(pco_shader *shader, bool skip_ssa); bool pco_nir_pfo(nir_shader *nir); bool pco_nir_pvi(nir_shader *nir); bool pco_opt(pco_shader *shader); diff --git a/src/imagination/pco/pco_ir.c b/src/imagination/pco/pco_ir.c index 346626af162..fe54225f6e3 100644 --- a/src/imagination/pco/pco_ir.c +++ b/src/imagination/pco/pco_ir.c @@ -33,6 +33,9 @@ static inline bool pco_should_skip_pass(const char *pass) UNUSED bool _; \ progress = true; \ \ + if (PCO_DEBUG(REINDEX)) \ + pco_index(shader, false); \ + \ pco_validate_shader(shader, "after " #pass); \ \ if (pco_should_print_shader_pass(shader)) \ diff --git a/src/imagination/pco/pco_opt.c b/src/imagination/pco/pco_opt.c index 4756792a4ea..e1b96412539 100644 --- a/src/imagination/pco/pco_opt.c +++ b/src/imagination/pco/pco_opt.c @@ -273,12 +273,8 @@ static inline bool fwd_prop(pco_shader *shader) bool pco_opt(pco_shader *shader) { bool progress = false; - - pco_index(shader); - progress |= back_prop(shader); progress |= fwd_prop(shader); - return progress; } @@ -314,7 +310,6 @@ bool pco_dce(pco_shader *shader) bool progress = false; BITSET_WORD *ssa_used; - pco_index(shader); pco_foreach_func_in_shader (func, shader) { ssa_used = rzalloc_array_size(NULL, sizeof(*ssa_used), @@ -348,8 +343,5 @@ bool pco_dce(pco_shader *shader) ralloc_free(ssa_used); } - if (progress) - pco_index(shader); - return progress; } diff --git a/src/imagination/pco/pco_ra.c b/src/imagination/pco/pco_ra.c index 7a510136642..5cacfed28db 100644 --- a/src/imagination/pco/pco_ra.c +++ b/src/imagination/pco/pco_ra.c @@ -282,8 +282,6 @@ bool pco_ra(pco_shader *shader) { assert(!shader->is_grouped); - pco_index(shader); - unsigned hw_temps = rogue_get_temps(shader->ctx->dev_info); /* TODO: * unsigned opt_temps = rogue_get_optimal_temps(shader->ctx->dev_info); diff --git a/src/imagination/pco/pco_schedule.c b/src/imagination/pco/pco_schedule.c index 6f592503077..c3e97dd10b9 100644 --- a/src/imagination/pco/pco_schedule.c +++ b/src/imagination/pco/pco_schedule.c @@ -43,8 +43,5 @@ bool pco_schedule(pco_shader *shader) } } - if (progress) - pco_index(shader); - return progress; } diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 75cb7cb83a6..b4dd121986f 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -45,23 +45,27 @@ static pco_block *trans_cf_nodes(trans_ctx *tctx, * \brief Splits a vector destination into scalar components. * * \param[in,out] tctx Translation context. + * \param[in] instr Instruction producing the vector destination. * \param[in] dest Instruction destination. */ -static void split_dest_comps(trans_ctx *tctx, pco_ref dest) +static void split_dest_comps(trans_ctx *tctx, pco_instr *instr, pco_ref dest) { unsigned chans = pco_ref_get_chans(dest); assert(chans > 1); pco_func *func = tctx->func; - pco_instr **comps = - rzalloc_array_size(func->vec_comps, sizeof(*comps), chans); + + pco_vec_info *vec_info = rzalloc_size(func->vec_infos, sizeof(*vec_info)); + vec_info->instr = instr; + vec_info->comps = + rzalloc_array_size(vec_info, sizeof(*vec_info->comps), chans); for (unsigned u = 0; u < chans; ++u) { pco_ref comp = pco_ref_new_ssa(func, pco_ref_get_bits(dest), 1); - comps[u] = pco_comp(&tctx->b, comp, dest, pco_ref_val16(u)); + vec_info->comps[u] = pco_comp(&tctx->b, comp, dest, pco_ref_val16(u)); } - _mesa_hash_table_u64_insert(func->vec_comps, dest.val, comps); + _mesa_hash_table_u64_insert(func->vec_infos, dest.val, vec_info); } /** @@ -144,25 +148,25 @@ pco_ref_nir_alu_src_t(const nir_alu_instr *alu, unsigned src, trans_ctx *tctx) if (!swizzle0 && seq_comps && chans == nir_src_num_components(alu_src->src)) return ref; - pco_instr **comps = - _mesa_hash_table_u64_search(tctx->func->vec_comps, ref.val); - assert(comps); + pco_vec_info *vec_info = + _mesa_hash_table_u64_search(tctx->func->vec_infos, ref.val); + assert(vec_info); /* One channel; just return its component. */ if (chans == 1) - return comps[swizzle0]->dest[0]; + return vec_info->comps[swizzle0]->dest[0]; /* Multiple channels, either a partial vec and/or swizzling; we need to build * a new vec for this. */ - pco_ref vec_comps[NIR_MAX_VEC_COMPONENTS] = { 0 }; + pco_ref comps[NIR_MAX_VEC_COMPONENTS] = { 0 }; for (unsigned u = 0; u < chans; ++u) - vec_comps[u] = comps[alu_src->swizzle[u]]->dest[0]; + comps[u] = vec_info->comps[alu_src->swizzle[u]]->dest[0]; pco_ref vec = pco_ref_new_ssa(tctx->func, pco_ref_get_bits(ref), chans); - pco_vec(&tctx->b, vec, chans, vec_comps); + pco_instr *instr = pco_vec(&tctx->b, vec, chans, comps); - split_dest_comps(tctx, vec); + split_dest_comps(tctx, instr, vec); return vec; } @@ -331,7 +335,7 @@ static pco_instr *trans_intr(trans_ctx *tctx, nir_intrinsic_instr *intr) } if (!pco_ref_is_scalar(dest)) - split_dest_comps(tctx, dest); + split_dest_comps(tctx, instr, dest); return instr; } @@ -432,7 +436,7 @@ static unsigned try_collate_vec_srcs(trans_ctx *tctx, collated_src[num_srcs_collated++] = collated_ref; s += chans - 1; - collated_vector |= true; + collated_vector = true; } return collated_vector ? num_srcs_collated : 0; @@ -460,7 +464,23 @@ static pco_instr *pco_trans_nir_vec(trans_ctx *tctx, if (!num_srcs_collated) return pco_vec(&tctx->b, dest, num_srcs, src); - return pco_vec(&tctx->b, dest, num_srcs_collated, collated_src); + pco_instr *instr = pco_vec(&tctx->b, dest, num_srcs_collated, collated_src); + + /* Record the collated vectors. */ + for (unsigned s = 0; s < num_srcs_collated; ++s) { + if (pco_ref_is_scalar(collated_src[s])) + continue; + + pco_vec_info *vec_info = + _mesa_hash_table_u64_search(tctx->func->vec_infos, + collated_src[s].val); + assert(vec_info); + + /* Skip if there are multiple users. */ + vec_info->vec_user = vec_info->vec_user ? VEC_USER_MULTI : instr; + } + + return instr; } /** @@ -525,7 +545,7 @@ static pco_instr *trans_alu(trans_ctx *tctx, nir_alu_instr *alu) } if (!pco_ref_is_scalar(dest)) - split_dest_comps(tctx, dest); + split_dest_comps(tctx, instr, dest); return instr; } @@ -540,20 +560,37 @@ static pco_instr *trans_alu(trans_ctx *tctx, nir_alu_instr *alu) static pco_instr *trans_const(trans_ctx *tctx, nir_load_const_instr *nconst) { unsigned num_bits = nconst->def.bit_size; - unsigned comps = nconst->def.num_components; + unsigned chans = nconst->def.num_components; /* TODO: support more bit sizes/components. */ assert(num_bits == 32); - assert(comps == 1); - uint64_t val = nir_const_value_as_uint(nconst->value[0], num_bits); pco_ref dest = pco_ref_nir_def_t(&nconst->def, tctx); - pco_ref imm = pco_ref_imm(val, pco_bits(num_bits), pco_ref_get_dtype(dest)); - pco_instr *instr = pco_movi32(&tctx->b, dest, imm); + if (pco_ref_is_scalar(dest)) { + assert(chans == 1); - if (!pco_ref_is_scalar(dest)) - split_dest_comps(tctx, dest); + uint64_t val = nir_const_value_as_uint(nconst->value[0], num_bits); + pco_ref imm = + pco_ref_imm(val, pco_bits(num_bits), pco_ref_get_dtype(dest)); + + return pco_movi32(&tctx->b, dest, imm); + } + + pco_ref comps[NIR_MAX_VEC_COMPONENTS] = { 0 }; + for (unsigned c = 0; c < chans; ++c) { + comps[c] = pco_ref_new_ssa(tctx->func, pco_ref_get_bits(dest), 1); + + uint64_t val = nir_const_value_as_uint(nconst->value[c], num_bits); + pco_ref imm = + pco_ref_imm(val, pco_bits(num_bits), pco_ref_get_dtype(dest)); + + pco_movi32(&tctx->b, comps[c], imm); + } + + pco_instr *instr = pco_vec(&tctx->b, dest, chans, comps); + + split_dest_comps(tctx, instr, dest); return instr; }