aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 1b6dc79..b86a339 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1549,20 +1549,33 @@ save_expr (expr)
tree expr;
{
tree t = fold (expr);
+ tree inner;
/* We don't care about whether this can be used as an lvalue in this
context. */
while (TREE_CODE (t) == NON_LVALUE_EXPR)
t = TREE_OPERAND (t, 0);
+
+ /* If we have simple operations applied to a SAVE_EXPR or to a SAVE_EXPR and
+ a constant, it will be more efficient to not make another SAVE_EXPR since
+ it will allow better simplification and GCSE will be able to merge the
+ computations if they actualy occur. */
+ for (inner = t;
+ (TREE_CODE_CLASS (TREE_CODE (inner)) == '1'
+ || (TREE_CODE_CLASS (TREE_CODE (inner)) == '2'
+ && TREE_CONSTANT (TREE_OPERAND (inner, 1))));
+ inner = TREE_OPERAND (inner, 0))
+ ;
+
/* If the tree evaluates to a constant, then we don't want to hide that
fact (i.e. this allows further folding, and direct checks for constants).
However, a read-only object that has side effects cannot be bypassed.
Since it is no problem to reevaluate literals, we just return the
literal node. */
-
- if (TREE_CONSTANT (t) || (TREE_READONLY (t) && ! TREE_SIDE_EFFECTS (t))
- || TREE_CODE (t) == SAVE_EXPR || TREE_CODE (t) == ERROR_MARK)
+ if (TREE_CONSTANT (inner)
+ || (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
+ || TREE_CODE (inner) == SAVE_EXPR || TREE_CODE (inner) == ERROR_MARK)
return t;
/* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since