diff options
author | Rob Clark <[email protected]> | 2018-01-29 15:59:55 -0500 |
---|---|---|
committer | Rob Clark <[email protected]> | 2018-02-10 14:54:58 -0500 |
commit | 76440fcca9150645c5d7a5396f902f42fd565937 (patch) | |
tree | e968e79697b33e464433a43156aca6b3ecbdc820 /src/gallium/drivers | |
parent | aea223741fa008c704e8bc66fe00bde05d51b2c7 (diff) |
freedreno/ir3: clean up dangling false-dep's
Maybe there is a better way for this.. where it comes useful is "array"
loads, which end up as a false-dep for a later array store.
If all the uses of an array load are CP'd into their consumer, it still
leaves the dangling array load, leading to funny things like:
mov.u32u32 r5.y, r0.y
mov.u32u32 r5.y, r0.z
Signed-off-by: Rob Clark <[email protected]>
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/freedreno/ir3/ir3_cp.c | 44 |
2 files changed, 46 insertions, 0 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h index 250d4672b6b..776239707c7 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3.h +++ b/src/gallium/drivers/freedreno/ir3/ir3.h @@ -360,6 +360,8 @@ struct ir3_instruction { /* Entry in ir3_block's instruction list: */ struct list_head node; + int use_count; /* currently just updated/used by cp */ + #ifdef DEBUG uint32_t serialno; #endif diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c index 11d39a4093e..7713c645e08 100644 --- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c +++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c @@ -309,6 +309,26 @@ lower_immed(struct ir3_cp_ctx *ctx, struct ir3_register *reg, unsigned new_flags return reg; } +static void +unuse(struct ir3_instruction *instr) +{ + debug_assert(instr->use_count > 0); + + if (--instr->use_count == 0) { + struct ir3_block *block = instr->block; + + instr->barrier_class = 0; + instr->barrier_conflict = 0; + + /* we don't want to remove anything in keeps (which could + * be things like array store's) + */ + for (unsigned i = 0; i < block->keeps_count; i++) { + debug_assert(block->keeps[i] != instr); + } + } +} + /** * Handle cp for a given src register. This additionally handles * the cases of collapsing immedate/const (which replace the src @@ -339,6 +359,8 @@ reg_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr, instr->barrier_class |= src->barrier_class; instr->barrier_conflict |= src->barrier_conflict; + + unuse(src); } } else if (is_same_type_mov(src) && @@ -558,6 +580,7 @@ instr_cp(struct ir3_cp_ctx *ctx, struct ir3_instruction *instr) instr->regs[2] = cond->regs[2]; instr->barrier_class |= cond->barrier_class; instr->barrier_conflict |= cond->barrier_conflict; + unuse(cond); break; default: break; @@ -573,6 +596,27 @@ ir3_cp(struct ir3 *ir, struct ir3_shader_variant *so) .so = so, }; + /* This is a bit annoying, and probably wouldn't be necessary if we + * tracked a reverse link from producing instruction to consumer. + * But we need to know when we've eliminated the last consumer of + * a mov, so we need to do a pass to first count consumers of a + * mov. + */ + list_for_each_entry (struct ir3_block, block, &ir->block_list, node) { + list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) { + struct ir3_instruction *src; + + /* by the way, we don't acount for false-dep's, so the CP + * pass should always happen before false-dep's are inserted + */ + debug_assert(instr->deps_count == 0); + + foreach_ssa_src(src, instr) { + src->use_count++; + } + } + } + ir3_clear_mark(ir); for (unsigned i = 0; i < ir->noutputs; i++) { |