OSDN Git Service

2007-02-09 Zdenek Dvorak <dvorakz@suse.cz>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 13:29:11 +0000 (13:29 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Feb 2007 13:29:11 +0000 (13:29 +0000)
Richard Guenther  <rguenther@suse.de>

PR middle-end/23361
* fold-const.c (fold_comparison): Handle obfuscated comparisons
against INT_MIN/INT_MAX.
* tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump
file if a loop is removed.

* gcc.dg/fold-compare-3.c: New testcase.
* gcc.dg/tree-ssa/loop-24.c: Likewise.

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

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/fold-compare-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/loop-24.c [new file with mode: 0644]
gcc/tree-ssa-loop-ivcanon.c

index 777ca63..cd1f196 100644 (file)
@@ -1,3 +1,12 @@
+2007-02-09  Zdenek Dvorak  <dvorakz@suse.cz>
+       Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/23361
+       * fold-const.c (fold_comparison): Handle obfuscated comparisons
+       against INT_MIN/INT_MAX.
+       * tree-ssa-loop-ivcanon.c (remove_empty_loop): Print to dump
+       file if a loop is removed.
+
 2007-02-09  Joseph Myers  <joseph@codesourcery.com>
 
        * calls.c (store_one_arg): Pass correct alignment to
index 0b37a0f..d20d78f 100644 (file)
@@ -8043,6 +8043,40 @@ fold_comparison (enum tree_code code, tree type, tree op0, tree op1)
 
       lhs = fold_build2 (lhs_add ? PLUS_EXPR : MINUS_EXPR,
                         TREE_TYPE (arg1), const2, const1);
+
+      /* If the constant operation overflowed this can be
+        simplified as a comparison against INT_MAX/INT_MIN.  */
+      if (TREE_CODE (lhs) == INTEGER_CST
+         && TREE_OVERFLOW (lhs))
+       {
+         int const1_sgn = tree_int_cst_sgn (const1);
+         enum tree_code code2 = code;
+
+         /* Get the sign of the constant on the lhs if the
+            operation were VARIABLE + CONST1.  */
+         if (TREE_CODE (arg0) == MINUS_EXPR)
+           const1_sgn = -const1_sgn;
+
+         /* The sign of the constant determines if we overflowed
+            INT_MAX (const1_sgn == -1) or INT_MIN (const1_sgn == 1).
+            Canonicalize to the INT_MIN overflow by swapping the comparison
+            if necessary.  */
+         if (const1_sgn == -1)
+           code2 = swap_tree_comparison (code);
+
+         /* We now can look at the canonicalized case
+              VARIABLE + 1  CODE2  INT_MIN
+            and decide on the result.  */
+         if (code2 == LT_EXPR
+             || code2 == LE_EXPR
+             || code2 == EQ_EXPR)
+           return omit_one_operand (type, boolean_false_node, variable);
+         else if (code2 == NE_EXPR
+                  || code2 == GE_EXPR
+                  || code2 == GT_EXPR)
+           return omit_one_operand (type, boolean_true_node, variable);
+       }
+
       if (TREE_CODE (lhs) == TREE_CODE (arg1)
          && (TREE_CODE (lhs) != INTEGER_CST
              || !TREE_OVERFLOW (lhs)))
index 5608be0..8575ad5 100644 (file)
@@ -1,3 +1,10 @@
+2007-02-09  Zdenek Dvorak  <dvorakz@suse.cz>
+       Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/23361
+       * gcc.dg/fold-compare-3.c: New testcase.
+       * gcc.dg/tree-ssa/loop-24.c: Likewise.
+
 2007-02-09  Uros Bizjak  <ubizjak@gmail.com>
 
        * gcc.dg/pr26570.c: Clean up coverage files.
diff --git a/gcc/testsuite/gcc.dg/fold-compare-3.c b/gcc/testsuite/gcc.dg/fold-compare-3.c
new file mode 100644 (file)
index 0000000..011bf47
--- /dev/null
@@ -0,0 +1,159 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cleanup_cfg1" } */
+
+#include <limits.h>
+
+void this_comparison_is_false (void);
+void this_comparison_is_true (void);
+void this_comparison_is_not_decidable (void);
+
+void bla1eq (int var)
+{
+  if (var + 10 == INT_MIN + 9)
+    this_comparison_is_false ();
+}
+
+void bla2eq (int var)
+{
+  if (var + 10 == INT_MIN + 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3eq (int var)
+{
+  if (var - 10 == INT_MAX - 9)
+    this_comparison_is_false ();
+}
+
+void bla4eq (int var)
+{
+  if (var - 10 == INT_MAX - 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla1ne (int var)
+{
+  if (var + 10 != INT_MIN + 9)
+    this_comparison_is_true ();
+}
+
+void bla2ne (int var)
+{
+  if (var + 10 != INT_MIN + 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3ne (int var)
+{
+  if (var - 10 != INT_MAX - 9)
+    this_comparison_is_true ();
+}
+
+void bla4ne (int var)
+{
+  if (var - 10 != INT_MAX - 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla1lt (int var)
+{
+  if (var + 10 < INT_MIN + 10)
+    this_comparison_is_false ();
+}
+
+void bla2lt (int var)
+{
+  if (var + 10 < INT_MIN + 11)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3lt (int var)
+{
+  if (var - 10 < INT_MAX - 9)
+    this_comparison_is_true ();
+}
+
+void bla4lt (int var)
+{
+  if (var - 10 < INT_MAX - 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla1le (int var)
+{
+  if (var + 10 <= INT_MIN + 9)
+    this_comparison_is_false ();
+}
+
+void bla2le (int var)
+{
+  if (var + 10 <= INT_MIN + 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3le (int var)
+{
+  if (var - 10 <= INT_MAX - 10)
+    this_comparison_is_true ();
+}
+
+void bla4le (int var)
+{
+  if (var - 10 <= INT_MAX - 11)
+    this_comparison_is_not_decidable ();
+}
+
+void bla1gt (int var)
+{
+  if (var + 10 > INT_MIN + 9)
+    this_comparison_is_true ();
+}
+
+void bla2gt (int var)
+{
+  if (var + 10 > INT_MIN + 10)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3gt (int var)
+{
+  if (var - 10 > INT_MAX - 10)
+    this_comparison_is_false ();
+}
+
+void bla4gt (int var)
+{
+  if (var - 10 > INT_MAX - 11)
+    this_comparison_is_not_decidable ();
+}
+
+void bla1ge (int var)
+{
+  if (var + 10 >= INT_MIN + 10)
+    this_comparison_is_true ();
+}
+
+void bla2ge (int var)
+{
+  if (var + 10 >= INT_MIN + 11)
+    this_comparison_is_not_decidable ();
+}
+
+void bla3ge (int var)
+{
+  if (var - 11 >= INT_MAX - 10)
+    this_comparison_is_false ();
+}
+
+void bla4ge (int var)
+{
+  if (var - 10 >= INT_MAX - 10)
+    this_comparison_is_not_decidable ();
+}
+
+/* { dg-final { scan-tree-dump-times "this_comparison_is_false" 0 "cleanup_cfg1" } } */
+/* { dg-final { scan-tree-dump-times "this_comparison_is_true" 6 "cleanup_cfg1" } } */
+/* { dg-final { scan-tree-dump-times "this_comparison_is_not_decidable" 12 "cleanup_cfg1" } } */
+/* { dg-final { scan-tree-dump-times "if " 12 "cleanup_cfg1" } } */
+
+/* { dg-final { cleanup-tree-dump "cleanup_cfg1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c
new file mode 100644 (file)
index 0000000..dfad30d
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-overflow -fdump-tree-empty" } */
+
+void foo(int a, int b)
+{ for(;a!=b;a+=4); }
+
+void foo2(int a, int b)
+{ for(;a<b;a+=4); }
+
+void foo3(int*a, int* b)
+{ for(;a<b;a++); }
+
+void foo4(int*a, int*b)
+{ for(;a!=b;a++); }
+
+/* { dg-final { scan-tree-dump-times "Removing empty loop" 4 "empty" } } */
+/* { dg-final { cleanup-tree-dump "empty" } } */
index acc8cf3..80ac155 100644 (file)
@@ -480,6 +480,9 @@ remove_empty_loop (struct loop *loop)
   unsigned n_before, freq_in, freq_h;
   gcov_type exit_count = exit->count;
 
+  if (dump_file)
+    fprintf (dump_file, "Removing empty loop %d\n", loop->num);
+
   non_exit = EDGE_SUCC (exit->src, 0);
   if (non_exit == exit)
     non_exit = EDGE_SUCC (exit->src, 1);