summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-04 10:54:33 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2010-11-04 10:54:33 +0000
commit2fee2038f99cb244aa1250f8ad42cae7fe2702ec (patch)
treededa1d4b4cc70866a2c7abdb650bf6e35c900463
parent16463c8dccb07d1219cca1c3bfba4a68fe4e87fc (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/passes.c2
-rw-r--r--gcc/testsuite/ChangeLog11
-rw-r--r--gcc/testsuite/gcc.dg/vec-scal-opt.c22
-rw-r--r--gcc/testsuite/gcc.dg/vec-scal-opt1.c20
-rw-r--r--gcc/testsuite/gcc.dg/vec-scal-opt2.c19
-rw-r--r--gcc/tree-vect-generic.c104
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
}
};