i965/vec4: Eliminate writes that are never read.
authorMatt Turner <mattst88@gmail.com>
Tue, 11 Mar 2014 20:16:37 +0000 (13:16 -0700)
committerMatt Turner <mattst88@gmail.com>
Mon, 24 Mar 2014 18:06:26 +0000 (11:06 -0700)
With an awful O(n^2) algorithm that searches previous instructions for
dead writes.

total instructions in shared programs: 805582 -> 788074 (-2.17%)
instructions in affected programs:     144561 -> 127053 (-12.11%)

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

index 4ad398af90b7d7307bcfd554c7830e99339cb5cc..e9219a9aa5ef30baf315d038a7c313a26862e27b 100644 (file)
@@ -369,6 +369,7 @@ bool
 vec4_visitor::dead_code_eliminate()
 {
    bool progress = false;
+   bool seen_control_flow = false;
    int pc = -1;
 
    calculate_live_intervals();
@@ -378,6 +379,8 @@ vec4_visitor::dead_code_eliminate()
 
       pc++;
 
+      seen_control_flow = inst->is_control_flow() || seen_control_flow;
+
       if (inst->dst.file != GRF || inst->has_side_effects())
          continue;
 
@@ -393,6 +396,49 @@ vec4_visitor::dead_code_eliminate()
       }
 
       progress = try_eliminate_instruction(inst, write_mask) || progress;
+
+      if (seen_control_flow || inst->predicate || inst->prev == NULL)
+         continue;
+
+      int 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 j = 0; j < 4; j++) {
+            int swiz = BRW_GET_SWZ(inst->src[i].swizzle, j);
+            dead_channels &= ~(1 << swiz);
+         }
+      }
+
+      for (exec_node *node = inst->prev, *prev = node->prev;
+           prev != NULL && dead_channels != 0;
+           node = prev, prev = prev->prev) {
+         vec4_instruction *scan_inst = (vec4_instruction  *)node;
+
+         if (scan_inst->dst.file != GRF || scan_inst->has_side_effects())
+            continue;
+
+         if (inst->dst.reg == scan_inst->dst.reg) {
+            int new_writemask = scan_inst->dst.writemask & ~dead_channels;
+
+            progress = try_eliminate_instruction(scan_inst, new_writemask) ||
+                       progress;
+         }
+
+         for (int i = 0; i < 3; i++) {
+            if (scan_inst->src[i].file != GRF ||
+                scan_inst->src[i].reg != inst->dst.reg)
+               continue;
+
+            for (int j = 0; j < 4; j++) {
+               int swiz = BRW_GET_SWZ(scan_inst->src[i].swizzle, j);
+               dead_channels &= ~(1 << swiz);
+            }
+         }
+      }
    }
 
    if (progress)