}
}
+/* Being a little silly with the names, but returns the op that is the bitwise
+ * inverse of the op with the argument switched. I.e. (f and g are
+ * contrapositives):
+ *
+ * f(a, b) = ~g(b, a)
+ *
+ * Corollary: if g is the contrapositve of f, f is the contrapositive of g:
+ *
+ * f(a, b) = ~g(b, a)
+ * ~f(a, b) = g(b, a)
+ * ~f(a, b) = ~h(a, b) where h is the contrapositive of g
+ * f(a, b) = h(a, b)
+ *
+ * Thus we define this function in pairs.
+ */
+
+static inline midgard_alu_op
+mir_contrapositive(midgard_alu_op op)
+{
+ switch (op) {
+ case midgard_alu_op_flt:
+ return midgard_alu_op_fle;
+ case midgard_alu_op_fle:
+ return midgard_alu_op_flt;
+
+ case midgard_alu_op_ilt:
+ return midgard_alu_op_ile;
+ case midgard_alu_op_ile:
+ return midgard_alu_op_ilt;
+
+ default:
+ unreachable("No known contrapositive");
+ }
+}
+
/* Midgard supports two types of constants, embedded constants (128-bit) and
* inline constants (16-bit). Sometimes, especially with scalar ops, embedded
* constants can be demoted to inline constants, for space savings and
int op = ins->alu.op;
if (ins->ssa_args.src0 == SSA_FIXED_REGISTER(REGISTER_CONSTANT)) {
+ bool flip = alu_opcode_props[op].props & OP_COMMUTES;
+
switch (op) {
- /* These ops require an operational change to flip
- * their arguments TODO */
+ /* Conditionals can be inverted */
case midgard_alu_op_flt:
- case midgard_alu_op_fle:
case midgard_alu_op_ilt:
+ case midgard_alu_op_fle:
case midgard_alu_op_ile:
+ ins->alu.op = mir_contrapositive(ins->alu.op);
+ ins->invert = true;
+ flip = true;
+ break;
+
case midgard_alu_op_fcsel:
case midgard_alu_op_icsel:
DBG("Missed non-commutative flip (%s)\n", alu_opcode_props[op].name);
break;
}
- if (alu_opcode_props[op].props & OP_COMMUTES) {
+ if (flip) {
/* Flip the SSA numbers */
ins->ssa_args.src0 = ins->ssa_args.src1;
ins->ssa_args.src1 = SSA_FIXED_REGISTER(REGISTER_CONSTANT);