This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR37795
On Sun, 12 Oct 2008, Andrew Thomas Pinski wrote:
>
>
> Sent from my iPhone
>
> On Oct 12, 2008, at 11:50 AM, Richard Guenther <rguenther@suse.de> wrote:
>
> >
> > This fixes PR37795, a missed optimization with optimizing consecutive
> > (and-ed) tests as we already do for or-ed ones.
> >
> Does this do the correct thing for floating point comparisons? That is it if
> we had a >= b and b < a does not change as NaN would give true and the false.
This variant just re-uses the logic present in fold-const for this.
Bootstrapped and tested on x86_64-unknown-linux-gnu.
Richard.
2008-10-12 Richard Guenther <rguenther@suse.de>
PR tree-optimization/37795
* tree.h (combine_comparisons): Declare.
* tree.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.
Index: gcc/tree-ssa-ifcombine.c
===================================================================
*** gcc/tree-ssa-ifcombine.c.orig 2008-09-09 13:18:48.000000000 +0200
--- gcc/tree-ssa-ifcombine.c 2008-10-13 11:12:07.000000000 +0200
*************** ifcombine_ifandif (basic_block inner_con
*** 380,385 ****
--- 380,422 ----
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_AND_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;
}
*************** ifcombine_iforif (basic_block inner_cond
*** 502,543 ****
{
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
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;
--- 539,551 ----
{
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_OR_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;
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c 2008-10-13 11:08:31.000000000 +0200
***************
*** 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" } } */
Index: gcc/tree.h
===================================================================
*** gcc/tree.h.orig 2008-10-13 10:58:05.000000000 +0200
--- gcc/tree.h 2008-10-13 11:18:09.000000000 +0200
*************** extern bool tree_call_nonnegative_warnv_
*** 4837,4842 ****
--- 4837,4844 ----
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);
/* In builtins.c */
extern tree fold_call_expr (tree, bool);
Index: gcc/fold-const.c
===================================================================
*** gcc/fold-const.c.orig 2008-10-13 11:32:36.000000000 +0200
--- gcc/fold-const.c 2008-10-13 11:32:43.000000000 +0200
*************** static tree associate_trees (tree, tree,
*** 103,110 ****
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 truth_value_p (enum tree_code);
static int operand_equal_for_comparison_p (tree, tree, tree);
static int twoval_comparison_p (tree, tree *, tree *, int *);
--- 103,108 ----