From cf74048fd14eb594dbb23e07d37cf8df44564263 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 4 Apr 2020 09:53:32 -0700 Subject: [PATCH] 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 Part-of: --- src/freedreno/ir3/ir3.h | 23 ++++++++++++++++------- src/freedreno/ir3/ir3_depth.c | 15 ++++++++++++++- src/freedreno/ir3/ir3_postsched.c | 2 +- src/freedreno/ir3/ir3_print.c | 6 +++++- 4 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 65c16791e62..7fb0d823d25 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -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) \ diff --git a/src/freedreno/ir3/ir3_depth.c b/src/freedreno/ir3/ir3_depth.c index 00d0c54fac5..90a0ddef51f 100644 --- a/src/freedreno/ir3/ir3_depth.c +++ b/src/freedreno/ir3/ir3_depth.c @@ -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); } diff --git a/src/freedreno/ir3/ir3_postsched.c b/src/freedreno/ir3/ir3_postsched.c index 09e58750c04..521078a04c9 100644 --- a/src/freedreno/ir3/ir3_postsched.c +++ b/src/freedreno/ir3/ir3_postsched.c @@ -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; } diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c index 44c8278276a..b18a3d27e34 100644 --- a/src/freedreno/ir3/ir3_print.c +++ b/src/freedreno/ir3/ir3_print.c @@ -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"); -- 2.30.2