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:
parent
15b19a7dbf
commit
a9ecacf6c4
@ -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.
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
88
gcc/tree.c
88
gcc/tree.c
@ -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
|
||||
|
10
gcc/tree.h
10
gcc/tree.h
@ -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. */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user