]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* tree-vect-generic.c (optimize_vector_constructor): New function.
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Nov 2013 00:41:38 +0000 (00:41 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Nov 2013 00:41:38 +0000 (00:41 +0000)
(expand_vector_operations_1): Call it.

* gcc.dg/vect/vect-124.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@205240 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-124.c [new file with mode: 0644]
gcc/tree-vect-generic.c

index e472888c3fb23323d1222a6c3abdd29fe234b6ed..33f32b3b890a53cd9239b3a82574336ebc523168 100644 (file)
@@ -1,3 +1,8 @@
+2013-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * tree-vect-generic.c (optimize_vector_constructor): New function.
+       (expand_vector_operations_1): Call it.
+
 2013-11-21  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.c (ix86_expand_special_args_builtin): Use
index 2bc0fcc3dea0412cfc4a151d5bd5bda79ff51ff7..220a5eca77fb4d3a7faaffaae5ee7486ab3dd701 100644 (file)
@@ -1,3 +1,7 @@
+2013-11-22  Jakub Jelinek  <jakub@redhat.com>
+
+       * gcc.dg/vect/vect-124.c: New test.
+
 2013-11-21  Cary Coutant  <ccoutant@google.com>
 
        * gcc.dg/debug/dwarf2/mlt1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/vect/vect-124.c b/gcc/testsuite/gcc.dg/vect/vect-124.c
new file mode 100644 (file)
index 0000000..dc81c31
--- /dev/null
@@ -0,0 +1,28 @@
+#include "tree-vect.h"
+
+#ifndef N
+#define N 64
+#endif
+
+int a[N];
+
+__attribute__((noinline, noclone)) void
+foo (int x)
+{
+  int i;
+  for (i = 0; i < N; i++, x += 3)
+    a[i] = x;
+}
+
+int
+main ()
+{
+  int i;
+  
+  check_vect ();
+  foo (6);
+  for (i = 0; i < N; i++)
+    if (a[i] != i * 3 + 6)
+      abort ();
+  return 0;
+}
index 735689b4c18b2ab31bddce068875db06acf4d8f2..fc1c7b14fb9fe7876ed85ad72d59e959047fed85 100644 (file)
@@ -988,6 +988,84 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
                                    gimple_assign_rhs1 (assign),
                                    gimple_assign_rhs2 (assign), code);
 }
+
+/* Try to optimize
+   a_5 = { b_7, b_7 + 3, b_7 + 6, b_7 + 9 };
+   style stmts into:
+   _9 = { b_7, b_7, b_7, b_7 };
+   a_5 = _9 + { 0, 3, 6, 9 };
+   because vector splat operation is usually more efficient
+   than piecewise initialization of the vector.  */
+
+static void
+optimize_vector_constructor (gimple_stmt_iterator *gsi)
+{
+  gimple stmt = gsi_stmt (*gsi);
+  tree lhs = gimple_assign_lhs (stmt);
+  tree rhs = gimple_assign_rhs1 (stmt);
+  tree type = TREE_TYPE (rhs);
+  unsigned int i, j, nelts = TYPE_VECTOR_SUBPARTS (type);
+  bool all_same = true;
+  constructor_elt *elt;
+  tree *cst;
+  gimple g;
+  tree base = NULL_TREE;
+
+  if (nelts <= 2 || CONSTRUCTOR_NELTS (rhs) != nelts)
+    return;
+  FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt)
+    if (TREE_CODE (elt->value) != SSA_NAME
+       || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE)
+      return;
+    else
+      {
+       tree this_base = elt->value;
+       if (this_base != CONSTRUCTOR_ELT (rhs, 0)->value)
+         all_same = false;
+       for (j = 0; j < nelts + 1; j++)
+         {
+           g = SSA_NAME_DEF_STMT (this_base);
+           if (is_gimple_assign (g)
+               && gimple_assign_rhs_code (g) == PLUS_EXPR
+               && TREE_CODE (gimple_assign_rhs2 (g)) == INTEGER_CST
+               && TREE_CODE (gimple_assign_rhs1 (g)) == SSA_NAME
+               && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (g)))
+             this_base = gimple_assign_rhs1 (g);
+           else
+             break;
+         }
+       if (i == 0)
+         base = this_base;
+       else if (this_base != base)
+         return;
+      }
+  if (all_same)
+    return;
+  cst = XALLOCAVEC (tree, nelts);
+  for (i = 0; i < nelts; i++)
+    {
+      tree this_base = CONSTRUCTOR_ELT (rhs, i)->value;;
+      cst[i] = build_zero_cst (TREE_TYPE (base));
+      while (this_base != base)
+       {
+         g = SSA_NAME_DEF_STMT (this_base);
+         cst[i] = fold_binary (PLUS_EXPR, TREE_TYPE (base),
+                               cst[i], gimple_assign_rhs2 (g));
+         if (cst[i] == NULL_TREE
+             || TREE_CODE (cst[i]) != INTEGER_CST
+             || TREE_OVERFLOW (cst[i]))
+           return;
+         this_base = gimple_assign_rhs1 (g);
+       }
+    }
+  for (i = 0; i < nelts; i++)
+    CONSTRUCTOR_ELT (rhs, i)->value = base;
+  g = gimple_build_assign (make_ssa_name (type, NULL), rhs);
+  gsi_insert_before (gsi, g, GSI_SAME_STMT);
+  g = gimple_build_assign_with_ops (PLUS_EXPR, lhs, gimple_assign_lhs (g),
+                                   build_vector (type, cst));
+  gsi_replace (gsi, g, false);
+}
 \f
 /* Return a type for the widest vector mode whose components are of type
    TYPE, or NULL_TREE if none is found.  */
@@ -1278,6 +1356,17 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
       expand_vector_condition (gsi);
       return;
     }
+
+  if (code == CONSTRUCTOR
+      && TREE_CODE (lhs) == SSA_NAME
+      && VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (lhs)))
+      && !gimple_clobber_p (stmt)
+      && optimize)
+    {
+      optimize_vector_constructor (gsi);
+      return;
+    }
+
   if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS)
     return;