diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-124.c | 28 | ||||
-rw-r--r-- | gcc/tree-vect-generic.c | 89 |
4 files changed, 126 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e472888..33f32b3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2bc0fcc..220a5ec 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..dc81c31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-124.c @@ -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; +} diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 735689b..fc1c7b1 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -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); +} /* 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; |