tree.c (skip_simple_arithmetics_at, [...]): New functions.

* tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions.
        (save_expr): Replace loop by call to skip_simple_arithmetics_at.
        * tree.h: Add prototypes for the two new functions.
        * fold-const.c (fold_binary_op_with_conditional_arg): Replace test
        updates introduced in the previous revision by call to saved_expr_p.
        * stor-layout.c (put_pending_size): Use skip_simple_arithmetics_at.

From-SVN: r65702
This commit is contained in:
Olivier Hainque 2003-04-16 23:33:19 +02:00 committed by Richard Kenner
parent 15b19a7dbf
commit a9ecacf6c4
5 changed files with 84 additions and 50 deletions

View File

@ -1,5 +1,12 @@
2003-04-16 Olivier Hainque <hainque@act-europe.fr>
* tree.c (skip_simple_arithmetics_at, saved_expr_p): New functions.
(save_expr): Replace loop by call to skip_simple_arithmetics_at.
* tree.h: Add prototypes for the two new functions.
* fold-const.c (fold_binary_op_with_conditional_arg): Replace test
updates introduced in the previous revision by call to saved_expr_p.
* stor-layout.c (put_pending_size): Use skip_simple_arithmetics_at.
* expr.c (store_field): Force usage of bitfield instructions when
the field position requires it, whatever SLOW_UNALIGNED_ACCESS.
(expand_expr, case BIT_FIELD_REF): likewise.

View File

@ -4568,21 +4568,19 @@ fold_binary_op_with_conditional_arg (code, type, cond, arg, cond_first_p)
false_value = convert (testtype, integer_zero_node);
}
/* If ARG is complex we want to make sure we only evaluate
it once. Though this is only required if it is volatile, it
might be more efficient even if it is not. However, if we
succeed in folding one part to a constant, we do not need
to make this SAVE_EXPR. Since we do this optimization
primarily to see if we do end up with constant and this
SAVE_EXPR interferes with later optimizations, suppressing
it when we can is important.
/* If ARG is complex we want to make sure we only evaluate it once. Though
this is only required if it is volatile, it might be more efficient even
if it is not. However, if we succeed in folding one part to a constant,
we do not need to make this SAVE_EXPR. Since we do this optimization
primarily to see if we do end up with constant and this SAVE_EXPR
interferes with later optimizations, suppressing it when we can is
important.
If we are not in a function, we can't make a SAVE_EXPR, so don't
try to do so. Don't try to see if the result is a constant
if an arm is a COND_EXPR since we get exponential behavior
in that case. */
If we are not in a function, we can't make a SAVE_EXPR, so don't try to
do so. Don't try to see if the result is a constant if an arm is a
COND_EXPR since we get exponential behavior in that case. */
if (TREE_CODE (arg) == SAVE_EXPR)
if (saved_expr_p (arg))
save = 1;
else if (lhs == 0 && rhs == 0
&& !TREE_CONSTANT (arg)

View File

@ -128,10 +128,7 @@ put_pending_size (expr)
{
/* Strip any simple arithmetic from EXPR to see if it has an underlying
SAVE_EXPR. */
while (TREE_CODE_CLASS (TREE_CODE (expr)) == '1'
|| (TREE_CODE_CLASS (TREE_CODE (expr)) == '2'
&& TREE_CONSTANT (TREE_OPERAND (expr, 1))))
expr = TREE_OPERAND (expr, 0);
expr = skip_simple_arithmetic (expr);
if (TREE_CODE (expr) == SAVE_EXPR)
pending_sizes = tree_cons (NULL_TREE, expr, pending_sizes);

View File

@ -1379,18 +1379,60 @@ save_expr (expr)
tree expr;
{
tree t = fold (expr);
tree inner;
tree inner = skip_simple_arithmetic (t);
/* 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 (inner)
|| (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
|| TREE_CODE (inner) == SAVE_EXPR
|| TREE_CODE (inner) == ERROR_MARK)
return t;
/* If INNER contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
it means that the size or offset of some field of an object depends on
the value within another field.
Note that it must not be the case that T contains both a PLACEHOLDER_EXPR
and some variable since it would then need to be both evaluated once and
evaluated more than once. Front-ends must assure this case cannot
happen by surrounding any such subexpressions in their own SAVE_EXPR
and forcing evaluation at the proper time. */
if (contains_placeholder_p (inner))
return t;
t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
/* This expression might be placed ahead of a jump to ensure that the
value was computed on both sides of the jump. So make sure it isn't
eliminated as dead. */
TREE_SIDE_EFFECTS (t) = 1;
TREE_READONLY (t) = 1;
return t;
}
/* Look inside EXPR and into any simple arithmetic operations. Return
the innermost non-arithmetic node. */
tree
skip_simple_arithmetic (expr)
tree 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);
while (TREE_CODE (expr) == NON_LVALUE_EXPR)
expr = TREE_OPERAND (expr, 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 actually occur. */
inner = t;
inner = expr;
while (1)
{
if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
@ -1408,37 +1450,17 @@ save_expr (expr)
break;
}
/* 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 (inner)
|| (TREE_READONLY (inner) && ! TREE_SIDE_EFFECTS (inner))
|| TREE_CODE (inner) == SAVE_EXPR
|| TREE_CODE (inner) == ERROR_MARK)
return t;
return inner;
}
/* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
it means that the size or offset of some field of an object depends on
the value within another field.
/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
SAVE_EXPR. Return FALSE otherwise. */
Note that it must not be the case that T contains both a PLACEHOLDER_EXPR
and some variable since it would then need to be both evaluated once and
evaluated more than once. Front-ends must assure this case cannot
happen by surrounding any such subexpressions in their own SAVE_EXPR
and forcing evaluation at the proper time. */
if (contains_placeholder_p (t))
return t;
t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
/* This expression might be placed ahead of a jump to ensure that the
value was computed on both sides of the jump. So make sure it isn't
eliminated as dead. */
TREE_SIDE_EFFECTS (t) = 1;
TREE_READONLY (t) = 1;
return t;
bool
saved_expr_p (expr)
tree expr;
{
return TREE_CODE (skip_simple_arithmetic (expr)) == SAVE_EXPR;
}
/* Arrange for an expression to be expanded multiple independent

View File

@ -2681,6 +2681,16 @@ extern int lvalue_or_else PARAMS ((tree, const char *));
extern tree save_expr PARAMS ((tree));
/* Look inside EXPR and into any simple arithmetic operations. Return
the innermost non-arithmetic node. */
extern tree skip_simple_arithmetic PARAMS ((tree));
/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
SAVE_EXPR. Return FALSE otherwise. */
extern bool saved_expr_p PARAMS ((tree));
/* Returns the index of the first non-tree operand for CODE, or the number
of operands if all are trees. */