diff options
author | Marc Glisse <marc.glisse@inria.fr> | 2012-11-02 00:39:44 +0100 |
---|---|---|
committer | Marc Glisse <glisse@gcc.gnu.org> | 2012-11-01 23:39:44 +0000 |
commit | 374ab2d79709f570856ee9c4a1f0d82b189b6a0e (patch) | |
tree | 1a0502f4a9d8b1bc870689bf54fec5e1cf24b5d3 /gcc/tree-vect-generic.c | |
parent | 2328b1de5ebeea8908d5db53c1188b2782d33120 (diff) | |
download | gcc-374ab2d79709f570856ee9c4a1f0d82b189b6a0e.tar.gz |
re PR middle-end/55001 (Handle VEC_COND_EXPR better in tree-vect-generic.c)
2012-11-01 Marc Glisse <marc.glisse@inria.fr>
PR middle-end/55001
gcc/
* tree-vect-generic.c (expand_vector_condition): New function.
(expand_vector_operations_1): Call it.
testsuite/
* g++.dg/ext/vector19.C: Remove target restrictions.
* gcc.dg/fold-compare-7.c: New testcase.
From-SVN: r193077
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r-- | gcc/tree-vect-generic.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 9d54bdd99b5..2dec341fc82 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -868,6 +868,72 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0, return gimplify_build2 (gsi, MINUS_EXPR, type, op0, tem); } +/* Expand a vector condition to scalars, by using many conditions + on the vector's elements. */ +static void +expand_vector_condition (gimple_stmt_iterator *gsi) +{ + gimple stmt = gsi_stmt (*gsi); + tree type = gimple_expr_type (stmt); + tree a = gimple_assign_rhs1 (stmt); + tree a1 = a; + tree a2; + bool a_is_comparison = false; + tree b = gimple_assign_rhs2 (stmt); + tree c = gimple_assign_rhs3 (stmt); + VEC(constructor_elt,gc) *v; + tree constr; + tree inner_type = TREE_TYPE (type); + tree cond_type = TREE_TYPE (TREE_TYPE (a)); + tree comp_inner_type = cond_type; + tree width = TYPE_SIZE (inner_type); + tree index = bitsize_int (0); + int nunits = TYPE_VECTOR_SUBPARTS (type); + int i; + location_t loc = gimple_location (gsi_stmt (*gsi)); + + if (TREE_CODE (a) != SSA_NAME) + { + gcc_assert (COMPARISON_CLASS_P (a)); + a_is_comparison = true; + a1 = TREE_OPERAND (a, 0); + a2 = TREE_OPERAND (a, 1); + comp_inner_type = TREE_TYPE (TREE_TYPE (a1)); + } + + if (expand_vec_cond_expr_p (type, TREE_TYPE (a1))) + return; + + /* TODO: try and find a smaller vector type. */ + + warning_at (loc, OPT_Wvector_operation_performance, + "vector condition will be expanded piecewise"); + + v = VEC_alloc(constructor_elt, gc, nunits); + for (i = 0; i < nunits; + i++, index = int_const_binop (PLUS_EXPR, index, width)) + { + tree aa, result; + tree bb = tree_vec_extract (gsi, inner_type, b, width, index); + tree cc = tree_vec_extract (gsi, inner_type, c, width, index); + if (a_is_comparison) + { + tree aa1 = tree_vec_extract (gsi, comp_inner_type, a1, width, index); + tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2, width, index); + aa = build2 (TREE_CODE (a), cond_type, aa1, aa2); + } + else + aa = tree_vec_extract (gsi, cond_type, a, width, index); + result = gimplify_build3 (gsi, COND_EXPR, inner_type, aa, bb, cc); + constructor_elt ce = {NULL_TREE, result}; + VEC_quick_push (constructor_elt, v, ce); + } + + constr = build_constructor (type, v); + gimple_assign_set_rhs_from_tree (gsi, constr); + update_stmt (gsi_stmt (*gsi)); +} + static tree expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type, gimple assign, enum tree_code code) @@ -1248,6 +1314,11 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi) return; } + if (code == VEC_COND_EXPR) + { + expand_vector_condition (gsi); + return; + } if (rhs_class != GIMPLE_UNARY_RHS && rhs_class != GIMPLE_BINARY_RHS) return; |