diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-04 10:54:33 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2010-11-04 10:54:33 +0000 |
commit | 2fee2038f99cb244aa1250f8ad42cae7fe2702ec (patch) | |
tree | deda1d4b4cc70866a2c7abdb650bf6e35c900463 | |
parent | 16463c8dccb07d1219cca1c3bfba4a68fe4e87fc (diff) | |
download | gcc-2fee2038f99cb244aa1250f8ad42cae7fe2702ec.tar.gz |
2010-11-04 Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
Richard Guenther <rguenther@suse.de>
* passes.c (init_optimization_passes): Move veclower after SSA.
* tree-vect-generic.c (uniform_vector_p): New function.
(expand_vector_operations_1): Handle conversion.
(pass_lower_vector): Update SSA form.
testsuite/
* gcc.dg/vec-scal-opt.c: New testcase.
* gcc.dg/vec-scal-opt1.c: New testcase.
* gcc.dg/vec-scal-opt2.c: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@166303 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/passes.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vec-scal-opt.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vec-scal-opt1.c | 20 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vec-scal-opt2.c | 19 | ||||
-rw-r--r-- | gcc/tree-vect-generic.c | 104 |
7 files changed, 169 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 712366c8846..7c903436186 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2010-11-04 Artjoms Sinkarovs <artyom.shinakroff@gmail.com> + Richard Guenther <rguenther@suse.de> + + * passes.c (init_optimization_passes): Move veclower after SSA. + * tree-vect-generic.c (uniform_vector_p): New function. + (expand_vector_operations_1): Handle conversion. + (pass_lower_vector): Update SSA form. + 2010-11-04 Iain Sandoe <iains@gcc.gnu.org> * gcc/configure.ac: Filter -mdynamic-no-pic from CFLAGS when testing for diff --git a/gcc/passes.c b/gcc/passes.c index 1ee3400e0ca..5da5ea8ab6c 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -736,7 +736,6 @@ init_optimization_passes (void) NEXT_PASS (pass_refactor_eh); NEXT_PASS (pass_lower_eh); NEXT_PASS (pass_build_cfg); - NEXT_PASS (pass_lower_vector); NEXT_PASS (pass_warn_function_return); NEXT_PASS (pass_build_cgraph_edges); NEXT_PASS (pass_inline_parameters); @@ -755,6 +754,7 @@ init_optimization_passes (void) NEXT_PASS (pass_referenced_vars); NEXT_PASS (pass_build_ssa); + NEXT_PASS (pass_lower_vector); NEXT_PASS (pass_early_warn_uninitialized); /* Note that it is not strictly necessary to schedule an early inline pass here. However, some test cases (e.g., diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bbcf32deb28..e76da86e091 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,14 @@ +2010-11-04 Artjoms Sinkarovs <artyom.shinakroff@gmail.com> + Richard Guenther <rguenther@suse.de> + + * gcc.dg/vec-scal-opt.c: New testcase. + * gcc.dg/vec-scal-opt1.c: New testcase. + * gcc.dg/vec-scal-opt2.c: New testcase. + 2010-11-04 Iain Sandoe <iains@gcc.gnu.org> - * lib/plugin-support.exp (plugin-test-execute): Filter -mdynamic-no-pic from - plugin build flags on Darwin targets. + * lib/plugin-support.exp (plugin-test-execute): Filter -mdynamic-no-pic + from plugin build flags on Darwin targets. 2010-11-03 H.J. Lu <hongjiu.lu@intel.com> diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt.c b/gcc/testsuite/gcc.dg/vec-scal-opt.c new file mode 100644 index 00000000000..0af49cf8b7f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vec-scal-opt.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-veclower" } */ + +#define vidx(type, vec, idx) (*((type *) &(vec) + idx)) +#define vector(elcount, type) \ +__attribute__((vector_size((elcount)*sizeof(type)))) type + +short k; + +int main (int argc, char *argv[]) { + k = argc; + vector(8, short) v0 = {argc,1,2,3,4,5,6,7}; + vector(8, short) v2 = {k, k,k,k,k,k,k,k}; + vector(8, short) r1; + + r1 = v0 >> v2; + + return vidx(short, r1, 0); +} + +/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower" } } */ +/* { dg-final { cleanup-tree-dump "veclower" } } */ diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt1.c b/gcc/testsuite/gcc.dg/vec-scal-opt1.c new file mode 100644 index 00000000000..e4ef8a9a3e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vec-scal-opt1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-veclower" } */ + +#define vidx(type, vec, idx) (*((type *) &(vec) + idx)) +#define vector(elcount, type) \ +__attribute__((vector_size((elcount)*sizeof(type)))) type + +short k; + +int main (int argc, char *argv[]) { + vector(8, short) v0 = {argc,1,2,3,4,5,6,7}; + vector(8, short) r1; + + r1 = v0 >> (vector(8, short)){2,2,2,2,2,2,2,2}; + + return vidx(short, r1, 0); +} + +/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */ +/* { dg-final { cleanup-tree-dump "veclower" } } */ diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt2.c b/gcc/testsuite/gcc.dg/vec-scal-opt2.c new file mode 100644 index 00000000000..f9ed1bbd958 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vec-scal-opt2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-veclower" } */ + +#define vidx(type, vec, idx) (*((type *) &(vec) + idx)) +#define vector(elcount, type) \ +__attribute__((vector_size((elcount)*sizeof(type)))) type + +int main (int argc, char *argv[]) { + vector(8, short) v0 = {argc,1,2,3,4,5,6,7}; + vector(8, short) v1 = {2,2,2,2,2,2,2,2}; + vector(8, short) r1; + + r1 = v0 >> v1; + + return vidx(short, r1, 0); +} + +/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */ +/* { dg-final { cleanup-tree-dump "veclower" } } */ diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 1fd29629e66..3f582402443 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -284,6 +284,55 @@ expand_vector_addition (gimple_stmt_iterator *gsi, a, b, code); } +/* Check if vector VEC consists of all the equal elements and + that the number of elements corresponds to the type of VEC. + The function returns first element of the vector + or NULL_TREE if the vector is not uniform. */ +static tree +uniform_vector_p (tree vec) +{ + tree first, t, els; + unsigned i; + + if (vec == NULL_TREE) + return NULL_TREE; + + if (TREE_CODE (vec) == VECTOR_CST) + { + els = TREE_VECTOR_CST_ELTS (vec); + first = TREE_VALUE (els); + els = TREE_CHAIN (els); + + for (t = els; t; t = TREE_CHAIN (t)) + if (!operand_equal_p (first, TREE_VALUE (t), 0)) + return NULL_TREE; + + return first; + } + + else if (TREE_CODE (vec) == CONSTRUCTOR) + { + first = error_mark_node; + + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t) + { + if (i == 0) + { + first = t; + continue; + } + if (!operand_equal_p (first, t, 0)) + return NULL_TREE; + } + if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))) + return NULL_TREE; + + return first; + } + + return NULL_TREE; +} + static tree expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, gimple assign, enum tree_code code) @@ -392,7 +441,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) tree lhs, rhs1, rhs2 = NULL, type, compute_type; enum tree_code code; enum machine_mode compute_mode; - optab op; + optab op = NULL; enum gimple_rhs_class rhs_class; tree new_rhs; @@ -434,18 +483,44 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) || code == LROTATE_EXPR || code == RROTATE_EXPR) { - /* If the 2nd argument is vector, we need a vector/vector shift */ + bool vector_scalar_shift; + op = optab_for_tree_code (code, type, optab_scalar); + + /* Vector/Scalar shift is supported. */ + vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type)) + != CODE_FOR_nothing)); + + /* If the 2nd argument is vector, we need a vector/vector shift. + Except all the elements in the second vector are the same. */ if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2)))) - op = optab_for_tree_code (code, type, optab_vector); - else - { - /* Try for a vector/scalar shift, and if we don't have one, see if we - have a vector/vector shift */ - op = optab_for_tree_code (code, type, optab_scalar); - if (!op - || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) - op = optab_for_tree_code (code, type, optab_vector); - } + { + tree first; + gimple def_stmt; + + /* Check whether we have vector <op> {x,x,x,x} where x + could be a scalar variable or a constant. Transform + vector <op> {x,x,x,x} ==> vector <op> scalar. */ + if (vector_scalar_shift + && ((TREE_CODE (rhs2) == VECTOR_CST + && (first = uniform_vector_p (rhs2)) != NULL_TREE) + || (TREE_CODE (rhs2) == SSA_NAME + && (def_stmt = SSA_NAME_DEF_STMT (rhs2)) + && gimple_assign_single_p (def_stmt) + && (first = uniform_vector_p + (gimple_assign_rhs1 (def_stmt))) != NULL_TREE))) + { + gimple_assign_set_rhs2 (stmt, first); + update_stmt (stmt); + rhs2 = first; + } + else + op = optab_for_tree_code (code, type, optab_vector); + } + + /* Try for a vector/scalar shift, and if we don't have one, see if we + have a vector/vector shift */ + else if (!vector_scalar_shift) + op = optab_for_tree_code (code, type, optab_vector); } else op = optab_for_tree_code (code, type, optab_default); @@ -559,8 +634,9 @@ struct gimple_opt_pass pass_lower_vector = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func | TODO_ggc_collect - | TODO_verify_stmts /* todo_flags_finish */ + TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ + | TODO_verify_ssa + | TODO_verify_stmts | TODO_verify_flow } }; |