i965/vec4: fix record clearing in copy propagation
authorChia-I Wu <olv@lunarg.com>
Mon, 7 Apr 2014 04:31:14 +0000 (12:31 +0800)
committerChia-I Wu <olvaffe@gmail.com>
Tue, 8 Apr 2014 13:04:22 +0000 (21:04 +0800)
Given

  mov vgrf7, vgrf9.xyxz
  add vgrf9.xyz, vgrf4.xyzw, vgrf5.xyzw
  add vgrf10.x, vgrf6.xyzw, vgrf7.wwww

the last instruction would be wrongly changed to

  add vgrf10.x, vgrf6.xyzw, vgrf9.zzzz

during copy propagation.

The issue is that when deciding if a record should be cleared, the old code
checked for

  inst->dst.writemask & (1 << ch)

instead of

  inst->dst.writemask & (1 << BRW_GET_SWZ(src->swizzle, ch))

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=76749
Signed-off-by: Chia-I Wu <olv@lunarg.com>
Cc: Jordan Justen <jljusten@gmail.com>
Cc: Matt Turner <mattst88@gmail.com>
Reviewed-by: Ian Romainck <ian.d.romanick@intel.com>
Reviewed-by: Eric Anholt <eric@anholt.net>
Cc: "10.1" <mesa-stable@freedesktop.org>
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp

index 3d68f0ed5d43db4fc5d6cee9adef31e1a599557b..83cf19114bed9fd5817264ab1c7aa94f62d051e9 100644 (file)
@@ -57,6 +57,21 @@ is_dominated_by_previous_instruction(vec4_instruction *inst)
           inst->opcode != BRW_OPCODE_ENDIF);
 }
 
+static bool
+is_channel_updated(vec4_instruction *inst, src_reg *values[4], int ch)
+{
+   const src_reg *src = values[ch];
+
+   /* consider GRF only */
+   assert(inst->dst.file == GRF);
+   if (!src || src->file != GRF)
+      return false;
+
+   return (src->reg == inst->dst.reg &&
+          src->reg_offset == inst->dst.reg_offset &&
+          inst->dst.writemask & (1 << BRW_GET_SWZ(src->swizzle, ch)));
+}
+
 static bool
 try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
 {
@@ -357,11 +372,7 @@ vec4_visitor::opt_copy_propagation()
         else {
            for (int i = 0; i < virtual_grf_reg_count; i++) {
               for (int j = 0; j < 4; j++) {
-                 if (inst->dst.writemask & (1 << j) &&
-                     cur_value[i][j] &&
-                     cur_value[i][j]->file == GRF &&
-                     cur_value[i][j]->reg == inst->dst.reg &&
-                     cur_value[i][j]->reg_offset == inst->dst.reg_offset) {
+                 if (is_channel_updated(inst, cur_value[i], j)){
                     cur_value[i][j] = NULL;
                  }
               }