aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorOlivier Hainque <hainque@act-europe.fr>2003-04-16 23:33:19 +0200
committerRichard Kenner <kenner@gcc.gnu.org>2003-04-16 17:33:19 -0400
commita9ecacf6c44316e20d54c36f84ae80dedfff09e6 (patch)
treed54db0fbb9e85319256be0471da62b0bf8117eb6 /gcc
parent15b19a7dbf433b1936eecd042ce7dedbb23220f9 (diff)
downloadgcc-a9ecacf6c44316e20d54c36f84ae80dedfff09e6.zip
gcc-a9ecacf6c44316e20d54c36f84ae80dedfff09e6.tar.gz
gcc-a9ecacf6c44316e20d54c36f84ae80dedfff09e6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c28
-rw-r--r--gcc/stor-layout.c5
-rw-r--r--gcc/tree.c82
-rw-r--r--gcc/tree.h10
5 files changed, 83 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index bb692cf..19fdf5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 065a4fc..fa64fd2 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 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)
diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
index 7ebdda8..66067d6 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 09c239e..ce5e219 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 95f2ad4..44ccd45 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. */