mirror of
https://gcc.gnu.org/git/gcc.git
synced 2025-01-15 16:24:09 +08:00
tree-vect-generic.c (optimize_vector_constructor): New function.
* tree-vect-generic.c (optimize_vector_constructor): New function. (expand_vector_operations_1): Call it. * gcc.dg/vect/vect-124.c: New test. From-SVN: r205240
This commit is contained in:
parent
061bdebb8b
commit
ce7e41fc9a
@ -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
|
||||
|
@ -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.
|
||||
|
28
gcc/testsuite/gcc.dg/vect/vect-124.c
Normal file
28
gcc/testsuite/gcc.dg/vect/vect-124.c
Normal file
@ -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;
|
||||
}
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user