summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <robdclark@gmail.com>2018-04-02 10:47:23 -0400
committerRob Clark <robdclark@gmail.com>2018-04-03 06:08:56 -0400
commit91f9450b3222469d93c270b8ca5fb4bf2ef584f2 (patch)
treef116835d71b69b7cffb9212b2ff1322388cd3a1e
parent7e9b7ec094500f1245eed518592f99244e54a753 (diff)
freedreno/ir3: fix fallout of unused false-depth elimination
Since we were MARK flag for both preventing loops, and tracking whether instructions were used, we could end up in an infinite loop due to bd2ca2bcdd. Instead invert the logic.. mark all instructions UNUSED up front and clear the flag as we visit them. Fixes: bd2ca2bcdd freedreno/ir3: eliminate unused false-deps Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3.h1
-rw-r--r--src/gallium/drivers/freedreno/ir3/ir3_depth.c35
2 files changed, 19 insertions, 17 deletions
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h
index 500faa85377..1152ea300b1 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.h
+++ b/src/gallium/drivers/freedreno/ir3/ir3.h
@@ -762,7 +762,6 @@ static inline bool writes_pred(struct ir3_instruction *instr)
static inline struct ir3_instruction *ssa(struct ir3_register *reg)
{
if (reg->flags & (IR3_REG_SSA | IR3_REG_ARRAY)) {
- debug_assert(!(reg->instr && (reg->instr->flags & IR3_INSTR_UNUSED)));
return reg->instr;
}
return NULL;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_depth.c b/src/gallium/drivers/freedreno/ir3/ir3_depth.c
index 3ece13928f4..18795f77eb9 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_depth.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_depth.c
@@ -137,14 +137,12 @@ 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 (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)) {
+ /* don't mark falsedep's as used, but otherwise process them normally: */
+ if (!falsedep)
+ instr->flags &= ~IR3_INSTR_UNUSED;
+
+ if (ir3_instr_check_mark(instr))
return;
- }
instr->depth = 0;
@@ -175,14 +173,9 @@ 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)
- continue;
- /* mark it, in case it is input, so we can
- * remove unused inputs:
- */
- instr->flags |= IR3_INSTR_UNUSED;
- /* and remove from instruction list: */
+ if (instr->opc == OPC_END)
+ continue;
+ if (instr->flags & IR3_INSTR_UNUSED) {
list_delinit(&instr->node);
progress = true;
}
@@ -197,6 +190,16 @@ compute_depth_and_remove_unused(struct ir3 *ir)
bool progress = false;
ir3_clear_mark(ir);
+
+ /* initially mark everything as unused, we'll clear the flag as we
+ * visit the instructions:
+ */
+ list_for_each_entry (struct ir3_block, block, &ir->block_list, node) {
+ list_for_each_entry (struct ir3_instruction, instr, &block->instr_list, node) {
+ instr->flags |= IR3_INSTR_UNUSED;
+ }
+ }
+
for (i = 0; i < ir->noutputs; i++)
if (ir->outputs[i])
ir3_instr_depth(ir->outputs[i], 0, false);
@@ -220,7 +223,7 @@ compute_depth_and_remove_unused(struct ir3 *ir)
*/
for (i = 0; i < ir->indirects_count; i++) {
struct ir3_instruction *instr = ir->indirects[i];
- if (instr->flags & IR3_INSTR_UNUSED)
+ if (instr && (instr->flags & IR3_INSTR_UNUSED))
ir->indirects[i] = NULL;
}