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.
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)
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).
|| 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.
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);
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. */