aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/panfrost/midgard/compiler.h1
-rw-r--r--src/panfrost/midgard/midgard_compile.c1
-rw-r--r--src/panfrost/midgard/midgard_opt_invert.c55
3 files changed, 57 insertions, 0 deletions
diff --git a/src/panfrost/midgard/compiler.h b/src/panfrost/midgard/compiler.h
index f428db3123d..b5231f3075b 100644
--- a/src/panfrost/midgard/compiler.h
+++ b/src/panfrost/midgard/compiler.h
@@ -576,5 +576,6 @@ bool midgard_opt_dead_move_eliminate(compiler_context *ctx, midgard_block *block
void midgard_opt_post_move_eliminate(compiler_context *ctx, midgard_block *block, struct ra_graph *g);
void midgard_lower_invert(compiler_context *ctx, midgard_block *block);
+bool midgard_opt_fuse_dest_invert(compiler_context *ctx, midgard_block *block);
#endif
diff --git a/src/panfrost/midgard/midgard_compile.c b/src/panfrost/midgard/midgard_compile.c
index a35b43faee7..f0b3dde2754 100644
--- a/src/panfrost/midgard/midgard_compile.c
+++ b/src/panfrost/midgard/midgard_compile.c
@@ -2357,6 +2357,7 @@ midgard_compile_shader_nir(struct midgard_screen *screen, nir_shader *nir, midga
progress |= midgard_opt_dead_code_eliminate(ctx, block);
progress |= midgard_opt_combine_projection(ctx, block);
progress |= midgard_opt_varying_projection(ctx, block);
+ progress |= midgard_opt_fuse_dest_invert(ctx, block);
}
} while (progress);
diff --git a/src/panfrost/midgard/midgard_opt_invert.c b/src/panfrost/midgard/midgard_opt_invert.c
index 1e6c5b383ea..aab64a3c3b5 100644
--- a/src/panfrost/midgard/midgard_opt_invert.c
+++ b/src/panfrost/midgard/midgard_opt_invert.c
@@ -62,3 +62,58 @@ midgard_lower_invert(compiler_context *ctx, midgard_block *block)
mir_insert_instruction_before(mir_next_op(ins), not);
}
}
+
+/* With that lowering out of the way, we can focus on more interesting
+ * optimizations. One easy one is fusing inverts into bitwise operations:
+ *
+ * ~iand = inand
+ * ~ior = inor
+ * ~ixor = inxor
+ */
+
+static bool
+mir_is_bitwise(midgard_instruction *ins)
+{
+ switch (ins->alu.op) {
+ case midgard_alu_op_iand:
+ case midgard_alu_op_ior:
+ case midgard_alu_op_ixor:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static midgard_alu_op
+mir_invert_op(midgard_alu_op op)
+{
+ switch (op) {
+ case midgard_alu_op_iand:
+ return midgard_alu_op_inand;
+ case midgard_alu_op_ior:
+ return midgard_alu_op_inor;
+ case midgard_alu_op_ixor:
+ return midgard_alu_op_inxor;
+ default:
+ unreachable("Op not invertible");
+ }
+}
+
+bool
+midgard_opt_fuse_dest_invert(compiler_context *ctx, midgard_block *block)
+{
+ bool progress = false;
+
+ mir_foreach_instr_in_block_safe(block, ins) {
+ /* Search for inverted bitwise */
+ if (ins->type != TAG_ALU_4) continue;
+ if (!mir_is_bitwise(ins)) continue;
+ if (!ins->invert) continue;
+
+ ins->alu.op = mir_invert_op(ins->alu.op);
+ ins->invert = false;
+ progress |= true;
+ }
+
+ return progress;
+}