From 51d4212ae9d460c41f5dfe2d47e4350a980c49c7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 14 Mar 2016 13:48:15 -0700 Subject: [PATCH] re PR tree-optimization/68714 (less folding of vector comparison) 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. From-SVN: r234196 --- gcc/ChangeLog | 9 ++ gcc/testsuite/gcc.dg/tree-ssa/pr68714.c | 9 ++ gcc/tree-ssa-reassoc.c | 163 ++++++++++++++++++++++++++++++-- 3 files changed, 173 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr68714.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac8b40d..b9fba23 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-03-14 Richard Henderson + + 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 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 0000000..741d311 --- /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 (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 *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: : ... @@ -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 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. */ -- 2.7.4