i965/vs: Add support for copy propagation of the UNIFORM and ATTR files.
authorEric Anholt <eric@anholt.net>
Thu, 1 Sep 2011 23:21:14 +0000 (16:21 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 9 Sep 2011 04:40:39 +0000 (21:40 -0700)
Removes 2.0% of the instructions from 35.7% of vertex shaders in shader-db.

src/mesa/drivers/dri/i965/brw_vec4.cpp
src/mesa/drivers/dri/i965/brw_vec4.h
src/mesa/drivers/dri/i965/brw_vec4_copy_propagation.cpp

index 656589dee3a33fc09db3f7b65113d5b121d352e7..436de2fea8e9739a69c74fb00bad08e895b38f0e 100644 (file)
@@ -31,6 +31,19 @@ extern "C" {
 
 namespace brw {
 
+bool
+vec4_instruction::is_math()
+{
+   return (opcode == SHADER_OPCODE_RCP ||
+          opcode == SHADER_OPCODE_RSQ ||
+          opcode == SHADER_OPCODE_SQRT ||
+          opcode == SHADER_OPCODE_EXP2 ||
+          opcode == SHADER_OPCODE_LOG2 ||
+          opcode == SHADER_OPCODE_SIN ||
+          opcode == SHADER_OPCODE_COS ||
+          opcode == SHADER_OPCODE_POW);
+}
+
 bool
 src_reg::equals(src_reg *r)
 {
index 545e8f15a8da6ee751ea3466f2b670ea54466a9b..7739a151e4955b57463cc1f940647fabf2f7de5a 100644 (file)
@@ -275,6 +275,8 @@ public:
     */
    ir_instruction *ir;
    const char *annotation;
+
+   bool is_math();
 };
 
 class vec4_visitor : public ir_visitor
index 1e24e2e1ccc0d8186749bb915087be5c077bcb45..4b33df1f105b4f25e987b78fa0874735606cb0ca 100644 (file)
@@ -153,6 +153,61 @@ try_constant_propagation(vec4_instruction *inst, int arg, src_reg *values[4])
    return false;
 }
 
+static bool
+try_copy_propagation(struct intel_context *intel,
+                    vec4_instruction *inst, int arg, src_reg *values[4])
+{
+   /* For constant propagation, we only handle the same constant
+    * across all 4 channels.  Some day, we should handle the 8-bit
+    * float vector format, which would let us constant propagate
+    * vectors better.
+    */
+   src_reg value = *values[0];
+   for (int i = 1; i < 4; i++) {
+      /* This is equals() except we don't care about the swizzle. */
+      if (value.file != values[i]->file ||
+         value.reg != values[i]->reg ||
+         value.reg_offset != values[i]->reg_offset ||
+         value.type != values[i]->type ||
+         value.negate != values[i]->negate ||
+         value.abs != values[i]->abs) {
+        return false;
+      }
+   }
+
+   /* Compute the swizzle of the original register by swizzling the
+    * component loaded from each value according to the swizzle of
+    * operand we're going to change.
+    */
+   int s[4];
+   for (int i = 0; i < 4; i++) {
+      s[i] = BRW_GET_SWZ(values[i]->swizzle,
+                        BRW_GET_SWZ(inst->src[arg].swizzle, i));
+   }
+   value.swizzle = BRW_SWIZZLE4(s[0], s[1], s[2], s[3]);
+
+   if (value.file != UNIFORM &&
+       value.file != ATTR)
+      return false;
+
+   if (inst->src[arg].abs) {
+      value.negate = false;
+      value.abs = true;
+   }
+   if (inst->src[arg].negate)
+      value.negate = true;
+
+   /* FINISHME: We can't copy-propagate things that aren't normal
+    * vec8s into gen6 math instructions, because of the weird src
+    * handling for those instructions.  Just ignore them for now.
+    */
+   if (intel->gen >= 6 && inst->is_math())
+      return false;
+
+   inst->src[arg] = value;
+   return true;
+}
+
 bool
 vec4_visitor::opt_copy_propagation()
 {
@@ -216,7 +271,8 @@ vec4_visitor::opt_copy_propagation()
         if (c != 4)
            continue;
 
-        if (try_constant_propagation(inst, i, values))
+        if (try_constant_propagation(inst, i, values) ||
+            try_copy_propagation(intel, inst, i, values))
            progress = true;
       }