}
}
+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,
{
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);
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);