freedreno/ir3: DCE unused arrays
authorRob Clark <robdclark@chromium.org>
Tue, 14 Jul 2020 17:36:04 +0000 (10:36 -0700)
committerMarge Bot <eric+marge@anholt.net>
Tue, 14 Jul 2020 23:26:15 +0000 (23:26 +0000)
Letting unused arrays stick around confuses RA, which assigns vreg names
to the unused arrays, but then does not precolor them (because they are
unused).  This leads to an assert in ra_select_reg_merged():

  skqp: ../src/freedreno/ir3/ir3_ra.c:589: name_to_instr: Assertion '!name_is_array(ctx, name)' failed.

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3262
Signed-off-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5907>

src/freedreno/ir3/ir3.h
src/freedreno/ir3/ir3_dce.c

index 51315a5f361530e40373190de70d1dc0dbfa757d..634089c590bbe271939717f76f9cc8b4b3c634c6 100644 (file)
@@ -506,6 +506,8 @@ struct ir3_array {
 
        /* Indicates if half-precision */
        bool half;
+
+       bool unused;
 };
 
 struct ir3_array * ir3_lookup_array(struct ir3 *ir, unsigned id);
@@ -1244,6 +1246,8 @@ static inline bool __is_false_dep(struct ir3_instruction *instr, unsigned n)
 /* iterators for arrays: */
 #define foreach_array(__array, __list) \
        list_for_each_entry(struct ir3_array, __array, __list, node)
+#define foreach_array_safe(__array, __list) \
+       list_for_each_entry_safe(struct ir3_array, __array, __list, node)
 
 /* Check if condition is true for any src instruction.
  */
index 92a5d87eed81812ed87693e7a3a230f07ea073e1..e1e303f548279e940a8af80f5ae059690ed55e9a 100644 (file)
  * Dead code elimination:
  */
 
+static void
+mark_array_use(struct ir3_instruction *instr, struct ir3_register *reg)
+{
+       if (reg->flags & IR3_REG_ARRAY) {
+               struct ir3_array *arr =
+                       ir3_lookup_array(instr->block->shader, reg->array.id);
+               arr->unused = false;
+       }
+}
+
 static void
 instr_dce(struct ir3_instruction *instr, bool falsedep)
 {
@@ -43,6 +53,12 @@ instr_dce(struct ir3_instruction *instr, bool falsedep)
        if (ir3_instr_check_mark(instr))
                return;
 
+       if (writes_gpr(instr))
+               mark_array_use(instr, instr->regs[0]);   /* dst */
+
+       foreach_src (reg, instr)
+               mark_array_use(instr, reg);              /* src */
+
        foreach_ssa_src_n (src, i, instr) {
                instr_dce(src, __is_false_dep(instr, i));
        }
@@ -118,6 +134,9 @@ find_and_remove_unused(struct ir3 *ir, struct ir3_shader_variant *so)
                }
        }
 
+       foreach_array (arr, &ir->array_list)
+               arr->unused = true;
+
        foreach_output (out, ir)
                instr_dce(out, false);
 
@@ -135,6 +154,12 @@ find_and_remove_unused(struct ir3 *ir, struct ir3_shader_variant *so)
                progress |= remove_unused_by_block(block);
        }
 
+       /* remove un-used arrays: */
+       foreach_array_safe (arr, &ir->array_list) {
+               if (arr->unused)
+                       list_delinit(&arr->node);
+       }
+
        /* fixup wrmask of split instructions to account for adjusted tex
         * wrmask's:
         */