freedreno/ir3: better cleanup when removing unused instructions
Do a better job of pruning when removing unused instructions, including cleaning up dangling false-deps. This introduces a new ssa src pointer iterator, which makes it easy to clear links without having to think about whether it is a normal ssa src or a false-dep. Signed-off-by: Rob Clark <robdclark@chromium.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4440>
This commit is contained in:
@@ -1118,13 +1118,16 @@ static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
|
||||
return cnt;
|
||||
}
|
||||
|
||||
static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr, unsigned n)
|
||||
static inline struct ir3_instruction **
|
||||
__ssa_srcp_n(struct ir3_instruction *instr, unsigned n)
|
||||
{
|
||||
if (n == (instr->regs_count + instr->deps_count))
|
||||
return instr->address;
|
||||
return &instr->address;
|
||||
if (n >= instr->regs_count)
|
||||
return instr->deps[n - instr->regs_count];
|
||||
return ssa(instr->regs[n]);
|
||||
return &instr->deps[n - instr->regs_count];
|
||||
if (ssa(instr->regs[n]))
|
||||
return &instr->regs[n]->instr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool __is_false_dep(struct ir3_instruction *instr, unsigned n)
|
||||
@@ -1136,12 +1139,18 @@ static inline bool __is_false_dep(struct ir3_instruction *instr, unsigned n)
|
||||
return false;
|
||||
}
|
||||
|
||||
#define __src_cnt(__instr) ((__instr)->address ? (__instr)->regs_count : (__instr)->regs_count - 1)
|
||||
#define foreach_ssa_srcp_n(__srcp, __n, __instr) \
|
||||
for (struct ir3_instruction **__srcp = (void *)~0; __srcp; __srcp = NULL) \
|
||||
for (unsigned __cnt = __ssa_src_cnt(__instr), __n = 0; __n < __cnt; __n++) \
|
||||
if ((__srcp = __ssa_srcp_n(__instr, __n)))
|
||||
|
||||
#define foreach_ssa_srcp(__srcp, __instr) \
|
||||
foreach_ssa_srcp_n(__srcp, __i, __instr)
|
||||
|
||||
/* iterator for an instruction's SSA sources (instr), also returns src #: */
|
||||
#define foreach_ssa_src_n(__srcinst, __n, __instr) \
|
||||
for (unsigned __cnt = __ssa_src_cnt(__instr), __n = 0; __n < __cnt; __n++) \
|
||||
if ((__srcinst = __ssa_src_n(__instr, __n)))
|
||||
foreach_ssa_srcp_n(__srcp, __n, __instr) \
|
||||
if ((__srcinst = *__srcp))
|
||||
|
||||
/* iterator for an instruction's SSA sources (instr): */
|
||||
#define foreach_ssa_src(__srcinst, __instr) \
|
||||
|
@@ -95,7 +95,7 @@ remove_unused_by_block(struct ir3_block *block)
|
||||
/* tex (cat5) instructions have a writemask, so we can
|
||||
* mask off unused components. Other instructions do not.
|
||||
*/
|
||||
if (is_tex_or_prefetch(src) && (src->regs[0]->wrmask > 1)) {
|
||||
if (src && is_tex_or_prefetch(src) && (src->regs[0]->wrmask > 1)) {
|
||||
src->regs[0]->wrmask &= ~(1 << instr->split.off);
|
||||
|
||||
/* prune no-longer needed right-neighbors. We could
|
||||
@@ -114,6 +114,13 @@ remove_unused_by_block(struct ir3_block *block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* prune false-deps, etc: */
|
||||
foreach_ssa_use (use, instr)
|
||||
foreach_ssa_srcp_n (srcp, n, use)
|
||||
if (*srcp == instr)
|
||||
*srcp = NULL;
|
||||
|
||||
list_delinit(&instr->node);
|
||||
progress = true;
|
||||
}
|
||||
@@ -206,8 +213,14 @@ compute_depth_and_remove_unused(struct ir3 *ir, struct ir3_shader_variant *so)
|
||||
void
|
||||
ir3_depth(struct ir3 *ir, struct ir3_shader_variant *so)
|
||||
{
|
||||
void *mem_ctx = ralloc_context(NULL);
|
||||
bool progress;
|
||||
|
||||
ir3_find_ssa_uses(ir, mem_ctx, true);
|
||||
|
||||
do {
|
||||
progress = compute_depth_and_remove_unused(ir, so);
|
||||
} while (progress);
|
||||
|
||||
ralloc_free(mem_ctx);
|
||||
}
|
||||
|
@@ -685,7 +685,7 @@ cleanup_self_movs(struct ir3 *ir)
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < instr->deps_count; i++) {
|
||||
if (is_self_mov(instr->deps[i])) {
|
||||
if (instr->deps[i] && is_self_mov(instr->deps[i])) {
|
||||
list_delinit(&instr->deps[i]->node);
|
||||
instr->deps[i] = instr->deps[i]->regs[1]->instr;
|
||||
}
|
||||
|
@@ -73,7 +73,11 @@ static void print_instr_name(struct ir3_instruction *instr, bool flags)
|
||||
printf("%04u:", instr->name);
|
||||
printf("%04u:", instr->ip);
|
||||
printf("%03d:", instr->depth);
|
||||
printf("%03u: ", instr->use_count);
|
||||
if (instr->flags & IR3_INSTR_UNUSED) {
|
||||
printf("XXX: ");
|
||||
} else {
|
||||
printf("%03u: ", instr->use_count);
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
printf("\t");
|
||||
|
Reference in New Issue
Block a user