diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-03-14 20:48:15 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-03-14 20:48:15 +0000 |
commit | 026f213783364bd6f4ac0d274bce9a8c95a629ed (patch) | |
tree | 9e66d592578a568f4060ec49ae3ffaf3056f0295 | |
parent | 39e2f1a461b97f5bba555a4577cf7c265bb8e99d (diff) | |
download | gcc-026f213783364bd6f4ac0d274bce9a8c95a629ed.tar.gz |
PR tree-opt/68714
* tree-ssa-reassoc.c (ovce_extract_ops, optimize_vec_cond_expr): New.
(can_reassociate_p): Allow ANY_INTEGRAL_TYPE_P.
(reassociate_bb): Use optimize_vec_cond_expr; avoid
optimize_range_tests, attempt_builtin_copysign and attempt_builtin_powi
on vectors.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@234196 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr68714.c | 9 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 163 |
3 files changed, 173 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac8b40dae68..b9fba23890a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-03-14 Richard Henderson <rth@redhat.com> + + PR tree-opt/68714 + * tree-ssa-reassoc.c (ovce_extract_ops, optimize_vec_cond_expr): New. + (can_reassociate_p): Allow ANY_INTEGRAL_TYPE_P. + (reassociate_bb): Use optimize_vec_cond_expr; avoid + optimize_range_tests, attempt_builtin_copysign and attempt_builtin_powi + on vectors. + 2016-03-14 Bernd Schmidt <bschmidt@redhat.com> PR target/70083 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr68714.c b/gcc/testsuite/gcc.dg/tree-ssa/pr68714.c new file mode 100644 index 00000000000..741d3113c05 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr68714.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef int vec __attribute__((vector_size(16))); +vec f(vec x,vec y){ + return x<y|x==y; +} + +/* { dg-final { scan-tree-dump-times " <= " 1 "optimized" } } */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 4e1251b2a94..0340df24930 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -2769,6 +2769,146 @@ optimize_range_tests (enum tree_code opcode, return any_changes; } +/* A subroutine of optimize_vec_cond_expr to extract and canonicalize + the operands of the VEC_COND_EXPR. Returns ERROR_MARK on failure, + otherwise the comparison code. */ + +static tree_code +ovce_extract_ops (tree var, gassign **rets, bool *reti) +{ + if (TREE_CODE (var) != SSA_NAME) + return ERROR_MARK; + + gassign *stmt = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (var)); + if (stmt == NULL) + return ERROR_MARK; + + /* ??? If we start creating more COND_EXPR, we could perform + this same optimization with them. For now, simplify. */ + if (gimple_assign_rhs_code (stmt) != VEC_COND_EXPR) + return ERROR_MARK; + + tree cond = gimple_assign_rhs1 (stmt); + tree_code cmp = TREE_CODE (cond); + if (TREE_CODE_CLASS (cmp) != tcc_comparison) + return ERROR_MARK; + + /* ??? For now, allow only canonical true and false result vectors. + We could expand this to other constants should the need arise, + but at the moment we don't create them. */ + tree t = gimple_assign_rhs2 (stmt); + tree f = gimple_assign_rhs3 (stmt); + bool inv; + if (integer_all_onesp (t)) + inv = false; + else if (integer_all_onesp (f)) + { + cmp = invert_tree_comparison (cmp, false); + inv = true; + } + else + return ERROR_MARK; + if (!integer_zerop (f)) + return ERROR_MARK; + + /* Success! */ + if (rets) + *rets = stmt; + if (reti) + *reti = inv; + return cmp; +} + +/* Optimize the condition of VEC_COND_EXPRs which have been combined + with OPCODE (either BIT_AND_EXPR or BIT_IOR_EXPR). */ + +static bool +optimize_vec_cond_expr (tree_code opcode, vec<operand_entry *> *ops) +{ + unsigned int length = ops->length (), i, j; + bool any_changes = false; + + if (length == 1) + return false; + + for (i = 0; i < length; ++i) + { + tree elt0 = (*ops)[i]->op; + + gassign *stmt0; + bool invert; + tree_code cmp0 = ovce_extract_ops (elt0, &stmt0, &invert); + if (cmp0 == ERROR_MARK) + continue; + + for (j = i + 1; j < length; ++j) + { + tree &elt1 = (*ops)[j]->op; + + gassign *stmt1; + tree_code cmp1 = ovce_extract_ops (elt1, &stmt1, NULL); + if (cmp1 == ERROR_MARK) + continue; + + tree cond0 = gimple_assign_rhs1 (stmt0); + tree x0 = TREE_OPERAND (cond0, 0); + tree y0 = TREE_OPERAND (cond0, 1); + + tree cond1 = gimple_assign_rhs1 (stmt1); + tree x1 = TREE_OPERAND (cond1, 0); + tree y1 = TREE_OPERAND (cond1, 1); + + tree comb; + if (opcode == BIT_AND_EXPR) + comb = maybe_fold_and_comparisons (cmp0, x0, y0, cmp1, x1, y1); + else if (opcode == BIT_IOR_EXPR) + comb = maybe_fold_or_comparisons (cmp0, x0, y0, cmp1, x1, y1); + else + gcc_unreachable (); + if (comb == NULL) + continue; + + /* Success! */ + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Transforming "); + print_generic_expr (dump_file, cond0, 0); + fprintf (dump_file, " %c ", opcode == BIT_AND_EXPR ? '&' : '|'); + print_generic_expr (dump_file, cond1, 0); + fprintf (dump_file, " into "); + print_generic_expr (dump_file, comb, 0); + fputc ('\n', dump_file); + } + + gimple_assign_set_rhs1 (stmt0, comb); + if (invert) + std::swap (*gimple_assign_rhs2_ptr (stmt0), + *gimple_assign_rhs3_ptr (stmt0)); + update_stmt (stmt0); + + elt1 = error_mark_node; + any_changes = true; + } + } + + if (any_changes) + { + operand_entry *oe; + j = 0; + FOR_EACH_VEC_ELT (*ops, i, oe) + { + if (oe->op == error_mark_node) + continue; + else if (i != j) + (*ops)[j] = oe; + j++; + } + ops->truncate (j); + } + + return any_changes; +} + /* Return true if STMT is a cast like: <bb N>: ... @@ -4326,7 +4466,7 @@ static bool can_reassociate_p (tree op) { tree type = TREE_TYPE (op); - if ((INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)) + if ((ANY_INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_WRAPS (type)) || NON_SAT_FIXED_POINT_TYPE_P (type) || (flag_associative_math && FLOAT_TYPE_P (type))) return true; @@ -4952,6 +5092,7 @@ reassociate_bb (basic_block bb) { auto_vec<operand_entry *> ops; tree powi_result = NULL_TREE; + bool is_vector = VECTOR_TYPE_P (TREE_TYPE (lhs)); /* There may be no immediate uses left by the time we get here because we may have eliminated them all. */ @@ -4970,15 +5111,21 @@ reassociate_bb (basic_block bb) } if (rhs_code == BIT_IOR_EXPR || rhs_code == BIT_AND_EXPR) - optimize_range_tests (rhs_code, &ops); + { + if (is_vector) + optimize_vec_cond_expr (rhs_code, &ops); + else + optimize_range_tests (rhs_code, &ops); + } - if (rhs_code == MULT_EXPR) - attempt_builtin_copysign (&ops); + if (rhs_code == MULT_EXPR && !is_vector) + { + attempt_builtin_copysign (&ops); - if (reassoc_insert_powi_p - && rhs_code == MULT_EXPR - && flag_unsafe_math_optimizations) - powi_result = attempt_builtin_powi (stmt, &ops); + if (reassoc_insert_powi_p + && flag_unsafe_math_optimizations) + powi_result = attempt_builtin_powi (stmt, &ops); + } /* If the operand vector is now empty, all operands were consumed by the __builtin_powi optimization. */ |