]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/37795 (if-combine doesn't optimize != after >= test)
authorRichard Guenther <rguenther@suse.de>
Sat, 28 Mar 2009 10:01:56 +0000 (10:01 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Sat, 28 Mar 2009 10:01:56 +0000 (10:01 +0000)
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.

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

From-SVN: r145170

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 f327b671e89ac728d95209da29f5859a28bc6491..738e7db6f868a3517641b93cec3fb098111ec54d 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 4ca91a22d980123455dce4cc3200897d06afa9d9..2dbca3fa83b82656dc141a0de40a891ac26424e0 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 0ea9d9bfc2b2e12d48e1ad1b0e12c7251bd49b94..41e5d7078af6fe5d11fcc284de29acc5df3ba116 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 335fd068540f405febcbce13afcf79455616c584..08048560cfb2b383e85b06c212b8403a6e8ef3c5 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 51fd7ec0c71b6fcd9432199177c60c284b2971db..9ff30a39e2d1901345b5db4a0d85a1f2b4175ebc 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