diff options
author | Sandra Loosemore <sandra@codesourcery.com> | 2010-05-08 11:53:59 -0400 |
---|---|---|
committer | Sandra Loosemore <sandra@gcc.gnu.org> | 2010-05-08 11:53:59 -0400 |
commit | 844381e5bc6eb515df838279303ac7843b68d39b (patch) | |
tree | 10331b08926ef42a8e2ee7f510365d174376f10a | |
parent | 4a79741bd29546a3f3d3722a29a62a1a8862523c (diff) | |
download | gcc-844381e5bc6eb515df838279303ac7843b68d39b.zip gcc-844381e5bc6eb515df838279303ac7843b68d39b.tar.gz gcc-844381e5bc6eb515df838279303ac7843b68d39b.tar.bz2 |
re PR middle-end/28685 (Multiple comparisons are not simplified)
2010-05-08 Sandra Loosemore <sandra@codesourcery.com>
PR middle-end/28685
gcc/
* tree-ssa-reassoc.c (eliminate_redundant_comparison): New function.
(optimize_ops_list): Call it.
gcc/testsuite/
* gcc.dg/pr28685-1.c: New file.
From-SVN: r159189
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr28685-1.c | 50 | ||||
-rw-r--r-- | gcc/tree-ssa-reassoc.c | 110 |
4 files changed, 170 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cb1661c..28fd31f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-05-08 Sandra Loosemore <sandra@codesourcery.com> + + PR middle-end/28685 + * tree-ssa-reassoc.c (eliminate_redundant_comparison): New function. + (optimize_ops_list): Call it. + 2010-05-08 Richard Guenther <rguenther@suse.de> PR tree-optimization/44030 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 66630e8..38501a7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-05-08 Sandra Loosemore <sandra@codesourcery.com> + + PR middle-end/28685 + * gcc.dg/pr28685-1.c: New file. + 2010-05-08 Richard Guenther <rguenther@suse.de> PR tree-optimization/44030 diff --git a/gcc/testsuite/gcc.dg/pr28685-1.c b/gcc/testsuite/gcc.dg/pr28685-1.c new file mode 100644 index 0000000..1d9d97e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr28685-1.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* Should produce <=. */ +int test1 (int a, int b) +{ + return (a < b || a == b); +} + +/* Should produce <=. */ +int test2 (int a, int b) +{ + int lt = a < b; + int eq = a == b; + + return (lt || eq); +} + +/* Should produce <= (just deleting redundant test). */ +int test3 (int a, int b) +{ + int lt = a <= b; + int eq = a == b; + + return (lt || eq); +} + +/* Should produce <= (operands reversed to test the swap logic). */ +int test4 (int a, int b) +{ + int lt = a < b; + int eq = b == a; + + return (lt || eq); +} + +/* Should produce constant 0. */ +int test5 (int a, int b) +{ + int lt = a < b; + int eq = a == b; + + return (lt && eq); +} + +/* { dg-final { scan-tree-dump-times " <= " 4 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-not " < " "optimized" } } */ +/* { dg-final { scan-tree-dump-not " == " "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index aa08085..6bdb57e 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -1215,6 +1215,113 @@ undistribute_ops_list (enum tree_code opcode, return changed; } +/* If OPCODE is BIT_IOR_EXPR or BIT_AND_EXPR and CURR is a comparison + expression, examine the other OPS to see if any of them are comparisons + of the same values, which we may be able to combine or eliminate. + For example, we can rewrite (a < b) | (a == b) as (a <= b). */ + +static bool +eliminate_redundant_comparison (enum tree_code opcode, + VEC (operand_entry_t, heap) **ops, + unsigned int currindex, + operand_entry_t curr) +{ + tree op1, op2; + enum tree_code lcode, rcode; + gimple def1, def2; + int i; + operand_entry_t oe; + + if (opcode != BIT_IOR_EXPR && opcode != BIT_AND_EXPR) + return false; + + /* Check that CURR is a comparison. */ + if (TREE_CODE (curr->op) != SSA_NAME) + return false; + def1 = SSA_NAME_DEF_STMT (curr->op); + if (!is_gimple_assign (def1)) + return false; + lcode = gimple_assign_rhs_code (def1); + if (TREE_CODE_CLASS (lcode) != tcc_comparison) + return false; + op1 = gimple_assign_rhs1 (def1); + op2 = gimple_assign_rhs2 (def1); + + /* Now look for a similar comparison in the remaining OPS. */ + for (i = currindex + 1; + VEC_iterate (operand_entry_t, *ops, i, oe); + i++) + { + tree t; + + if (TREE_CODE (oe->op) != SSA_NAME) + continue; + def2 = SSA_NAME_DEF_STMT (oe->op); + if (!is_gimple_assign (def2)) + continue; + rcode = gimple_assign_rhs_code (def2); + if (TREE_CODE_CLASS (rcode) != tcc_comparison) + continue; + if (operand_equal_p (op1, gimple_assign_rhs1 (def2), 0) + && operand_equal_p (op2, gimple_assign_rhs2 (def2), 0)) + ; + else if (operand_equal_p (op1, gimple_assign_rhs2 (def2), 0) + && operand_equal_p (op2, gimple_assign_rhs1 (def2), 0)) + rcode = swap_tree_comparison (rcode); + else + continue; + + /* If we got here, we have a match. See if we can combine the + two comparisons. */ + t = combine_comparisons (UNKNOWN_LOCATION, + (opcode == BIT_IOR_EXPR + ? TRUTH_OR_EXPR : TRUTH_AND_EXPR), + lcode, rcode, TREE_TYPE (curr->op), op1, op2); + if (!t) + continue; + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Equivalence: "); + print_generic_expr (dump_file, curr->op, 0); + fprintf (dump_file, " %s ", op_symbol_code (opcode)); + print_generic_expr (dump_file, oe->op, 0); + fprintf (dump_file, " -> "); + print_generic_expr (dump_file, t, 0); + fprintf (dump_file, "\n"); + } + + /* Now we can delete oe, as it has been subsumed by the new combined + expression t. */ + VEC_ordered_remove (operand_entry_t, *ops, i); + reassociate_stats.ops_eliminated ++; + + /* If t is the same as curr->op, we're done. Otherwise we must + replace curr->op with t. Special case is if we got a constant + back, in which case we add it to the end instead of in place of + the current entry. */ + if (TREE_CODE (t) == INTEGER_CST) + { + VEC_ordered_remove (operand_entry_t, *ops, currindex); + add_to_ops_vec (ops, t); + } + else if (TREE_CODE (t) != lcode) + { + tree tmpvar; + gimple sum; + enum tree_code subcode; + tree newop1; + tree newop2; + tmpvar = create_tmp_var (TREE_TYPE (t), NULL); + add_referenced_var (tmpvar); + extract_ops_from_tree (t, &subcode, &newop1, &newop2); + sum = build_and_add_sum (tmpvar, newop1, newop2, subcode); + curr->op = gimple_get_lhs (sum); + } + return true; + } + + return false; +} /* Perform various identities and other optimizations on the list of operand entries, stored in OPS. The tree code for the binary @@ -1276,7 +1383,8 @@ optimize_ops_list (enum tree_code opcode, if (eliminate_not_pairs (opcode, ops, i, oe)) return; if (eliminate_duplicate_pair (opcode, ops, &done, i, oe, oelast) - || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe))) + || (!done && eliminate_plus_minus_pair (opcode, ops, i, oe)) + || (!done && eliminate_redundant_comparison (opcode, ops, i, oe))) { if (done) return; |