On Mon, 21 Apr 2014, Bill Schmidt wrote:

Note that it would be possible to do a more general transformation here,
in which any vec_select feeding another could be replaced by a
vec_select performing the composite function of the other two.  I have
not done this because I am unaware of this situation arising in
practice.  If it's desirable, I can extend the patch in this direction.

It does arise, but I think it isn't done because not all permutations are (optimally) supported by all targets.

Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c  (revision 209516)
+++ gcc/simplify-rtx.c  (working copy)
@@ -3673,6 +3673,34 @@ simplify_binary_operation_1 (enum rtx_code code, e
            }
        }

+      /* If we have two nested selects that are inverses of each
+        other, replace them with the source operand.  */
+      if (GET_CODE (trueop0) == VEC_SELECT)
+       {
+         enum machine_mode reg_mode = GET_MODE (XEXP (trueop0, 0));
+         rtx op0_subop1 = XEXP (trueop0, 1);
+         gcc_assert (VECTOR_MODE_P (reg_mode));
+         gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER (reg_mode));
+         gcc_assert (GET_CODE (op0_subop1) == PARALLEL);
+
+         if (XVECLEN (trueop1, 0) == XVECLEN (op0_subop1, 0))
+           {
+             /* Apply the second ordering vector to the first.
+                If the result is { 0, 1, ..., n-1 } then the
+                two VEC_SELECTs cancel.  */
+             for (int i = 0; i < XVECLEN (trueop1, 0); ++i)
+               {
+                 rtx x = XVECEXP (trueop1, 0, i);
+                 gcc_assert (CONST_INT_P (x));
+                 rtx y = XVECEXP (op0_subop1, 0, INTVAL (x));
+                 gcc_assert (CONST_INT_P (y));
+                 if (i != INTVAL (y))
+                   return 0;
+               }
+             return XEXP (trueop0, 0);
+           }
+       }

I may have missed it, but don't you want to check that what you are returning has the right mode/length (or generate the obvious vec_select otherwise)? I don't know if any platform has such constructions (probably not), but in principle you could start from a vector of size 4, extract {1,0} from it, extract {1,0} from that, and you don't want to return the initial vector as is. On the other hand, I don't think you really care whether trueop1 is smaller than op0_subop1. Starting from a vector of size 2, extracting {1,0,1,0} then {3,0} gives the initial vector just fine.

--
Marc Glisse

Reply via email to