broadcom/vc5: Remove no-op MOVs after register allocation.
authorEric Anholt <eric@anholt.net>
Sun, 4 Feb 2018 21:05:03 +0000 (21:05 +0000)
committerEric Anholt <eric@anholt.net>
Mon, 5 Feb 2018 09:29:37 +0000 (09:29 +0000)
We emit some MOVs to track lifetimes of payload registers, but we don't
need there to be actual MOV instructions for them.

total instructions in shared programs: 101045 -> 100423 (-0.62%)
instructions in affected programs:     37083 -> 36461 (-1.68%)

src/broadcom/compiler/vir_to_qpu.c

index 11a7ef910311e9a063afe0709e57f7fbd38f30da..568a004803b90233a9713d1f7d57c6b43e628e37 100644 (file)
@@ -138,6 +138,60 @@ set_src(struct v3d_qpu_instr *instr, enum v3d_qpu_mux *mux, struct qpu_reg src)
         }
 }
 
+static bool
+is_no_op_mov(struct qinst *qinst)
+{
+        static const struct v3d_qpu_sig no_sig = {0};
+
+        /* Make sure it's just a lone MOV. */
+        if (qinst->qpu.type != V3D_QPU_INSTR_TYPE_ALU ||
+            qinst->qpu.alu.mul.op != V3D_QPU_M_MOV ||
+            qinst->qpu.alu.add.op != V3D_QPU_A_NOP ||
+            memcmp(&qinst->qpu.sig, &no_sig, sizeof(no_sig)) != 0) {
+                return false;
+        }
+
+        /* Check if it's a MOV from a register to itself. */
+        enum v3d_qpu_waddr waddr = qinst->qpu.alu.mul.waddr;
+        if (qinst->qpu.alu.mul.magic_write) {
+                if (waddr < V3D_QPU_WADDR_R0 || waddr > V3D_QPU_WADDR_R4)
+                        return false;
+
+                if (qinst->qpu.alu.mul.a !=
+                    V3D_QPU_MUX_R0 + (waddr - V3D_QPU_WADDR_R0)) {
+                        return false;
+                }
+        } else {
+                int raddr;
+
+                switch (qinst->qpu.alu.mul.a) {
+                case V3D_QPU_MUX_A:
+                        raddr = qinst->qpu.raddr_a;
+                        break;
+                case V3D_QPU_MUX_B:
+                        raddr = qinst->qpu.raddr_b;
+                        break;
+                default:
+                        return false;
+                }
+                if (raddr != waddr)
+                        return false;
+        }
+
+        /* No packing or flags updates, or we need to execute the
+         * instruction.
+         */
+        if (qinst->qpu.alu.mul.a_unpack != V3D_QPU_UNPACK_NONE ||
+            qinst->qpu.alu.mul.output_pack != V3D_QPU_PACK_NONE ||
+            qinst->qpu.flags.mc != V3D_QPU_COND_NONE ||
+            qinst->qpu.flags.mpf != V3D_QPU_PF_NONE ||
+            qinst->qpu.flags.muf != V3D_QPU_UF_NONE) {
+                return false;
+        }
+
+        return true;
+}
+
 static void
 v3d_generate_code_block(struct v3d_compile *c,
                         struct qblock *block,
@@ -145,7 +199,7 @@ v3d_generate_code_block(struct v3d_compile *c,
 {
         int last_vpm_read_index = -1;
 
-        vir_for_each_inst(qinst, block) {
+        vir_for_each_inst_safe(qinst, block) {
 #if 0
                 fprintf(stderr, "translating qinst to qpu: ");
                 vir_dump_inst(c, qinst);
@@ -289,6 +343,11 @@ v3d_generate_code_block(struct v3d_compile *c,
 
                                 qinst->qpu.alu.mul.waddr = dst.index;
                                 qinst->qpu.alu.mul.magic_write = dst.magic;
+
+                                if (is_no_op_mov(qinst)) {
+                                        vir_remove_instruction(c, qinst);
+                                        continue;
+                                }
                         }
                 } else {
                         assert(qinst->qpu.type == V3D_QPU_INSTR_TYPE_BRANCH);