From f94f22e87a64dcaaafba3e1a0d160385adce4807 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 30 Aug 2019 14:28:01 -0700 Subject: [PATCH] freedreno/ir3: fix mad copy propagation special case After the next patch enabling copy propagation for relative sources, we'll need to dereference the n'th src in valid_flags(), so we actually need to swap the sources before calling valid_flags(). But the logic was already a bit cumbersome, so move it into a helper function. Signed-off-by: Rob Clark Reviewed-by: Eric Anholt --- src/freedreno/ir3/ir3_cp.c | 44 ++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c index 9bd97b690e3..3039e50c3e4 100644 --- a/src/freedreno/ir3/ir3_cp.c +++ b/src/freedreno/ir3/ir3_cp.c @@ -32,6 +32,9 @@ #include "ir3_compiler.h" #include "ir3_shader.h" +#define swap(a, b) \ + do { __typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + /* * Copy Propagate: */ @@ -360,6 +363,36 @@ unuse(struct ir3_instruction *instr) } } +/** + * Handles the special case of the 2nd src (n == 1) to "normal" mad + * instructions, which cannot reference a constant. See if it is + * possible to swap the 1st and 2nd sources. + */ +static bool +try_swap_mad_two_srcs(struct ir3_instruction *instr, unsigned new_flags) +{ + if (!is_mad(instr->opc)) + return false; + + /* NOTE: pre-swap first two src's before valid_flags(), + * which might try to dereference the n'th src: + */ + swap(instr->regs[0 + 1], instr->regs[1 + 1]); + + bool valid_swap = + /* can we propagate mov if we move 2nd src to first? */ + valid_flags(instr, 0, new_flags) && + /* and does first src fit in second slot? */ + valid_flags(instr, 1, instr->regs[1 + 1]->flags); + + if (!valid_swap) { + /* put things back the way they were: */ + swap(instr->regs[0 + 1], instr->regs[1 + 1]); + } /* otherwise leave things swapped */ + + return valid_swap; +} + /** * Handle cp for a given src register. This additionally handles * the cases of collapsing immedate/const (which replace the src @@ -423,15 +456,8 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, * src prior to multiply) can swap their first two srcs if * src[0] is !CONST and src[1] is CONST: */ - if ((n == 1) && is_mad(instr->opc) && - !(instr->regs[0 + 1]->flags & (IR3_REG_CONST | IR3_REG_RELATIV)) && - valid_flags(instr, 0, new_flags & ~IR3_REG_IMMED)) { - /* swap src[0] and src[1]: */ - struct ir3_register *tmp; - tmp = instr->regs[0 + 1]; - instr->regs[0 + 1] = instr->regs[1 + 1]; - instr->regs[1 + 1] = tmp; - + if ((n == 1) && try_swap_mad_two_srcs(instr, new_flags)) { + /* we swapped, so now we are dealing with 1st src: */ n = 0; } else { return; -- 2.30.2