This patch is a followup to the patch Sandra Loosemore made to fix PR50380 (see (http://gcc.gnu.org/ml/gcc-patches/2011-12/msg01402.html). That patch only detects fixed points, but Joseph Myers found a testcase which creates a cycle of length 2, causing find_comparison_args to stall even with the earlier patch.

This patch uses a pointer_set to detect cycles of any length and adds the new testcase to the test. I have successfully run bootstrap and regression tests. Okay to commit to mainline?

Thanks,

Andrew

Index: ChangeLog
===================================================================
--- ChangeLog   (revision 187630)
+++ ChangeLog   (working copy)
@@ -1,3 +1,7 @@
+2012-05-17  Andrew Jenner  <and...@codesourcery.com>
+
+       * cse.c (find_comparison_args): Check for cycles of any length.
+
 2012-05-17  Manuel López-Ibáñez  <m...@gcc.gnu.org>
 
        * opts.c (common_handle_option): -pedantic-errors enables -Wpedantic.
Index: testsuite/gcc.c-torture/compile/pr50380.c
===================================================================
--- testsuite/gcc.c-torture/compile/pr50380.c   (revision 187630)
+++ testsuite/gcc.c-torture/compile/pr50380.c   (working copy)
@@ -10,3 +10,11 @@ void foo (const unsigned char y)
    ((void) (__builtin_expect((!! y == y), 1) ? 0 : (fail (), 0)));
    x = ! y;
 }
+
+int foo2 (int arg)
+{
+  if (arg != !arg)
+    fail ();
+  if (arg)
+    fail ();
+}
Index: testsuite/ChangeLog
===================================================================
--- testsuite/ChangeLog (revision 187630)
+++ testsuite/ChangeLog (working copy)
@@ -1,3 +1,7 @@
+2012-05-17  Andrew Jenner  <and...@codesourcery.com>
+
+       * gcc.c-torture/compile/pr50380.c: Add code to cause cycle of length 2.
+
 2012-05-17  Paolo Carlini  <paolo.carl...@oracle.com>
 
        PR c++/53371
Index: cse.c
===================================================================
--- cse.c       (revision 187630)
+++ cse.c       (working copy)
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3.  
 #include "tree-pass.h"
 #include "df.h"
 #include "dbgcnt.h"
+#include "pointer-set.h"
 
 /* The basic idea of common subexpression elimination is to go
    through the code, keeping a record of expressions that would
@@ -2905,6 +2906,7 @@ find_comparison_args (enum rtx_code code
                      enum machine_mode *pmode1, enum machine_mode *pmode2)
 {
   rtx arg1, arg2;
+  struct pointer_set_t *visited = pointer_set_create ();
 
   arg1 = *parg1, arg2 = *parg2;
 
@@ -2993,10 +2995,8 @@ find_comparison_args (enum rtx_code code
          if (! exp_equiv_p (p->exp, p->exp, 1, false))
            continue;
 
-         /* If it's the same comparison we're already looking at, skip it.  */
-         if (COMPARISON_P (p->exp)
-             && XEXP (p->exp, 0) == arg1
-             && XEXP (p->exp, 1) == arg2)
+         /* If it's a comparison we've used before, skip it.  */
+         if (pointer_set_contains (visited, p->exp))
            continue;
 
          if (GET_CODE (p->exp) == COMPARE
@@ -3070,6 +3070,8 @@ find_comparison_args (enum rtx_code code
       else if (COMPARISON_P (x))
        code = GET_CODE (x);
       arg1 = XEXP (x, 0), arg2 = XEXP (x, 1);
+
+      pointer_set_insert (visited, x);
     }
 
   /* Return our results.  Return the modes from before fold_rtx
@@ -3077,6 +3079,7 @@ find_comparison_args (enum rtx_code code
   *pmode1 = GET_MODE (arg1), *pmode2 = GET_MODE (arg2);
   *parg1 = fold_rtx (arg1, 0), *parg2 = fold_rtx (arg2, 0);
 
+  pointer_set_destroy (visited);
   return code;
 }
 

Reply via email to