re PR tree-optimization/88828 (Inefficient update of the first element of vector...
authorRichard Biener <rguenther@suse.de>
Mon, 6 May 2019 12:43:30 +0000 (12:43 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 6 May 2019 12:43:30 +0000 (12:43 +0000)
2019-05-06  Richard Biener  <rguenther@suse.de>

PR tree-optimization/88828
* tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from...
(simplify_vector_constructor): ...here.  Handle constants in
the constructor.

* gcc.target/i386/pr88828-0.c: New testcase.

From-SVN: r270908

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

index b4424ddd40e3695163b539d76b754db168ce4a0d..3e9b69be2f075cef449e373c1a75fa0635414853 100644 (file)
@@ -1,3 +1,10 @@
+2019-05-06  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/88828
+       * tree-ssa-forwprop.c (get_bit_field_ref_def): Split out from...
+       (simplify_vector_constructor): ...here.  Handle constants in
+       the constructor.
+
 2019-05-06  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/90328
index 2ad2c4ac4ce4689a3cf034cd6555049051183ad7..37887397d747267bf4366058e6f5b8e09660dc14 100644 (file)
@@ -1,3 +1,8 @@
+2019-05-06  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/88828
+       * gcc.target/i386/pr88828-0.c: New testcase.
+
 2019-05-06  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/90328
diff --git a/gcc/testsuite/gcc.target/i386/pr88828-0.c b/gcc/testsuite/gcc.target/i386/pr88828-0.c
new file mode 100644 (file)
index 0000000..3ddb2d1
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse4.2" } */
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef float v4sf __attribute__((vector_size(16)));
+
+v4si foo (v4si x)
+{
+  return (v4si){ x[0], 1, x[2], 3 };
+}
+
+/* { dg-final { scan-assembler "pblendw" } } */
+
+v4si bar (v4sf x)
+{
+  return (v4si){ 1, x[1], x[2], 3 };
+}
+
+/* { dg-final { scan-assembler "cvttps2dq" } } */
+/* { dg-final { scan-assembler "pblendw" } } */
+
+v4si baz (v4si x)
+{
+  return (v4si) { x[1], x[2], x[3], 0 };
+}
+
+/* { dg-final { scan-assembler "psrldq" } } */
index 1553c9e70ac1fd51627f351f75ba2d5f01eb719a..7dd1e64335ac65d8442e11f95af22e760cb77956 100644 (file)
@@ -1997,17 +1997,54 @@ simplify_permutation (gimple_stmt_iterator *gsi)
   return 0;
 }
 
+/* Get the BIT_FIELD_REF definition of VAL, if any, looking through
+   conversions with code CONV_CODE or update it if still ERROR_MARK.
+   Return NULL_TREE if no such matching def was found.  */
+
+static tree
+get_bit_field_ref_def (tree val, enum tree_code &conv_code)
+{
+  if (TREE_CODE (val) != SSA_NAME)
+    return NULL_TREE ;
+  gimple *def_stmt = get_prop_source_stmt (val, false, NULL);
+  if (!def_stmt)
+    return NULL_TREE;
+  enum tree_code code = gimple_assign_rhs_code (def_stmt);
+  if (code == FLOAT_EXPR
+      || code == FIX_TRUNC_EXPR)
+    {
+      tree op1 = gimple_assign_rhs1 (def_stmt);
+      if (conv_code == ERROR_MARK)
+       {
+         if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))),
+                       GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
+           return NULL_TREE;
+         conv_code = code;
+       }
+      else if (conv_code != code)
+       return NULL_TREE;
+      if (TREE_CODE (op1) != SSA_NAME)
+       return NULL_TREE;
+      def_stmt = SSA_NAME_DEF_STMT (op1);
+      if (! is_gimple_assign (def_stmt))
+       return NULL_TREE;
+      code = gimple_assign_rhs_code (def_stmt);
+    }
+  if (code != BIT_FIELD_REF)
+    return NULL_TREE;
+  return gimple_assign_rhs1 (def_stmt);
+}
+
 /* Recognize a VEC_PERM_EXPR.  Returns true if there were any changes.  */
 
 static bool
 simplify_vector_constructor (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
-  gimple *def_stmt;
   tree op, op2, orig[2], type, elem_type;
   unsigned elem_size, i;
   unsigned HOST_WIDE_INT nelts;
-  enum tree_code code, conv_code;
+  enum tree_code conv_code;
   constructor_elt *elt;
   bool maybe_ident;
 
@@ -2027,6 +2064,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
   orig[1] = NULL;
   conv_code = ERROR_MARK;
   maybe_ident = true;
+  tree one_constant = NULL_TREE;
+  auto_vec<tree> constants;
+  constants.safe_grow_cleared (nelts);
   FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
     {
       tree ref, op1;
@@ -2034,68 +2074,57 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       if (i >= nelts)
        return false;
 
-      if (TREE_CODE (elt->value) != SSA_NAME)
-       return false;
-      def_stmt = get_prop_source_stmt (elt->value, false, NULL);
-      if (!def_stmt)
-       return false;
-      code = gimple_assign_rhs_code (def_stmt);
-      if (code == FLOAT_EXPR
-         || code == FIX_TRUNC_EXPR)
+      op1 = get_bit_field_ref_def (elt->value, conv_code);
+      if (op1)
        {
-         op1 = gimple_assign_rhs1 (def_stmt);
-         if (conv_code == ERROR_MARK)
+         ref = TREE_OPERAND (op1, 0);
+         unsigned int j;
+         for (j = 0; j < 2; ++j)
            {
-             if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (elt->value))),
-                           GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
-               return false;
-             conv_code = code;
+             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;
            }
-         else if (conv_code != code)
-           return false;
-         if (TREE_CODE (op1) != SSA_NAME)
+         if (j == 2)
            return false;
-         def_stmt = SSA_NAME_DEF_STMT (op1);
-         if (! is_gimple_assign (def_stmt))
+
+         unsigned int elt;
+         if (maybe_ne (bit_field_size (op1), elem_size)
+             || !constant_multiple_p (bit_field_offset (op1), elem_size, &elt))
            return false;
-         code = gimple_assign_rhs_code (def_stmt);
+         if (j)
+           elt += nelts;
+         if (elt != i)
+           maybe_ident = false;
+         sel.quick_push (elt);
        }
