This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[4.1 PATCH] Avoid endless recursion between negate_expr and fold_unary (PR middle-end/30286)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 29 Dec 2006 13:44:15 -0500
- Subject: [4.1 PATCH] Avoid endless recursion between negate_expr and fold_unary (PR middle-end/30286)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
This testcase was fixed in 4.2+ with the PR27116 patch.
So, either we want to backport that and patches that it depends on,
or the following should fix this case as well.
If negate_expr doesn't optimize negation of an INTEGER_CST or REAL_CST,
it falls back to the default fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t),
which in turn calls fold_unary. As t here is known to be INTEGER_CST
or REAL_CST, all that it does is:
case NEGATE_EXPR:
if (negate_expr_p (arg0))
return fold_convert (type, negate_expr (arg0));
/* Convert - (~A) to A + 1. */
if (INTEGRAL_TYPE_P (type) && TREE_CODE (arg0) == BIT_NOT_EXPR)
return fold_build2 (PLUS_EXPR, type, TREE_OPERAND (arg0, 0),
build_int_cst (type, 1));
return NULL_TREE;
so either recurses again with the same argument, or returns NULL
(because arg0 is certainly not BIT_NOT_EXPR). Just calling
build1 instead of fold_build1 will make the endless recursion impossible,
while won't change behavior in the rest of cases.
2006-12-29 Jakub Jelinek <jakub@redhat.com>
PR middle-end/30286
* fold-const.c (negate_expr): Don't call fold_build1
for INTEGER_CST or REAL_CST.
* gcc.dg/pr30286.c: New test.
--- gcc/fold-const.c.jj 2006-11-23 08:39:42.000000000 +0100
+++ gcc/fold-const.c 2006-12-29 19:21:57.000000000 +0100
@@ -1048,14 +1048,14 @@ negate_expr (tree t)
|| TYPE_UNSIGNED (type)
|| ! flag_trapv)
return tem;
- break;
+ return build1 (NEGATE_EXPR, type, t);
case REAL_CST:
tem = fold_negate_const (t, type);
/* Two's complement FP formats, such as c4x, may overflow. */
if (! TREE_OVERFLOW (tem) || ! flag_trapping_math)
return fold_convert (type, tem);
- break;
+ return build1 (NEGATE_EXPR, type, t);
case COMPLEX_CST:
{
--- gcc/testsuite/gcc.dg/pr30286.c.jj 2006-12-29 19:07:50.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr30286.c 2006-12-29 19:06:47.000000000 +0100
@@ -0,0 +1,37 @@
+/* PR middle-end/30286 */
+/* { dg-do run } */
+/* { dg-options "-O2 -ftrapv" } */
+
+extern void abort (void);
+struct S { struct S *s; };
+struct T { struct S *t[25]; };
+
+void
+__attribute__((noinline))
+foo (int i, struct T *x, struct S *y)
+{
+ int j;
+ for (j = 14; j > i; j--)
+ x->t[j] = y->s;
+}
+
+int
+main (void)
+{
+ struct S s;
+ struct T t;
+ int i;
+
+ s.s = &s;
+ __builtin_memset (&t, 0, sizeof (t));
+ foo (6, &t, &s);
+ for (i = 0; i < 25; i++)
+ if (t.t[i] != ((i > 6 && i <= 14) ? &s : (struct S *) 0))
+ abort ();
+ __builtin_memset (&t, 0, sizeof (t));
+ foo (-1, &t, &s);
+ for (i = 0; i < 25; i++)
+ if (t.t[i] != ((i >= 0 && i <= 14) ? &s : (struct S *) 0))
+ abort ();
+ return 0;
+}
Jakub