summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2014-09-16 16:34:23 -0700
committerJason Ekstrand <[email protected]>2014-09-30 10:29:14 -0700
commit27d7ef094a55d6aeac22a11f20a9e819af4dd633 (patch)
tree83efd32a1f697f6d2e37dcd76d9fa618524ccb70 /src
parent16819b48ab0af244ccb5ef466a7343b1982792be (diff)
i965/fs: Fix a bug in register coalesce
This commit fixes a bug in register coalesce that happens when one register is moved to another the proper number of times but the channels are re-arranged. When this happens, the previous code would happily coalesce the registers regardless of the fact that the channel mappins were wrong. Signed-off-by: Jason Ekstrand <[email protected]> Reviewed-by: Matt Turner <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp b/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
index 9546dcdf06a..69d105a85c9 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp
@@ -200,6 +200,16 @@ fs_visitor::register_coalesce()
channels_remaining -= inst->regs_written;
} else {
const int offset = inst->src[0].reg_offset;
+ if (mov[offset]) {
+ /* This is the second time that this offset in the register has
+ * been set. This means, in particular, that inst->dst was
+ * live before this instruction and that the live ranges of
+ * inst->dst and inst->src[0] overlap and we can't coalesce the
+ * two variables. Let's ensure that doesn't happen.
+ */
+ channels_remaining = -1;
+ continue;
+ }
reg_to_offset[offset] = inst->dst.reg_offset;
if (inst->src[0].width == 16)
reg_to_offset[offset + 1] = inst->dst.reg_offset + 1;
@@ -212,6 +222,13 @@ fs_visitor::register_coalesce()
bool can_coalesce = true;
for (int i = 0; i < src_size; i++) {
+ if (reg_to_offset[i] != reg_to_offset[0] + i) {
+ /* Registers are out-of-order. */
+ can_coalesce = false;
+ reg_from = -1;
+ break;
+ }
+
var_to[i] = live_intervals->var_from_vgrf[reg_to] + reg_to_offset[i];
var_from[i] = live_intervals->var_from_vgrf[reg_from] + i;