From 6318e461416feacd352b611fd28e698dd654c6a4 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Fri, 12 Jun 2020 17:24:02 -0400 Subject: [PATCH] pan/mdg: Allow scheduling "x + x" to multipliers One of the neat things with Midgard's wacky VLIW... on VADD/SADD this is (x + x) literally, on VMUL/SMUL/VLUT this is (x * 2.0) where the 2.0 is exactly representable in FP16 so it fits nicely as an inline constant. So we don't need to restrict its scheduling. Signed-off-by: Alyssa Rosenzweig Part-of: --- src/panfrost/midgard/midgard_schedule.c | 53 +++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/panfrost/midgard/midgard_schedule.c b/src/panfrost/midgard/midgard_schedule.c index 5a12d11045e..7ebcc2d4ebb 100644 --- a/src/panfrost/midgard/midgard_schedule.c +++ b/src/panfrost/midgard/midgard_schedule.c @@ -26,6 +26,7 @@ #include "midgard_quirks.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/half_float.h" /* Scheduling for Midgard is complicated, to say the least. ALU instructions * must be grouped into VLIW bundles according to following model: @@ -508,12 +509,61 @@ mir_pipeline_count(midgard_instruction *ins) return DIV_ROUND_UP(bytecount, 16); } +/* Matches FADD x, x with modifiers compatible. Since x + x = x * 2, for + * any x including of the form f(y) for some swizzle/abs/neg function f */ + +static bool +mir_is_add_2(midgard_instruction *ins) +{ + if (ins->alu.op != midgard_alu_op_fadd) + return false; + + if (ins->src[0] != ins->src[1]) + return false; + + if (ins->src_types[0] != ins->src_types[1]) + return false; + + for (unsigned i = 0; i < MIR_VEC_COMPONENTS; ++i) { + if (ins->swizzle[0][i] != ins->swizzle[1][i]) + return false; + } + + if (ins->src_abs[0] != ins->src_abs[1]) + return false; + + if (ins->src_neg[0] != ins->src_neg[1]) + return false; + + return true; +} + +static void +mir_adjust_unit(midgard_instruction *ins, unsigned unit) +{ + /* FADD x, x = FMUL x, #2 */ + if (mir_is_add_2(ins) && (unit & (UNITS_MUL | UNIT_VLUT))) { + ins->alu.op = midgard_alu_op_fmul; + + ins->src[1] = ~0; + ins->src_abs[1] = false; + ins->src_neg[1] = false; + + ins->has_inline_constant = true; + ins->inline_constant = _mesa_float_to_half(2.0); + } +} + static unsigned mir_has_unit(midgard_instruction *ins, unsigned unit) { if (alu_opcode_props[ins->alu.op].props & unit) return true; + /* FADD x, x can run on any adder or any multiplier */ + if (mir_is_add_2(ins)) + return true; + return false; } @@ -616,6 +666,9 @@ mir_choose_instruction( if (ldst) predicate->pipeline_count += mir_pipeline_count(instructions[best_index]); + if (alu) + mir_adjust_unit(instructions[best_index], unit); + /* Once we schedule a conditional, we can't again */ predicate->no_cond |= best_conditional; } -- 2.30.2