Commit a9ecacf6 by Olivier Hainque Committed by Richard Kenner

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
parent 15b19a7d
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 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 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 (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);
......
......@@ -1379,34 +1379,7 @@ 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 actually occur. */
inner = t;
while (1)
{
if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
inner = TREE_OPERAND (inner, 0);
else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
{
if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
inner = TREE_OPERAND (inner, 0);
else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
inner = TREE_OPERAND (inner, 1);
else
break;
}
else
break;
}
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).
......@@ -1419,7 +1392,7 @@ save_expr (expr)
|| TREE_CODE (inner) == ERROR_MARK)
return t;
/* If T contains a PLACEHOLDER_EXPR, we must evaluate it each time, since
/* 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.
......@@ -1428,7 +1401,7 @@ save_expr (expr)
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))
if (contains_placeholder_p (inner))
return t;
t = build (SAVE_EXPR, TREE_TYPE (expr), t, current_function_decl, NULL_TREE);
......@@ -1441,6 +1414,55 @@ save_expr (expr)
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 (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 = expr;
while (1)
{
if (TREE_CODE_CLASS (TREE_CODE (inner)) == '1')
inner = TREE_OPERAND (inner, 0);
else if (TREE_CODE_CLASS (TREE_CODE (inner)) == '2')
{
if (TREE_CONSTANT (TREE_OPERAND (inner, 1)))
inner = TREE_OPERAND (inner, 0);
else if (TREE_CONSTANT (TREE_OPERAND (inner, 0)))
inner = TREE_OPERAND (inner, 1);
else
break;
}
else
break;
}
return inner;
}
/* Return TRUE if EXPR is a SAVE_EXPR or wraps simple arithmetic around a
SAVE_EXPR. Return FALSE otherwise. */
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
times. This is useful for cleanup actions, as the backend can
expand them multiple times in different places. */
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment