i965/vec4: Add ability to reswizzle arbitrary swizzles.
authorMatt Turner <mattst88@gmail.com>
Sun, 31 Aug 2014 18:27:40 +0000 (11:27 -0700)
committerMatt Turner <mattst88@gmail.com>
Fri, 5 Sep 2014 17:22:06 +0000 (10:22 -0700)
Before commit 04895f5c we would only reswizzle dot product instructions
(since they wrote the same value into all channels, and we didn't have
to think about anything else). That commit extended reswizzling to cases
when the swizzle was single valued -- i.e., writing the same result into
all channels.

But allowing reswizzling of arbitrary things is actually really easy and
is even less code. (Why didn't we do this in the first place?!)

total instructions in shared programs: 4266079 -> 4261000 (-0.12%)
instructions in affected programs:     351933 -> 346854 (-1.44%)

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_vec4.cpp

index dcfa5940f9a1fb55e66d32ca33cfa158cd00e742..3ace1bdf5f578735f1f1744d933b457b0451fc6d 100644 (file)
@@ -943,30 +943,10 @@ vec4_instruction::can_reswizzle(int dst_writemask,
    if (dst.writemask & ~swizzle_mask)
       return false;
 
-   switch (opcode) {
-   default:
-      if (!brw_is_single_value_swizzle(swizzle)) {
-         /* Check if there happens to be no reswizzling required. */
-         for (int c = 0; c < 4; c++) {
-            int bit = 1 << BRW_GET_SWZ(swizzle, c);
-            /* Skip components of the swizzle not used by the dst. */
-            if (!(dst_writemask & (1 << c)))
-               continue;
+   if (inst->mlen > 0)
+      return false;
 
-            /* We don't do the reswizzling yet, so just sanity check that we
-             * don't have to.
-             */
-            if (bit != (1 << c))
-               return false;
-         }
-         return true;
-      }
-      /* fallthrough */
-   case BRW_OPCODE_DP4:
-   case BRW_OPCODE_DP3:
-   case BRW_OPCODE_DP2:
-      return true;
-   }
+   return true;
 }
 
 /**
@@ -982,22 +962,9 @@ vec4_instruction::reswizzle(int dst_writemask, int swizzle)
    int new_writemask = 0;
    int new_swizzle[4] = { 0 };
 
-   switch (opcode) {
-   default:
-      if (!brw_is_single_value_swizzle(swizzle)) {
-         for (int c = 0; c < 4; c++) {
-            /* Skip components of the swizzle not used by the dst. */
-            if (!(dst_writemask & (1 << c)))
-               continue;
-
-            /* We don't do the reswizzling yet, so just sanity check that we
-             * don't have to.
-             */
-            assert((1 << BRW_GET_SWZ(swizzle, c)) == (1 << c));
-         }
-         break;
-      }
-
+   /* Dot product instructions write a single result into all channels. */
+   if (opcode != BRW_OPCODE_DP4 && opcode != BRW_OPCODE_DPH &&
+       opcode != BRW_OPCODE_DP3 && opcode != BRW_OPCODE_DP2) {
       for (int i = 0; i < 3; i++) {
          if (src[i].file == BAD_FILE || src[i].file == IMM)
             continue;
@@ -1009,25 +976,20 @@ vec4_instruction::reswizzle(int dst_writemask, int swizzle)
          src[i].swizzle = BRW_SWIZZLE4(new_swizzle[0], new_swizzle[1],
                                        new_swizzle[2], new_swizzle[3]);
       }
+   }
 
-      /* fallthrough */
-   case BRW_OPCODE_DP4:
-   case BRW_OPCODE_DP3:
-   case BRW_OPCODE_DP2:
-      for (int c = 0; c < 4; c++) {
-         int bit = 1 << BRW_GET_SWZ(swizzle, c);
-         /* Skip components of the swizzle not used by the dst. */
-         if (!(dst_writemask & (1 << c)))
-            continue;
-         /* If we were populating this component, then populate the
-          * corresponding channel of the new dst.
-          */
-         if (dst.writemask & bit)
-            new_writemask |= (1 << c);
-      }
-      dst.writemask = new_writemask;
-      break;
+   for (int c = 0; c < 4; c++) {
+      int bit = 1 << BRW_GET_SWZ(swizzle, c);
+      /* Skip components of the swizzle not used by the dst. */
+      if (!(dst_writemask & (1 << c)))
+         continue;
+      /* If we were populating this component, then populate the
+       * corresponding channel of the new dst.
+       */
+      if (dst.writemask & bit)
+         new_writemask |= (1 << c);
    }
+   dst.writemask = new_writemask;
 }
 
 /*