This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 ----


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]