/* 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
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
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;
}
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];
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);
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;