v3d/compiler: handle compact varyings
[mesa.git] / src / broadcom / compiler / vir_opt_dead_code.c
index 7ce05fb5f5102824530bc66fa886d80ce13a2cdf..6048ccfccb7c788519e9754ffa891f499d1d8ede 100644 (file)
@@ -47,10 +47,7 @@ dce(struct v3d_compile *c, struct qinst *inst)
                 vir_dump_inst(c, inst);
                 fprintf(stderr, "\n");
         }
-        assert(inst->qpu.flags.apf == V3D_QPU_PF_NONE);
-        assert(inst->qpu.flags.mpf == V3D_QPU_PF_NONE);
-        assert(inst->qpu.flags.auf == V3D_QPU_UF_NONE);
-        assert(inst->qpu.flags.muf == V3D_QPU_UF_NONE);
+        assert(!v3d_qpu_writes_flags(&inst->qpu));
         vir_remove_instruction(c, inst);
 }
 
@@ -58,31 +55,39 @@ static bool
 has_nonremovable_reads(struct v3d_compile *c, struct qinst *inst)
 {
         for (int i = 0; i < vir_get_nsrc(inst); i++) {
-                if (inst->src[i].file == QFILE_VPM) {
-                        /* Instance ID, Vertex ID: Should have been removed at
-                         * the NIR level
-                         */
-                        if (inst->src[i].index == ~0)
-                                return true;
+                if (inst->src[i].file == QFILE_VPM)
+                        return true;
+        }
 
-                        uint32_t attr = inst->src[i].index / 4;
-                        uint32_t offset = inst->src[i].index % 4;
+        return false;
+}
 
-                        if (c->vattr_sizes[attr] != offset)
-                                return true;
+static bool
+can_write_to_null(struct v3d_compile *c, struct qinst *inst)
+{
+        /* The SFU instructions must write to a physical register. */
+        if (c->devinfo->ver >= 41 && v3d_qpu_uses_sfu(&inst->qpu))
+                return false;
 
-                        /* Can't get rid of the last VPM read, or the
-                         * simulator (at least) throws an error.
-                         */
-                        uint32_t total_size = 0;
-                        for (uint32_t i = 0; i < ARRAY_SIZE(c->vattr_sizes); i++)
-                                total_size += c->vattr_sizes[i];
-                        if (total_size == 1)
-                                return true;
-                }
+        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");
         }
 
-        return false;
+        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
@@ -91,6 +96,12 @@ vir_opt_dead_code(struct v3d_compile *c)
         bool progress = false;
         bool *used = calloc(c->num_temps, sizeof(bool));
 
+        /* Defuse the "are you removing the cursor?" assertion in the core.
+         * You'll need to set up a new cursor for any new instructions after
+         * doing DCE (which we would expect, anyway).
+         */
+        c->cursor.link = NULL;
+
         vir_for_each_inst_inorder(inst, c) {
                 for (int i = 0; i < vir_get_nsrc(inst); i++) {
                         if (inst->src[i].file == QFILE_TEMP)
@@ -99,7 +110,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])) {
@@ -109,10 +128,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
@@ -122,7 +152,8 @@ vir_opt_dead_code(struct v3d_compile *c)
                                  * it's nicer to read the VIR code without
                                  * unused destination regs.
                                  */
-                                if (inst->dst.file == QFILE_TEMP) {
+                                if (inst->dst.file == QFILE_TEMP &&
+                                    can_write_to_null(c, inst)) {
                                         if (debug) {
                                                 fprintf(stderr,
                                                         "Removing dst from: ");
@@ -136,18 +167,7 @@ vir_opt_dead_code(struct v3d_compile *c)
                                 continue;
                         }
 
-                        for (int i = 0; i < vir_get_nsrc(inst); i++) {
-                                if (inst->src[i].file != QFILE_VPM)
-                                        continue;
-                                uint32_t attr = inst->src[i].index / 4;
-                                uint32_t offset = (inst->src[i].index % 4);
-
-                                if (c->vattr_sizes[attr] == offset) {
-                                        c->num_inputs--;
-                                        c->vattr_sizes[attr]--;
-                                }
-                        }
-
+                        assert(inst != last_flags_write);
                         dce(c, inst);
                         progress = true;
                         continue;