re PR tree-optimization/85692 (Two source permute not used for vector initialization)
authorAllan Sandfeld Jensen <allan.jensen@qt.io>
Fri, 11 May 2018 07:38:49 +0000 (13:38 +0600)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 11 May 2018 07:38:49 +0000 (09:38 +0200)
PR tree-optimization/85692
* tree-ssa-forwprop.c (simplify_vector_constructor): Try two
source permute as well.

* gcc.target/i386/pr85692.c: New test.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
From-SVN: r260155

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr85692.c [new file with mode: 0644]
gcc/tree-ssa-forwprop.c

index 75ed3b33f70463913cb63d75efa04561754a6634..01d3b18ab446b5e0925ec0b04d6bc9530fd0434e 100644 (file)
@@ -1,3 +1,10 @@
+2018-05-11  Allan Sandfeld Jensen  <allan.jensen@qt.io>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/85692
+       * tree-ssa-forwprop.c (simplify_vector_constructor): Try two
+       source permute as well.
+
 2018-05-11  Martin Liska  <mliska@suse.cz>
 
         PR sanitizer/85556
index ee9f633ad8473a48576645450e59b0a9708ed896..1591122913dbfe99a1e99e4ff5b98d9144aede8a 100644 (file)
@@ -1,3 +1,9 @@
+2018-05-11  Allan Sandfeld Jensen  <allan.jensen@qt.io>
+           Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/85692
+       * gcc.target/i386/pr85692.c: New test.
+
 2018-05-11  Martin Liska  <mliska@suse.cz>
 
         PR sanitizer/85556
diff --git a/gcc/testsuite/gcc.target/i386/pr85692.c b/gcc/testsuite/gcc.target/i386/pr85692.c
new file mode 100644 (file)
index 0000000..45594ff
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse4.1" } */
+/* { dg-final { scan-assembler "unpcklps" } } */
+/* { dg-final { scan-assembler "blendps" } } */
+/* { dg-final { scan-assembler-not "shufps" } } */
+/* { dg-final { scan-assembler-not "unpckhps" } } */
+
+typedef float v4sf __attribute__ ((vector_size (16)));
+
+v4sf unpcklps(v4sf a, v4sf b)
+{
+    return (v4sf){a[0],b[0],a[1],b[1]};
+}
+
+v4sf blendps(v4sf a, v4sf b)
+{
+    return (v4sf){a[0],b[1],a[2],b[3]};
+}
index 58ec6b47a5bb6a5e0223dd08fae488e6ad114bea..2efb5acae8fd5f0b6c69992b69b05c619754798e 100644 (file)
@@ -2004,7 +2004,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
   gimple *def_stmt;
-  tree op, op2, orig, type, elem_type;
+  tree op, op2, orig[2], type, elem_type;
   unsigned elem_size, i;
   unsigned HOST_WIDE_INT nelts;
   enum tree_code code, conv_code;
@@ -2023,7 +2023,8 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   elem_size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
 
   vec_perm_builder sel (nelts, nelts, 1);
-  orig = NULL;
+  orig[0] = NULL;
+  orig[1] = NULL;
   conv_code = ERROR_MARK;
   maybe_ident = true;
   FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
@@ -2063,25 +2064,35 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
        return false;
       op1 = gimple_assign_rhs1 (def_stmt);
       ref = TREE_OPERAND (op1, 0);
-      if (orig)
+      unsigned int j;
+      for (j = 0; j < 2; ++j)
        {
-         if (ref != orig)
-           return false;
-       }
-      else
-       {
-         if (TREE_CODE (ref) != SSA_NAME)
-           return false;
-         if (! VECTOR_TYPE_P (TREE_TYPE (ref))
-             || ! useless_type_conversion_p (TREE_TYPE (op1),
-                                             TREE_TYPE (TREE_TYPE (ref))))
-           return false;
-         orig = ref;
+         if (!orig[j])
+           {
+             if (TREE_CODE (ref) != SSA_NAME)
+               return false;
+             if (! VECTOR_TYPE_P (TREE_TYPE (ref))
+                 || ! useless_type_conversion_p (TREE_TYPE (op1),
+                                                 TREE_TYPE (TREE_TYPE (ref))))
+               return false;
+             if (j && !useless_type_conversion_p (TREE_TYPE (orig[0]),
+                                                  TREE_TYPE (ref)))
+               return false;
+             orig[j] = ref;
+             break;
+           }
+         else if (ref == orig[j])
+           break;
        }
+      if (j == 2)
+       return false;
+
       unsigned int elt;
       if (maybe_ne (bit_field_size (op1), elem_size)
          || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
        return false;
+      if (j)
+       elt += nelts;
       if (elt != i)
        maybe_ident = false;
       sel.quick_push (elt);
@@ -2089,14 +2100,15 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   if (i < nelts)
     return false;
 
-  if (! VECTOR_TYPE_P (TREE_TYPE (orig))
+  if (! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
       || maybe_ne (TYPE_VECTOR_SUBPARTS (type),
-                  TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig))))
+                  TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig[0]))))
     return false;
 
   tree tem;
   if (conv_code != ERROR_MARK
-      && (! supportable_convert_operation (conv_code, type, TREE_TYPE (orig),
+      && (! supportable_convert_operation (conv_code, type,
+                                          TREE_TYPE (orig[0]),
                                           &tem, &conv_code)
          || conv_code == CALL_EXPR))
     return false;
@@ -2104,16 +2116,16 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   if (maybe_ident)
     {
       if (conv_code == ERROR_MARK)
-       gimple_assign_set_rhs_from_tree (gsi, orig);
+       gimple_assign_set_rhs_from_tree (gsi, orig[0]);
       else
-       gimple_assign_set_rhs_with_ops (gsi, conv_code, orig,
+       gimple_assign_set_rhs_with_ops (gsi, conv_code, orig[0],
                                        NULL_TREE, NULL_TREE);
     }
   else
     {
       tree mask_type;
 
-      vec_perm_indices indices (sel, 1, nelts);
+      vec_perm_indices indices (sel, orig[1] ? 2 : 1, nelts);
       if (!can_vec_perm_const_p (TYPE_MODE (type), indices))
        return false;
       mask_type
@@ -2124,16 +2136,19 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
                       GET_MODE_SIZE (TYPE_MODE (type))))
        return false;
       op2 = vec_perm_indices_to_tree (mask_type, indices);
+      if (!orig[1])
+       orig[1] = orig[0];
       if (conv_code == ERROR_MARK)
-       gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig, orig, op2);
+       gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
+                                       orig[1], op2);
       else
        {
          gimple *perm
-           = gimple_build_assign (make_ssa_name (TREE_TYPE (orig)),
-                                  VEC_PERM_EXPR, orig, orig, op2);
-         orig = gimple_assign_lhs (perm);
+           = gimple_build_assign (make_ssa_name (TREE_TYPE (orig[0])),
+                                  VEC_PERM_EXPR, orig[0], orig[1], op2);
+         orig[0] = gimple_assign_lhs (perm);
          gsi_insert_before (gsi, perm, GSI_SAME_STMT);
-         gimple_assign_set_rhs_with_ops (gsi, conv_code, orig,
+         gimple_assign_set_rhs_with_ops (gsi, conv_code, orig[0],
                                          NULL_TREE, NULL_TREE);
        }
     }