freedreno/ir3: better cleanup when removing unused instructions
authorRob Clark <robdclark@chromium.org>
Sat, 4 Apr 2020 16:53:32 +0000 (09:53 -0700)
committerMarge Bot <eric+marge@anholt.net>
Mon, 13 Apr 2020 20:47:28 +0000 (20:47 +0000)
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>

src/freedreno/ir3/ir3.h
src/freedreno/ir3/ir3_depth.c
src/freedreno/ir3/ir3_postsched.c
src/freedreno/ir3/ir3_print.c

index 65c16791e6277500ff77e252269bdc8fae81b2aa..7fb0d823d25e8aca38f189cef94beb499b1e0048 100644 (file)
@@ -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) \
index 00d0c54fac590f3338fd676f1acfccbba5dff47d..90a0ddef51f71e1c6b5dd3d7acdb5231591381bf 100644 (file)
@@ -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);
 }
index 09e58750c048164aa7976ccfdf7b71fb08f3dd21..521078a04c9a6d322140da2a10c8b2a379fee387 100644 (file)
@@ -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;
                                }
index 44c8278276a2cbd1ffb6b1781e0ff9e9185389fa..b18a3d27e3451716ffa493a73c02c1d1e86afe47 100644 (file)
@@ -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");