From a9ecacf6c44316e20d54c36f84ae80dedfff09e6 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 16 Apr 2003 23:33:19 +0200 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 ++++ gcc/fold-const.c | 24 ++++++------- gcc/stor-layout.c | 5 +-- gcc/tree.c | 88 +++++++++++++++++++++++++++++------------------ gcc/tree.h | 10 ++++++ 5 files changed, 84 insertions(+), 50 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bb692cf621d..19fdf5af8fc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2003-04-16 Olivier Hainque + * 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. diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 065a4fc527d..fa64fd2b956 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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) diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 7ebdda845d1..66067d6f276 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -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); diff --git a/gcc/tree.c b/gcc/tree.c index 09c239e743f..ce5e21997b1 100644 --- a/gcc/tree.c +++ b/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 diff --git a/gcc/tree.h b/gcc/tree.h index 95f2ad4ac03..44ccd451784 100644 --- a/gcc/tree.h +++ b/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. */