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;
}