summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2012-09-05 22:10:41 -0700
committerEric Anholt <[email protected]>2012-09-07 08:29:49 -0700
commit39aca5076fa0e31d418b481167063933f5f7b74f (patch)
tree44109012ed799508e535331ec349458a2246d63e
parent7b3fe776e2950d1cbaadc2fe69eb43b102a84ba9 (diff)
i965: Fix virtual_grf_interferes() between calculate_live_intervals() and DCE.
This fixes the blue zombies bug in l4d2. NOTE: This is a candidate for the 9.0 branch. Reviewed-by: Kenneth Graunke <[email protected]>
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp24
1 files changed, 24 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp b/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
index 16480ad8a90..392691dd47e 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_live_variables.cpp
@@ -221,6 +221,30 @@ fs_visitor::calculate_live_intervals()
}
this->live_intervals_valid = true;
+
+ /* Note in the non-control-flow code above, that we only take def[] as the
+ * first store, and use[] as the last use. We use this in dead code
+ * elimination, to determine when a store never gets used. However, we
+ * also use these arrays to answer the virtual_grf_interferes() question
+ * (live interval analysis), which is used for register coalescing and
+ * register allocation.
+ *
+ * So, there's a conflict over what the array should mean: if use[]
+ * considers a def after the last use, then the dead code elimination pass
+ * never does anything (and it's an important pass!). But if we don't
+ * include dead code, then virtual_grf_interferes() lies and we'll do
+ * horrible things like coalesce the register that is dead-code-written
+ * into another register that was live across the dead write (causing the
+ * use of the second register to take the dead write's source value instead
+ * of the coalesced MOV's source value).
+ *
+ * To resolve the conflict, immediately after calculating live intervals,
+ * detect dead code, nuke it, and if we changed anything, calculate again
+ * before returning to the caller. Now we happen to produce def[] and
+ * use[] arrays that will work for virtual_grf_interferes().
+ */
+ if (dead_code_eliminate())
+ calculate_live_intervals();
}
bool