Hello,

in PR50829, HJ Lu pointed me to this PR for which I already had a patch (I hadn't submitted it because I didn't have a good use case for it).

bootstrap+testsuite on x86_64-linux.

2012-12-02  Marc Glisse  <marc.gli...@inria.fr>

        PR target/44551
gcc/
        * simplify-rtx.c (simplify_binary_operation_1) <VEC_SELECT>: Detect
        when all elements come from one half of a VEC_CONCAT.

gcc/testsuite/
        * gcc.target/i386/pr44551.c: New testcase.

--
Marc Glisse
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c  (revision 194037)
+++ gcc/simplify-rtx.c  (working copy)
@@ -3482,44 +3482,77 @@ simplify_binary_operation_1 (enum rtx_co
              rtx subop0, subop1;
 
              gcc_assert (i0 < 2 && i1 < 2);
              subop0 = XEXP (trueop0, i0);
              subop1 = XEXP (trueop0, i1);
 
              return simplify_gen_binary (VEC_CONCAT, mode, subop0, subop1);
            }
        }
 
-      if (XVECLEN (trueop1, 0) == 1
-         && CONST_INT_P (XVECEXP (trueop1, 0, 0))
-         && GET_CODE (trueop0) == VEC_CONCAT)
+      /* Detect if all the elements come from the same subpart of a concat.  */
+      if (GET_CODE (trueop0) == VEC_CONCAT)
        {
-         rtx vec = trueop0;
-         int offset = INTVAL (XVECEXP (trueop1, 0, 0)) * GET_MODE_SIZE (mode);
+         rtx new_op0 = NULL_RTX;
+         rtx new_op1 = NULL_RTX;
+         int first = 0;
+         int second = 0;
+         unsigned nelts_first_half = 1;
+         enum machine_mode mode_first_half = GET_MODE (XEXP (trueop0, 0));
+         if (VECTOR_MODE_P (mode_first_half))
+           {
+             int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode_first_half));
+             nelts_first_half = (GET_MODE_SIZE (mode_first_half) / elt_size);
+           }
 
-         /* Try to find the element in the VEC_CONCAT.  */
-         while (GET_MODE (vec) != mode
-                && GET_CODE (vec) == VEC_CONCAT)
+         for (int i = 0; i < XVECLEN (trueop1, 0); i++)
            {
-             HOST_WIDE_INT vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0)));
-             if (offset < vec_size)
-               vec = XEXP (vec, 0);
+             rtx j = XVECEXP (trueop1, 0, i);
+             if (!CONST_INT_P (j))
+               {
+                 first++;
+                 second++;
+                 break;
+               }
+             if (INTVAL (j) < nelts_first_half)
+               first++;
              else
+               second++;
+           }
+
+         if (second == 0)
+           {
+             new_op0 = XEXP (trueop0, 0);
+             new_op1 = trueop1;
+           }
+         else if (first == 0)
+           {
+             int len = XVECLEN (trueop1, 0);
+             rtvec vec = rtvec_alloc (len);
+             for (int i = 0; i < len; i++)
                {
-                 offset -= vec_size;
-                 vec = XEXP (vec, 1);
+                 int j = INTVAL (XVECEXP (trueop1, 0, i)) - nelts_first_half;
+                 RTVEC_ELT (vec, i) = GEN_INT (j);
                }
-             vec = avoid_constant_pool_reference (vec);
+             new_op0 = XEXP (trueop0, 1);
+             new_op1 = gen_rtx_PARALLEL (VOIDmode, vec);
            }
 
-         if (GET_MODE (vec) == mode)
-           return vec;
+         if (new_op0)
+           {
+             if (VECTOR_MODE_P (GET_MODE (new_op0)))
+               return simplify_gen_binary (VEC_SELECT, mode, new_op0, new_op1);
+             if (VECTOR_MODE_P (mode))
+               return simplify_gen_unary (VEC_DUPLICATE, mode, new_op0,
+                                          GET_MODE (new_op0));
+             return new_op0;
+           }
        }
 
       return 0;
     case VEC_CONCAT:
       {
        enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode
                                      ? GET_MODE (trueop0)
                                      : GET_MODE_INNER (mode));
        enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode
                                      ? GET_MODE (trueop1)
Index: gcc/testsuite/gcc.target/i386/pr44551.c
===================================================================
--- gcc/testsuite/gcc.target/i386/pr44551.c     (revision 0)
+++ gcc/testsuite/gcc.target/i386/pr44551.c     (revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mavx" } */
+
+#include <immintrin.h>
+
+__m128i
+foo (__m256i x, __m128i y)
+{
+  __m256i r = _mm256_insertf128_si256(x, y, 1);
+  __m128i a = _mm256_extractf128_si256(r, 1);
+  return a;
+}
+
+/* { dg-final { scan-assembler-not "insert" } } */
+/* { dg-final { scan-assembler-not "extract" } } */

Property changes on: gcc/testsuite/gcc.target/i386/pr44551.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Reply via email to