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 <[email protected]>
* 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