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]

[PATCH] Fix PR37795


This fixes PR37795, a missed optimization with optimizing consecutive
(and-ed) tests as we already do for or-ed ones.

Bootstrapped and tested on x86_64-unknown-linux-gnu, queued for 4.5.

Richard.


2008-10-12  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/37795
	* tree-ssa-ifcombine.c (ifcombine_ifandif): Optimize two successive
	comparisons.

	* gcc.dg/tree-ssa/ssa-ifcombine-7.c: New testcase.

Index: gcc/tree-ssa-ifcombine.c
===================================================================
*** gcc/tree-ssa-ifcombine.c	(revision 141074)
--- gcc/tree-ssa-ifcombine.c	(working copy)
*************** ifcombine_ifandif (basic_block inner_con
*** 380,385 ****
--- 380,441 ----
        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);
+       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, LE))
+ 	code = EQ_EXPR;
+       else if (CHK (EQ, GE))
+ 	code = EQ_EXPR;
+       else if (CHK (NE, LE))
+ 	code = LT_EXPR;
+       else if (CHK (NE, GE))
+ 	code = GT_EXPR;
+       else if (CHK (LE, GE))
+ 	code = EQ_EXPR;
+       /* 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;
+       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;
  }
  
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c	(revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c	(revision 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" } } */


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