diff mbox

PR49720, infinite recursion in RTX simplification

Message ID 4EA8FA03.10805@codesourcery.com
State New
Headers show

Commit Message

Chung-Lin Tang Oct. 27, 2011, 6:28 a.m. UTC
Hi,
this patch is for a specific case in RTX simplification where infinite
recursion ensues, causing the out-of-stack segfault in PR49720.

Tracking back the origin of this bug, the exact revision causing this
was rev.92429, back in 2004.

The clause in simplify-rtx.c:simplify_relational_operation_1(),
transforming X + cst1 == cst2 into X == cst2 - cst1 can cause an
oscillating recursive cycle like this:

  A + B == C    <===>   C - B == A

When all A, B, and C are CONSTANT_P, but not simplifiable (in the PR
testcase, they are all SYMBOL_REFs).  The switching of XEXP(op0,1) to
the other side of the equation, plus commutative canonicalizing then
completes the cycle.

This can be solved by using simplify_binary_relation() and returning
NULL_RTX when simplification of the constant PLUS/MINUS fails, but I'm
not sure that further working on X == CST2-CST1 will never yield more
optimization, so the patch here just tries to plug the recursion hole
for the exact condition.

Bootstrapped and tested on i686 and x86_64 without regressions. Is this
okay for trunk?

Thanks,
Chung-Lin

2011-10-27  Chung-Lin Tang  <cltang@codesourcery.com>

	PR rtl-optimization/49720
	* simplify-rtx.c (simplify_relational_operation_1): Detect
	infinite recursion condition in "(eq/ne (plus x cst1) cst2)
	simplifies to (eq/ne x (cst2 - cst1))" case.

	testsuite/
	* g++.dg/torture/pr49720.C: New test.

Comments

Eric Botcazou Oct. 27, 2011, 10:39 p.m. UTC | #1
> 2011-10-27  Chung-Lin Tang  <cltang@codesourcery.com>
>
> 	PR rtl-optimization/49720
> 	* simplify-rtx.c (simplify_relational_operation_1): Detect
> 	infinite recursion condition in "(eq/ne (plus x cst1) cst2)
> 	simplifies to (eq/ne x (cst2 - cst1))" case.
>
> 	testsuite/
> 	* g++.dg/torture/pr49720.C: New test.

OK, thanks.
H.J. Lu Dec. 15, 2011, 10 p.m. UTC | #2
On Thu, Oct 27, 2011 at 3:39 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
>> 2011-10-27  Chung-Lin Tang  <cltang@codesourcery.com>
>>
>>       PR rtl-optimization/49720
>>       * simplify-rtx.c (simplify_relational_operation_1): Detect
>>       infinite recursion condition in "(eq/ne (plus x cst1) cst2)
>>       simplifies to (eq/ne x (cst2 - cst1))" case.
>>
>>       testsuite/
>>       * g++.dg/torture/pr49720.C: New test.
>
> OK, thanks.
>

This also fails on 4.6 branch.  Can we move it to 4.6 branch?

Thanks.
Eric Botcazou Dec. 15, 2011, 10:45 p.m. UTC | #3
> This also fails on 4.6 branch.  Can we move it to 4.6 branch?

Sure.
diff mbox

Patch

Index: trunk/gcc/simplify-rtx.c
===================================================================
--- trunk/gcc/simplify-rtx.c	(revision 180421)
+++ trunk/gcc/simplify-rtx.c	(working copy)
@@ -4352,10 +4352,20 @@ 
     {
       rtx x = XEXP (op0, 0);
       rtx c = XEXP (op0, 1);
+      enum rtx_code invcode = op0code == PLUS ? MINUS : PLUS;
+      rtx tem = simplify_gen_binary (invcode, cmp_mode, op1, c);
 
-      c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS,
-			       cmp_mode, op1, c);
-      return simplify_gen_relational (code, mode, cmp_mode, x, c);
+      /* Detect an infinite recursive condition, where we oscillate at this
+	 simplification case between:
+	    A + B == C  <--->  C - B == A,
+	 where A, B, and C are all constants with non-simplifiable expressions,
+	 usually SYMBOL_REFs.  */
+      if (GET_CODE (tem) == invcode
+	  && CONSTANT_P (x)
+	  && rtx_equal_p (c, XEXP (tem, 1)))
+	return NULL_RTX;
+
+      return simplify_gen_relational (code, mode, cmp_mode, x, tem);
     }
 
   /* (ne:SI (zero_extract:SI FOO (const_int 1) BAR) (const_int 0))) is
Index: trunk/gcc/testsuite/g++.dg/torture/pr49720.C
===================================================================
--- trunk/gcc/testsuite/g++.dg/torture/pr49720.C	(revision 0)
+++ trunk/gcc/testsuite/g++.dg/torture/pr49720.C	(revision 0)
@@ -0,0 +1,8 @@ 
+/* { dg-do compile } */
+
+extern char t_start[], t_end[], t_size[];
+bool foo (void)
+{
+  long size = reinterpret_cast<long>(t_size);
+  return (size == t_end - t_start);
+}