Hi!

On Fri, May 12, 2017 at 09:48:28PM +0200, Jakub Jelinek wrote:
> On Fri, May 12, 2017 at 09:37:27PM +0200, Marek Polacek wrote:
> > @@ -565,6 +564,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool 
> > *maybe_const_operands,
> >      appropriate in any particular case.  */
> >        gcc_unreachable ();
> >  
> > +    case SAVE_EXPR:
> > +      /* Make sure to fold the contents of a SAVE_EXPR exactly once.  */
> > +      if (!SAVE_EXPR_FOLDED_P (expr))
> > +   {
> > +     op0 = TREE_OPERAND (expr, 0);
> > +     op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
> > +                                  maybe_const_itself, for_int_const);
> > +     /* Don't wrap the folded tree in a SAVE_EXPR if we don't
> > +        have to.  */
> > +     if (tree_invariant_p (op0))
> > +       ret = op0;
> > +     else
> > +       {
> > +         TREE_OPERAND (expr, 0) = op0;
> > +         SAVE_EXPR_FOLDED_P (expr) = true;
> > +       }
> > +   }
> 
> Wouldn't it be better to guard with if (!SAVE_EXPR_FOLDED_P (expr))
> only c_fully_fold_internal recursion on the operand
> and then use if (tree_invariant_p (op0)) unconditionally?

After discussions on IRC with Marek, we concluded the above is bad, because
if there is a huge SAVE_EXPR operand that c_fully_fold_internal folds into
an invariant (worse if it contains many other SAVE_EXPRs with such
properties), the current trunk code will fold it over and over again.

Fixed thusly, acked by Marek on IRC, bootstrapped/regtested on x86_64-linux
and i686-linux, committed to trunk.

2017-05-22  Jakub Jelinek  <ja...@redhat.com>

        * c-fold.c (c_fully_fold_internal): Save the c_fully_fold_internal
        result for SAVE_EXPR operand and set SAVE_EXPR_FOLDED_P even if
        it returned invariant.  Call tree_invariant_p unconditionally
        afterwards to decide whether to return expr or op0.

--- gcc/c/c-fold.c      2017-05-22 10:49:38.669161353 +0200
+++ gcc/c/c-fold.c      2017-05-22 18:09:49.358107221 +0200
@@ -566,21 +566,17 @@ c_fully_fold_internal (tree expr, bool i
 
     case SAVE_EXPR:
       /* Make sure to fold the contents of a SAVE_EXPR exactly once.  */
+      op0 = TREE_OPERAND (expr, 0);
       if (!SAVE_EXPR_FOLDED_P (expr))
        {
-         op0 = TREE_OPERAND (expr, 0);
          op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
                                       maybe_const_itself, for_int_const);
-         /* Don't wrap the folded tree in a SAVE_EXPR if we don't
-            have to.  */
-         if (tree_invariant_p (op0))
-           ret = op0;
-         else
-           {
-             TREE_OPERAND (expr, 0) = op0;
-             SAVE_EXPR_FOLDED_P (expr) = true;
-           }
+         TREE_OPERAND (expr, 0) = op0;
+         SAVE_EXPR_FOLDED_P (expr) = true;
        }
+      /* Return the SAVE_EXPR operand if it is invariant.  */
+      if (tree_invariant_p (op0))
+       ret = op0;
       goto out;
 
     default:


        Jakub

Reply via email to