pan/midgard: Only one conditional per bundle allowed
[mesa.git] / src / panfrost / midgard / midgard_schedule.c
index ecc4f4696b53eef19536f7149c0958429c0b0046..ff71e0dcd3f80c4a6258bb491a1d422ac19fa8eb 100644 (file)
@@ -188,10 +188,6 @@ is_single_component_mask(unsigned mask)
 static bool
 mir_is_scalar(midgard_instruction *ains)
 {
-        /* Does the op support scalar units? */
-        if (!(alu_opcode_props[ains->alu.op].props & UNITS_SCALAR))
-                return false;
-
         /* Do we try to use it as a vector op? */
         if (!is_single_component_mask(ains->mask))
                 return false;
@@ -339,6 +335,10 @@ struct midgard_predicate {
 
         /* Exclude this destination (if not ~0) */
         unsigned exclude;
+
+        /* Don't schedule instructions consuming conditionals (since we already
+         * scheduled one). Excludes conditional branches and csel */
+        bool no_cond;
 };
 
 /* For an instruction that can fit, adjust it to fit and update the constants
@@ -397,12 +397,15 @@ mir_choose_instruction(
         bool alu = tag == TAG_ALU_4;
         unsigned unit = predicate->unit;
         bool branch = alu && (unit == ALU_ENAB_BR_COMPACT);
+        bool scalar = (unit != ~0) && (unit & UNITS_SCALAR);
+        bool no_cond = predicate->no_cond;
 
         /* Iterate to find the best instruction satisfying the predicate */
         unsigned i;
         BITSET_WORD tmp;
 
         signed best_index = -1;
+        bool best_conditional = false;
 
         /* Enforce a simple metric limiting distance to keep down register
          * pressure. TOOD: replace with liveness tracking for much better
@@ -431,14 +434,24 @@ mir_choose_instruction(
                 if (branch && !instructions[i]->compact_branch)
                         continue;
 
+                if (alu && scalar && !mir_is_scalar(instructions[i]))
+                        continue;
+
                 if (alu && !mir_adjust_constants(instructions[i], predicate, false))
                         continue;
 
+                bool conditional = alu && !branch && OP_IS_CSEL(instructions[i]->alu.op);
+                conditional |= (branch && !instructions[i]->prepacked_branch && instructions[i]->branch.conditional);
+
+                if (conditional && no_cond)
+                        continue;
+
                 /* Simulate in-order scheduling */
                 if ((signed) i < best_index)
                         continue;
 
                 best_index = i;
+                best_conditional = conditional;
         }
 
 
@@ -455,6 +468,9 @@ mir_choose_instruction(
 
                 if (alu)
                         mir_adjust_constants(instructions[best_index], predicate, true);
+
+                /* Once we schedule a conditional, we can't again */
+                predicate->no_cond |= best_conditional;
         }
 
         return instructions[best_index];
@@ -753,6 +769,8 @@ mir_schedule_alu(
                         unreachable("Bad condition");
         }
 
+        mir_choose_alu(&smul, instructions, worklist, len, &predicate, UNIT_SMUL);
+
         if (!writeout)
                 mir_choose_alu(&vlut, instructions, worklist, len, &predicate, UNIT_VLUT);
 
@@ -777,6 +795,9 @@ mir_schedule_alu(
                         unreachable("Bad condition");
         }
 
+        /* Stage 2, let's schedule sadd before vmul for writeout */
+        mir_choose_alu(&sadd, instructions, worklist, len, &predicate, UNIT_SADD);
+
         /* Check if writeout reads its own register */
         bool bad_writeout = false;