2009-03-28 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Mar 2009 10:01:56 +0000 (10:01 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Mar 2009 10:01:56 +0000 (10:01 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@145170 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c [new file with mode: 0644]
gcc/tree-ssa-ifcombine.c
gcc/tree.h

index f327b67..738e7db 100644 (file)
@@ -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.
index 4ca91a2..2dbca3f 100644 (file)
@@ -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);
index 0ea9d9b..41e5d70 100644 (file)
@@ -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 (file)
index 0000000..fd20250
--- /dev/null
@@ -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 335fd06..0804856 100644 (file)
@@ -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;
index 51fd7ec..9ff30a3 100644 (file)
@@ -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