/* Now that booleans are lowered, we can run out late opts */
NIR_PASS(progress, nir, midgard_nir_lower_algebraic_late);
+ NIR_PASS(progress, nir, midgard_nir_cancel_inot);
NIR_PASS(progress, nir, nir_copy_prop);
NIR_PASS(progress, nir, nir_opt_dce);
}
}
+/* Compare mir_lower_invert */
+static bool
+nir_accepts_inot(nir_op op, unsigned src)
+{
+ switch (op) {
+ case nir_op_ior:
+ case nir_op_iand:
+ case nir_op_ixor:
+ return true;
+ case nir_op_b32csel:
+ /* Only the condition */
+ return (src == 0);
+ default:
+ return false;
+ }
+}
+
static void
-mir_copy_src(midgard_instruction *ins, nir_alu_instr *instr, unsigned i, unsigned to, bool *abs, bool *neg, bool is_int, unsigned bcast_count)
+mir_copy_src(midgard_instruction *ins, nir_alu_instr *instr, unsigned i, unsigned to, bool *abs, bool *neg, bool *not, bool is_int, unsigned bcast_count)
{
nir_alu_src src = instr->src[i];
*abs = true;
}
+ if (nir_accepts_inot(instr->op, i) && pan_has_source_mod(&src, nir_op_inot))
+ *not = true;
+
unsigned bits = nir_src_bit_size(src.src);
ins->src[to] = nir_src_index(NULL, &src.src);
ALU_CASE(fsin, fsin);
ALU_CASE(fcos, fcos);
- /* We'll set invert */
- ALU_CASE(inot, imov);
+ /* We'll get 0 in the second arg, so:
+ * ~a = ~(a | 0) = nor(a, 0) */
+ ALU_CASE(inot, inor);
ALU_CASE(iand, iand);
ALU_CASE(ior, ior);
ALU_CASE(ixor, ixor);
if (quirk_flipped_r24) {
ins.src[0] = ~0;
- mir_copy_src(&ins, instr, 0, 1, &abs[1], &neg[1], is_int, broadcast_swizzle);
+ mir_copy_src(&ins, instr, 0, 1, &abs[1], &neg[1], &ins.src_invert[1], is_int, broadcast_swizzle);
} else {
for (unsigned i = 0; i < nr_inputs; ++i) {
unsigned to = i;
if (i == 0)
to = 2;
+ else if (flip_src12)
+ to = 2 - i;
else
to = i - 1;
} else if (flip_src12) {
to = 1 - to;
}
- mir_copy_src(&ins, instr, i, to, &abs[to], &neg[to], is_int, broadcast_swizzle);
+ mir_copy_src(&ins, instr, i, to, &abs[to], &neg[to], &ins.src_invert[to], is_int, broadcast_swizzle);
+
+ /* (!c) ? a : b = c ? b : a */
+ if (instr->op == nir_op_b32csel && ins.src_invert[2]) {
+ ins.src_invert[2] = false;
+ flip_src12 ^= true;
+ }
}
}
ins.alu = alu;
+ /* Arrange for creation of iandnot/iornot */
+ if (ins.src_invert[0] && !ins.src_invert[1]) {
+ mir_flip(&ins);
+ ins.src_invert[0] = false;
+ ins.src_invert[1] = true;
+ }
+
/* Late fixup for emulated instructions */
if (instr->op == nir_op_b2f32 || instr->op == nir_op_b2i32) {
for (unsigned c = 0; c < 16; ++c)
ins.swizzle[1][c] = 0;
- } else if (instr->op == nir_op_inot) {
- ins.invert = true;
}
if ((opcode_props & UNITS_ALL) == UNIT_VLUT) {
progress |= midgard_opt_dead_code_eliminate(ctx, block);
progress |= midgard_opt_combine_projection(ctx, block);
progress |= midgard_opt_varying_projection(ctx, block);
+#if 0
progress |= midgard_opt_not_propagate(ctx, block);
progress |= midgard_opt_fuse_src_invert(ctx, block);
progress |= midgard_opt_fuse_dest_invert(ctx, block);
progress |= midgard_opt_csel_invert(ctx, block);
progress |= midgard_opt_drop_cmp_invert(ctx, block);
progress |= midgard_opt_invert_branch(ctx, block);
+#endif
}
} while (progress);
mir_foreach_block(ctx, _block) {
midgard_block *block = (midgard_block *) _block;
- midgard_lower_invert(ctx, block);
+ //midgard_lower_invert(ctx, block);
midgard_lower_derivatives(ctx, block);
}
ins->load_store.mask = packed;
}
+static void
+mir_lower_inverts(midgard_instruction *ins)
+{
+ bool inv[3] = {
+ ins->src_invert[0],
+ ins->src_invert[1],
+ ins->src_invert[2]
+ };
+
+ switch (ins->alu.op) {
+ case midgard_alu_op_iand:
+ /* a & ~b = iandnot(a, b) */
+ /* ~a & ~b = ~(a | b) = inor(a, b) */
+
+ if (inv[0] && inv[1])
+ ins->alu.op = midgard_alu_op_inor;
+ else if (inv[1])
+ ins->alu.op = midgard_alu_op_iandnot;
+
+ break;
+ case midgard_alu_op_ior:
+ /* a | ~b = iornot(a, b) */
+ /* ~a | ~b = ~(a & b) = inand(a, b) */
+
+ if (inv[0] && inv[1])
+ ins->alu.op = midgard_alu_op_inand;
+ else if (inv[1])
+ ins->alu.op = midgard_alu_op_iornot;
+
+ break;
+
+ case midgard_alu_op_ixor:
+ /* ~a ^ b = a ^ ~b = ~(a ^ b) = inxor(a, b) */
+ /* ~a ^ ~b = a ^ b */
+
+ if (inv[0] ^ inv[1])
+ ins->alu.op = midgard_alu_op_inxor;
+
+ break;
+
+ default:
+ break;
+ }
+}
+
static void
emit_alu_bundle(compiler_context *ctx,
midgard_bundle *bundle,
/* In case we demote to a scalar */
midgard_scalar_alu scalarized;
+ if (!ins->compact_branch)
+ mir_lower_inverts(ins);
+
if (ins->unit & UNITS_ANY_VECTOR) {
mir_pack_mask_alu(ins);
mir_pack_swizzle_alu(ins);