[4.1 PATCH] Avoid endless recursion between negate_expr and fold_unary (PR middle-end/30286)

Jakub Jelinek jakub@redhat.com
Fri Dec 29 18:44:00 GMT 2006


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



More information about the Gcc-patches mailing list