diff options
author | Richard Guenther <rguenther@suse.de> | 2009-03-28 10:01:56 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2009-03-28 10:01:56 +0000 |
commit | a254e44de7e7f417e3cdff485b27396e6bb16650 (patch) | |
tree | 41f27c9d3a60891996ed9cd47be2243a484783fc | |
parent | a8ee227c046930794867e48c6478b0b04e3bd137 (diff) | |
download | gcc-a254e44de7e7f417e3cdff485b27396e6bb16650.zip gcc-a254e44de7e7f417e3cdff485b27396e6bb16650.tar.gz gcc-a254e44de7e7f417e3cdff485b27396e6bb16650.tar.bz2 |
re PR tree-optimization/37795 (if-combine doesn't optimize != after >= test)
2009-03-28 Richard Guenther <rguenther@suse.de>
PR tree-optimization/37795
* tree.h (combine_comparisons): Declare.
* fold-const.c (combine_comparisons): Export.
* tree-ssa-ifcombine.c (ifcombine_ifandif): Optimize two successive
comparisons.
(ifcombine_iforif): Use combine_comparisons.
* gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase.
From-SVN: r145170
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/fold-const.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c | 15 | ||||
-rw-r--r-- | gcc/tree-ssa-ifcombine.c | 74 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
6 files changed, 72 insertions, 35 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f327b67..738e7db 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-03-28 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/37795 + * tree.h (combine_comparisons): Declare. + * fold-const.c (combine_comparisons): Export. + * tree-ssa-ifcombine.c (ifcombine_ifandif): Optimize two successive + comparisons. + (ifcombine_iforif): Use combine_comparisons. + 2009-03-28 Jan Hubicka <jh@suse.cz> * tree-eh.c (inlinable_call_p): New function. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4ca91a2..2dbca3f 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -103,8 +103,6 @@ static tree associate_trees (tree, tree, enum tree_code, tree); static tree const_binop (enum tree_code, tree, tree, int); static enum comparison_code comparison_to_compcode (enum tree_code); static enum tree_code compcode_to_comparison (enum comparison_code); -static tree combine_comparisons (enum tree_code, enum tree_code, - enum tree_code, tree, tree, tree); static int operand_equal_for_comparison_p (tree, tree, tree); static int twoval_comparison_p (tree, tree *, tree *, int *); static tree eval_subst (tree, tree, tree, tree, tree); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0ea9d9b..41e5d70 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-03-28 Richard Guenther <rguenther@suse.de> + + PR tree-optimization/37795 + * gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase. + 2009-03-28 Joseph Myers <joseph@codesourcery.com> * g++.old-deja/g++.ext/attrib5.C, g++.old-deja/g++.jason/thunk3.C, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c new file mode 100644 index 0000000..fd20250 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int test1 (int i, int j) +{ + if (i >= j) + if (i != j) + return 0; + return -1; +} + +/* The above should be optimized to a i > j test by ifcombine. */ + +/* { dg-final { scan-tree-dump " > " "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index 335fd06..0804856 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -380,6 +380,43 @@ ifcombine_ifandif (basic_block inner_cond_bb, basic_block outer_cond_bb) return true; } + /* See if we have two comparisons that we can merge into one. */ + else if (TREE_CODE_CLASS (gimple_cond_code (inner_cond)) == tcc_comparison + && TREE_CODE_CLASS (gimple_cond_code (outer_cond)) == tcc_comparison + && operand_equal_p (gimple_cond_lhs (inner_cond), + gimple_cond_lhs (outer_cond), 0) + && operand_equal_p (gimple_cond_rhs (inner_cond), + gimple_cond_rhs (outer_cond), 0)) + { + enum tree_code code1 = gimple_cond_code (inner_cond); + enum tree_code code2 = gimple_cond_code (outer_cond); + tree t; + + if (!(t = combine_comparisons (TRUTH_ANDIF_EXPR, code1, code2, + boolean_type_node, + gimple_cond_lhs (outer_cond), + gimple_cond_rhs (outer_cond)))) + return false; + t = canonicalize_cond_expr_cond (t); + if (!t) + return false; + gimple_cond_set_condition_from_tree (inner_cond, t); + update_stmt (inner_cond); + + /* Leave CFG optimization to cfg_cleanup. */ + gimple_cond_set_condition_from_tree (outer_cond, boolean_true_node); + update_stmt (outer_cond); + + if (dump_file) + { + fprintf (dump_file, "optimizing two comparisons to "); + print_generic_expr (dump_file, t, 0); + fprintf (dump_file, "\n"); + } + + return true; + } + return false; } @@ -502,42 +539,13 @@ ifcombine_iforif (basic_block inner_cond_bb, basic_block outer_cond_bb) { enum tree_code code1 = gimple_cond_code (inner_cond); enum tree_code code2 = gimple_cond_code (outer_cond); - enum tree_code code; tree t; -#define CHK(a,b) ((code1 == a ## _EXPR && code2 == b ## _EXPR) \ - || (code2 == a ## _EXPR && code1 == b ## _EXPR)) - /* Merge the two condition codes if possible. */ - if (code1 == code2) - code = code1; - else if (CHK (EQ, LT)) - code = LE_EXPR; - else if (CHK (EQ, GT)) - code = GE_EXPR; - else if (CHK (LT, LE)) - code = LE_EXPR; - else if (CHK (GT, GE)) - code = GE_EXPR; - else if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (inner_cond))) - || flag_unsafe_math_optimizations) - { - if (CHK (LT, GT)) - code = NE_EXPR; - else if (CHK (LT, NE)) - code = NE_EXPR; - else if (CHK (GT, NE)) - code = NE_EXPR; - else - return false; - } - /* We could check for combinations leading to trivial true/false. */ - else + if (!(t = combine_comparisons (TRUTH_ORIF_EXPR, code1, code2, + boolean_type_node, + gimple_cond_lhs (outer_cond), + gimple_cond_rhs (outer_cond)))) return false; -#undef CHK - - /* Do it. */ - t = fold_build2 (code, boolean_type_node, gimple_cond_lhs (outer_cond), - gimple_cond_rhs (outer_cond)); t = canonicalize_cond_expr_cond (t); if (!t) return false; @@ -4853,6 +4853,8 @@ extern bool tree_call_nonnegative_warnv_p (tree, tree, tree, tree, bool *); extern bool tree_expr_nonzero_warnv_p (tree, bool *); extern bool fold_real_zero_addition_p (const_tree, const_tree, int); +extern tree combine_comparisons (enum tree_code, enum tree_code, + enum tree_code, tree, tree, tree); /* Return nonzero if CODE is a tree code that represents a truth value. */ static inline bool |