i965/fs: Fix a bug in register coalesce
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 16 Sep 2014 23:34:23 +0000 (16:34 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 30 Sep 2014 17:29:14 +0000 (10:29 -0700)
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 <jason.ekstrand@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
src/mesa/drivers/dri/i965/brw_fs_register_coalesce.cpp

index 9546dcdf06a8767162c9216b5af018b3be667e28..69d105a85c93774d7bfb0e7401485112fdff1246 100644 (file)
@@ -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;