summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_cp.c2
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_depth.c40
2 files changed, 31 insertions, 11 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
index 391e94ca44f..67a7714b9c5 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
@@ -607,7 +607,7 @@ ir3_cp(struct ir3 *ir, struct ir3_shader_variant *so)
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
+ /* by the way, we don't account for false-dep's, so the CP
* pass should always happen before false-dep's are inserted
*/
debug_assert(instr->deps_count == 0);
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_depth.c b/src/gallium/drivers/freedreno/ir3/ir3_depth.c
index 270d53dbed7..3ece13928f4 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_depth.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_depth.c
@@ -133,13 +133,18 @@ ir3_insert_by_depth(struct ir3_instruction *instr, struct list_head *list)
}
static void
-ir3_instr_depth(struct ir3_instruction *instr, unsigned boost)
+ir3_instr_depth(struct ir3_instruction *instr, unsigned boost, bool falsedep)
{
struct ir3_instruction *src;
/* if we've already visited this instruction, bail now: */
- if (ir3_instr_check_mark(instr))
+ if (falsedep) {
+ /* don't mark falsedep's as used, but process them normally: */
+ if (instr->flags & IR3_INSTR_MARK)
+ return;
+ } else if (ir3_instr_check_mark(instr)) {
return;
+ }
instr->depth = 0;
@@ -147,7 +152,7 @@ ir3_instr_depth(struct ir3_instruction *instr, unsigned boost)
unsigned sd;
/* visit child to compute it's depth: */
- ir3_instr_depth(src, boost);
+ ir3_instr_depth(src, boost, __is_false_dep(instr, i));
/* for array writes, no need to delay on previous write: */
if (i == 0)
@@ -165,9 +170,10 @@ ir3_instr_depth(struct ir3_instruction *instr, unsigned boost)
ir3_insert_by_depth(instr, &instr->block->instr_list);
}
-static void
+static bool
remove_unused_by_block(struct ir3_block *block)
{
+ bool progress = false;
list_for_each_entry_safe (struct ir3_instruction, instr, &block->instr_list, node) {
if (!ir3_instr_check_mark(instr)) {
if (instr->opc == OPC_END)
@@ -178,32 +184,35 @@ remove_unused_by_block(struct ir3_block *block)
instr->flags |= IR3_INSTR_UNUSED;
/* and remove from instruction list: */
list_delinit(&instr->node);
+ progress = true;
}
}
+ return progress;
}
-void
-ir3_depth(struct ir3 *ir)
+static bool
+compute_depth_and_remove_unused(struct ir3 *ir)
{
unsigned i;
+ bool progress = false;
ir3_clear_mark(ir);
for (i = 0; i < ir->noutputs; i++)
if (ir->outputs[i])
- ir3_instr_depth(ir->outputs[i], 0);
+ ir3_instr_depth(ir->outputs[i], 0, false);
list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
for (i = 0; i < block->keeps_count; i++)
- ir3_instr_depth(block->keeps[i], 0);
+ ir3_instr_depth(block->keeps[i], 0, false);
/* We also need to account for if-condition: */
if (block->condition)
- ir3_instr_depth(block->condition, 6);
+ ir3_instr_depth(block->condition, 6, false);
}
/* mark un-used instructions: */
list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
- remove_unused_by_block(block);
+ progress |= remove_unused_by_block(block);
}
/* note that we can end up with unused indirects, but we should
@@ -221,4 +230,15 @@ ir3_depth(struct ir3 *ir)
if (in && (in->flags & IR3_INSTR_UNUSED))
ir->inputs[i] = NULL;
}
+
+ return progress;
+}
+
+void
+ir3_depth(struct ir3 *ir)
+{
+ bool progress;
+ do {
+ progress = compute_depth_and_remove_unused(ir);
+ } while (progress);
}