diff options
author | Rob Clark <[email protected]> | 2019-10-18 15:55:10 -0700 |
---|---|---|
committer | Rob Clark <[email protected]> | 2019-10-24 13:08:56 -0700 |
commit | bc67b892d010be71e264747a5ebbf975358dd7ea (patch) | |
tree | 42f766832119cb93a6aad68902545f99cb67a80b | |
parent | 97b24efd9f44590fe262c99d91f78f53d4da121b (diff) |
freedreno/ir3: handle the progress case
In some cases, in particular when you have things that can be src
modifiers ((abs)/(neg)), once eliminating one mov, there is a
possibility to remove another. Handle this by re-visiting an
instruction after eliminating a copy on one of it's srcs.
Signed-off-by: Rob Clark <[email protected]>
Reviewed-by: Kristian H. Kristensen <[email protected]>
-rw-r--r-- | src/freedreno/ir3/ir3_cp.c | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/src/freedreno/ir3/ir3_cp.c b/src/freedreno/ir3/ir3_cp.c index 16dd8583f39..fa25c9ca8a1 100644 --- a/src/freedreno/ir3/ir3_cp.c +++ b/src/freedreno/ir3/ir3_cp.c @@ -431,7 +431,7 @@ try_swap_mad_two_srcs(struct ir3_instruction *instr, unsigned new_flags) * src (which needs to also fixup the address src reference by the * instruction). */ -static void +static bool reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, struct ir3_register *reg, unsigned n) { @@ -457,8 +457,9 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, unuse(src); reg->instr->use_count++; - } + return true; + } } else if (is_same_type_mov(src) && /* cannot collapse const/immed/etc into meta instrs: */ !is_meta(instr)) { @@ -477,7 +478,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, debug_assert(new_flags & IR3_REG_IMMED); instr->regs[n + 1] = lower_immed(ctx, src_reg, new_flags, f_opcode); - return; + return true; } /* special case for "normal" mad instructions, we can @@ -488,10 +489,9 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, * src[0] is !CONST and src[1] is CONST: */ if ((n == 1) && try_swap_mad_two_srcs(instr, new_flags)) { - /* we swapped, so now we are dealing with 1st src: */ - n = 0; + return true; } else { - return; + return false; } } @@ -509,7 +509,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, */ if ((src_reg->flags & IR3_REG_RELATIV) && conflicts(instr->address, reg->instr->address)) - return; + return false; /* This seems to be a hw bug, or something where the timings * just somehow don't work out. This restriction may only @@ -518,7 +518,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, if ((opc_cat(instr->opc) == 3) && (n == 2) && (src_reg->flags & IR3_REG_RELATIV) && (src_reg->array.offset == 0)) - return; + return false; src_reg = ir3_reg_clone(instr->block->shader, src_reg); src_reg->flags = new_flags; @@ -527,7 +527,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, if (src_reg->flags & IR3_REG_RELATIV) ir3_instr_set_address(instr, reg->instr->address); - return; + return true; } if ((src_reg->flags & IR3_REG_RELATIV) && @@ -537,7 +537,7 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, instr->regs[n+1] = src_reg; ir3_instr_set_address(instr, reg->instr->address); - return; + return true; } /* NOTE: seems we can only do immed integers, so don't @@ -574,16 +574,21 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, src_reg->flags = new_flags; src_reg->iim_val = iim_val; instr->regs[n+1] = src_reg; + + return true; } else if (valid_flags(instr, n, (new_flags & ~IR3_REG_IMMED) | IR3_REG_CONST)) { bool f_opcode = (ir3_cat2_float(instr->opc) || ir3_cat3_float(instr->opc)) ? true : false; /* See if lowering an immediate to const would help. */ instr->regs[n+1] = lower_immed(ctx, src_reg, new_flags, f_opcode); + + return true; } - return; } } + + return false; } /* Handle special case of eliminating output mov, and similar cases where @@ -621,26 +626,30 @@ instr_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr) return; /* walk down the graph from each src: */ - foreach_src_n(reg, n, instr) { - struct ir3_instruction *src = ssa(reg); + bool progress; + do { + progress = false; + foreach_src_n(reg, n, instr) { + struct ir3_instruction *src = ssa(reg); - if (!src) - continue; + if (!src) + continue; - instr_cp(ctx, src); + instr_cp(ctx, src); - /* TODO non-indirect access we could figure out which register - * we actually want and allow cp.. - */ - if (reg->flags & IR3_REG_ARRAY) - continue; + /* TODO non-indirect access we could figure out which register + * we actually want and allow cp.. + */ + if (reg->flags & IR3_REG_ARRAY) + continue; - /* Don't CP absneg into meta instructions, that won't end well: */ - if (is_meta(instr) && (src->opc != OPC_MOV)) - continue; + /* Don't CP absneg into meta instructions, that won't end well: */ + if (is_meta(instr) && (src->opc != OPC_MOV)) + continue; - reg_cp(ctx, instr, reg, n); - } + progress |= reg_cp(ctx, instr, reg, n); + } + } while (progress); if (instr->regs[0]->flags & IR3_REG_ARRAY) { struct ir3_instruction *src = ssa(instr->regs[0]); |