-      if (code != BIT_FIELD_REF)
-       return false;
-      op1 = gimple_assign_rhs1 (def_stmt);
-      ref = TREE_OPERAND (op1, 0);
-      unsigned int j;
-      for (j = 0; j < 2; ++j)
+      else if (CONSTANT_CLASS_P (elt->value))
        {
-         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 (orig[1]
+             && orig[1] != error_mark_node)
+           return false;
+         orig[1] = error_mark_node;
+         if (!one_constant)
+           one_constant = elt->value;
+         constants[i] = elt->value;
+         sel.quick_push (i + nelts);
+         maybe_ident = false;
        }
-      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))
+      else
        return false;
-      if (j)
-       elt += nelts;
-      if (elt != i)
-       maybe_ident = false;
-      sel.quick_push (elt);
     }
   if (i < nelts)
     return false;
@@ -2138,9 +2167,29 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
       op2 = vec_perm_indices_to_tree (mask_type, indices);
       if (!orig[1])
        orig[1] = orig[0];
+      if (orig[1] == error_mark_node)
+       {
+         tree_vector_builder vec (type, nelts, 1);
+         for (unsigned i = 0; i < nelts; ++i)
+           if (constants[i])
+             vec.quick_push (constants[i]);
+           else
+             /* ??? Push a don't-care value.  */
+             vec.quick_push (one_constant);
+         orig[1] = vec.build ();
+       }
       if (conv_code == ERROR_MARK)
        gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
                                        orig[1], op2);
+      else if (TREE_CODE (orig[1]) == VECTOR_CST)
+       {
+         gimple *conv
+           = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);
+         orig[0] = gimple_assign_lhs (conv);
+         gsi_insert_before (gsi, conv, GSI_SAME_STMT);
+         gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR,
+                                         orig[0], orig[1], op2);
+       }
       else
        {
          gimple *perm