From: Richard Guenther Date: Sat, 28 Mar 2009 10:01:56 +0000 (+0000) Subject: re PR tree-optimization/37795 (if-combine doesn't optimize != after >= test) X-Git-Tag: releases/gcc-4.5.0~7103 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a254e44de7e7f417e3cdff485b27396e6bb16650;p=thirdparty%2Fgcc.git re PR tree-optimization/37795 (if-combine doesn't optimize != after >= test) 2009-03-28 Richard Guenther 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f327b671e89a..738e7db6f868 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2009-03-28 Richard Guenther + + 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 * tree-eh.c (inlinable_call_p): New function. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4ca91a22d980..2dbca3fa83b8 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 0ea9d9bfc2b2..41e5d7078af6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-03-28 Richard Guenther + + PR tree-optimization/37795 + * gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase. + 2009-03-28 Joseph Myers * 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 000000000000..fd2025092177 --- /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 335fd068540f..08048560cfb2 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; diff --git a/gcc/tree.h b/gcc/tree.h index 51fd7ec0c71b..9ff30a39e2d1 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -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