i965/vec4: Eliminate dead writes to the flag register.
authorMatt Turner <mattst88@gmail.com>
Wed, 19 Mar 2014 02:19:02 +0000 (19:19 -0700)
committerMatt Turner <mattst88@gmail.com>
Mon, 24 Mar 2014 18:06:26 +0000 (11:06 -0700)
For each write, search previous instructions for unread writes to the
flag register and remove them. Note that this will not eliminate the
last unread write.

total instructions in shared programs: 788074 -> 788004 (-0.01%)
instructions in affected programs:     4930 -> 4860 (-1.42%)

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_vec4.cpp

index e9219a9aa5ef30baf315d038a7c313a26862e27b..4ae60208f2cac17609fb8e67e8b0a076f7a50f7a 100644 (file)
@@ -381,35 +381,53 @@ vec4_visitor::dead_code_eliminate()
 
       seen_control_flow = inst->is_control_flow() || seen_control_flow;
 
-      if (inst->dst.file != GRF || inst->has_side_effects())
+      if (inst->has_side_effects())
          continue;
 
-      int write_mask = inst->dst.writemask;
+      bool inst_writes_flag = false;
+      if (inst->dst.file != GRF) {
+         if (inst->dst.is_null() && inst->writes_flag()) {
+            inst_writes_flag = true;
+         } else {
+            continue;
+         }
+      }
 
-      for (int c = 0; c < 4; c++) {
-         if (write_mask & (1 << c)) {
-            assert(this->virtual_grf_end[inst->dst.reg * 4 + c] >= pc);
-            if (this->virtual_grf_end[inst->dst.reg * 4 + c] == pc) {
-               write_mask &= ~(1 << c);
+      if (inst->dst.file == GRF) {
+         int write_mask = inst->dst.writemask;
+
+         for (int c = 0; c < 4; c++) {
+            if (write_mask & (1 << c)) {
+               assert(this->virtual_grf_end[inst->dst.reg * 4 + c] >= pc);
+               if (this->virtual_grf_end[inst->dst.reg * 4 + c] == pc) {
+                  write_mask &= ~(1 << c);
+               }
             }
          }
-      }
 
-      progress = try_eliminate_instruction(inst, write_mask) || progress;
+         progress = try_eliminate_instruction(inst, write_mask) || progress;
+      }
 
       if (seen_control_flow || inst->predicate || inst->prev == NULL)
          continue;
 
-      int dead_channels = inst->dst.writemask;
+      int dead_channels;
+      if (inst_writes_flag) {
+/* Arbitrarily chosen, other than not being an xyzw writemask. */
+#define FLAG_WRITEMASK (1 << 5)
+         dead_channels = inst->reads_flag() ? 0 : FLAG_WRITEMASK;
+      } else {
+         dead_channels = inst->dst.writemask;
 
-      for (int i = 0; i < 3; i++) {
-         if (inst->src[i].file != GRF ||
-             inst->src[i].reg != inst->dst.reg)
-               continue;
+         for (int i = 0; i < 3; i++) {
+            if (inst->src[i].file != GRF ||
+                inst->src[i].reg != inst->dst.reg)
+                  continue;
 
-         for (int j = 0; j < 4; j++) {
-            int swiz = BRW_GET_SWZ(inst->src[i].swizzle, j);
-            dead_channels &= ~(1 << swiz);
+            for (int j = 0; j < 4; j++) {
+               int swiz = BRW_GET_SWZ(inst->src[i].swizzle, j);
+               dead_channels &= ~(1 << swiz);
+            }
          }
       }
 
@@ -418,9 +436,21 @@ vec4_visitor::dead_code_eliminate()
            node = prev, prev = prev->prev) {
          vec4_instruction *scan_inst = (vec4_instruction  *)node;
 
-         if (scan_inst->dst.file != GRF || scan_inst->has_side_effects())
+         if (scan_inst->has_side_effects())
             continue;
 
+         if (inst_writes_flag) {
+            if (scan_inst->dst.is_null() && scan_inst->writes_flag()) {
+               scan_inst->remove();
+               progress = true;
+            } else if (scan_inst->reads_flag()) {
+               dead_channels = 0;
+            }
+            continue;
+         } else if (scan_inst->dst.file != GRF) {
+            continue;
+         }
+
          if (inst->dst.reg == scan_inst->dst.reg) {
             int new_writemask = scan_inst->dst.writemask & ~dead_channels;