v3d: Dead-code eliminate unused flags updates.
authorEric Anholt <eric@anholt.net>
Sat, 29 Dec 2018 20:44:22 +0000 (12:44 -0800)
committerEric Anholt <eric@anholt.net>
Sun, 30 Dec 2018 16:05:11 +0000 (08:05 -0800)
The greedy comparison folding in bcsel means that we may have left the
original bool-generating NIR ALU instruction dead, but DCE wasn't
eliminating the VIR code for it because of the flags updates.

total instructions in shared programs: 5186024 -> 5100894 (-1.64%)
instructions in affected programs: 1448695 -> 1363565 (-5.88%)

src/broadcom/compiler/vir_opt_dead_code.c

index 9c93846e9b86461cf391d8b5aff988e30873ed5b..a486708bfa552402413f145814f3ba39a6d44aea 100644 (file)
@@ -92,6 +92,24 @@ can_write_to_null(struct v3d_compile *c, struct qinst *inst)
         return true;
 }
 
+static void
+vir_dce_flags(struct v3d_compile *c, struct qinst *inst)
+{
+        if (debug) {
+                fprintf(stderr,
+                        "Removing flags write from: ");
+                vir_dump_inst(c, inst);
+                fprintf(stderr, "\n");
+        }
+
+        assert(inst->qpu.type == V3D_QPU_INSTR_TYPE_ALU);
+
+        inst->qpu.flags.apf = V3D_QPU_PF_NONE;
+        inst->qpu.flags.mpf = V3D_QPU_PF_NONE;
+        inst->qpu.flags.auf = V3D_QPU_UF_NONE;
+        inst->qpu.flags.muf = V3D_QPU_UF_NONE;
+}
+
 bool
 vir_opt_dead_code(struct v3d_compile *c)
 {
@@ -112,7 +130,15 @@ vir_opt_dead_code(struct v3d_compile *c)
         }
 
         vir_for_each_block(block, c) {
+                struct qinst *last_flags_write = NULL;
+
                 vir_for_each_inst_safe(inst, block) {
+                        /* If this instruction reads the flags, we can't
+                         * remove the flags generation for it.
+                         */
+                        if (v3d_qpu_reads_flags(&inst->qpu))
+                                last_flags_write = NULL;
+
                         if (inst->dst.file != QFILE_NULL &&
                             !(inst->dst.file == QFILE_TEMP &&
                               !used[inst->dst.index])) {
@@ -122,10 +148,21 @@ vir_opt_dead_code(struct v3d_compile *c)
                         if (vir_has_side_effects(c, inst))
                                 continue;
 
-                        if (inst->qpu.flags.apf != V3D_QPU_PF_NONE ||
-                            inst->qpu.flags.mpf != V3D_QPU_PF_NONE ||
-                            inst->qpu.flags.auf != V3D_QPU_UF_NONE ||
-                            inst->qpu.flags.muf != V3D_QPU_UF_NONE ||
+                        if (v3d_qpu_writes_flags(&inst->qpu)) {
+                                /* If we obscure a previous flags write,
+                                 * drop it.
+                                 */
+                                if (last_flags_write &&
+                                    (inst->qpu.flags.apf != V3D_QPU_PF_NONE ||
+                                     inst->qpu.flags.mpf != V3D_QPU_PF_NONE)) {
+                                        vir_dce_flags(c, last_flags_write);
+                                        progress = true;
+                                }
+
+                                last_flags_write = inst;
+                        }
+
+                        if (v3d_qpu_writes_flags(&inst->qpu) ||
                             has_nonremovable_reads(c, inst)) {
                                 /* If we can't remove the instruction, but we
                                  * don't need its destination value, just
@@ -162,6 +199,7 @@ vir_opt_dead_code(struct v3d_compile *c)
                                 }
                         }
 
+                        assert(inst != last_flags_write);
                         dce(c, inst);
                         progress = true;
                         continue;