summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Clark <[email protected]>2018-01-29 15:59:55 -0500
committerRob Clark <[email protected]>2018-02-10 14:54:58 -0500
commit76440fcca9150645c5d7a5396f902f42fd565937 (patch)
treee968e79697b33e464433a43156aca6b3ecbdc820
parentaea223741fa008c704e8bc66fe00bde05d51b2c7 (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]>
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.h2
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_cp.c44
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++) {