diff options
author | Richard Guenther <rguenth@gcc.gnu.org> | 2005-05-27 17:23:30 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2005-05-27 11:23:30 -0600 |
commit | 30d2e94365655dae5bccb24797f97f5260da3154 (patch) | |
tree | 62ea9650b917f6874d18e3dfbb1662d57f77d04b | |
parent | 46aad78f22f0d84855daed56e7369e73e31c8c26 (diff) | |
download | gcc-30d2e94365655dae5bccb24797f97f5260da3154.zip gcc-30d2e94365655dae5bccb24797f97f5260da3154.tar.gz gcc-30d2e94365655dae5bccb24797f97f5260da3154.tar.bz2 |
[multiple changes]
2005-05-18 Richard Guenther <rguenth@gcc.gnu.org>
* tree-inline.c (copy_body_r): Manually fold *& to deal
with ADDR_EXPRs with mismatched types for now.
2005-05-17 Richard Guenther <rguenth@gcc.gnu.org>
* gimplify.c (fold_indirect_ref_rhs): New function.
(gimplify_modify_expr_rhs): Use it instead of pessimistic
fold_indirect_ref.
2005-05-15 Richard Guenther <rguenth@gcc.gnu.org>
* fold-const.c (fold_indirect_ref_1): Add type argument;
make sure the resulting expression is of this type.
(build_fold_indirect_ref, fold_indirect_ref): Adjust callers.
From-SVN: r100267
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fold-const.c | 23 | ||||
-rw-r--r-- | gcc/gimplify.c | 60 | ||||
-rw-r--r-- | gcc/tree-inline.c | 12 |
4 files changed, 94 insertions, 14 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 557ed56..c1dafb0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2005-05-27 Richard Guenther <rguenth@gcc.gnu.org> + + * tree-inline.c (copy_body_r): Manually fold *& to deal + with ADDR_EXPRs with mismatched types for now. + + * gimplify.c (fold_indirect_ref_rhs): New function. + (gimplify_modify_expr_rhs): Use it instead of pessimistic + fold_indirect_ref. + + * fold-const.c (fold_indirect_ref_1): Add type argument; + make sure the resulting expression is of this type. + (build_fold_indirect_ref, fold_indirect_ref): Adjust callers. + 2005-05-27 Kazu Hirata <kazu@cs.umass.edu> PR tree-optimization/21658 diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 0d5f4eb..9880327 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -11451,14 +11451,14 @@ build_fold_addr_expr (tree t) return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t))); } -/* Given a pointer value T, return a simplified version of an indirection - through T, or NULL_TREE if no simplification is possible. */ +/* Given a pointer value OP0 and a type TYPE, return a simplified version + of an indirection through OP0, or NULL_TREE if no simplification is + possible. */ static tree -fold_indirect_ref_1 (tree t) +fold_indirect_ref_1 (tree type, tree op0) { - tree type = TREE_TYPE (TREE_TYPE (t)); - tree sub = t; + tree sub = op0; tree subtype; STRIP_NOPS (sub); @@ -11471,11 +11471,11 @@ fold_indirect_ref_1 (tree t) tree op = TREE_OPERAND (sub, 0); tree optype = TREE_TYPE (op); /* *&p => p */ - if (lang_hooks.types_compatible_p (type, optype)) + if (type == optype) return op; /* *(foo *)&fooarray => fooarray[0] */ else if (TREE_CODE (optype) == ARRAY_TYPE - && lang_hooks.types_compatible_p (type, TREE_TYPE (optype))) + && type == TREE_TYPE (optype)) { tree type_domain = TYPE_DOMAIN (optype); tree min_val = size_zero_node; @@ -11487,7 +11487,7 @@ fold_indirect_ref_1 (tree t) /* *(foo *)fooarrptr => (*fooarrptr)[0] */ if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE - && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype)))) + && type == TREE_TYPE (TREE_TYPE (subtype))) { tree type_domain; tree min_val = size_zero_node; @@ -11507,12 +11507,13 @@ fold_indirect_ref_1 (tree t) tree build_fold_indirect_ref (tree t) { - tree sub = fold_indirect_ref_1 (t); + tree type = TREE_TYPE (TREE_TYPE (t)); + tree sub = fold_indirect_ref_1 (type, t); if (sub) return sub; else - return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); + return build1 (INDIRECT_REF, type, t); } /* Given an INDIRECT_REF T, return either T or a simplified version. */ @@ -11520,7 +11521,7 @@ build_fold_indirect_ref (tree t) tree fold_indirect_ref (tree t) { - tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0)); + tree sub = fold_indirect_ref_1 (TREE_TYPE (t), TREE_OPERAND (t, 0)); if (sub) return sub; diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 9452973..657d531 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2846,6 +2846,62 @@ gimplify_init_constructor (tree *expr_p, tree *pre_p, return GS_ALL_DONE; } +/* Given a pointer value OP0, return a simplified version of an + indirection through OP0, or NULL_TREE if no simplification is + possible. This may only be applied to a rhs of an expression. + Note that the resulting type may be different from the type pointed + to in the sense that it is still compatible from the langhooks + point of view. */ + +static tree +fold_indirect_ref_rhs (tree t) +{ + tree type = TREE_TYPE (TREE_TYPE (t)); + tree sub = t; + tree subtype; + + STRIP_NOPS (sub); + subtype = TREE_TYPE (sub); + if (!POINTER_TYPE_P (subtype)) + return NULL_TREE; + + if (TREE_CODE (sub) == ADDR_EXPR) + { + tree op = TREE_OPERAND (sub, 0); + tree optype = TREE_TYPE (op); + /* *&p => p */ + if (lang_hooks.types_compatible_p (type, optype)) + return op; + /* *(foo *)&fooarray => fooarray[0] */ + else if (TREE_CODE (optype) == ARRAY_TYPE + && lang_hooks.types_compatible_p (type, TREE_TYPE (optype))) + { + tree type_domain = TYPE_DOMAIN (optype); + tree min_val = size_zero_node; + if (type_domain && TYPE_MIN_VALUE (type_domain)) + min_val = TYPE_MIN_VALUE (type_domain); + return build4 (ARRAY_REF, type, op, min_val, NULL_TREE, NULL_TREE); + } + } + + /* *(foo *)fooarrptr => (*fooarrptr)[0] */ + if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE + && lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype)))) + { + tree type_domain; + tree min_val = size_zero_node; + sub = fold_indirect_ref_rhs (sub); + if (! sub) + sub = build1 (INDIRECT_REF, TREE_TYPE (subtype), sub); + type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); + if (type_domain && TYPE_MIN_VALUE (type_domain)) + min_val = TYPE_MIN_VALUE (type_domain); + return build4 (ARRAY_REF, type, sub, min_val, NULL_TREE, NULL_TREE); + } + + return NULL_TREE; +} + /* Subroutine of gimplify_modify_expr to do simplifications of MODIFY_EXPRs based on the code of the RHS. We loop for as long as something changes. */ @@ -2869,8 +2925,8 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p, This kind of code arises in C++ when an object is bound to a const reference, and if "x" is a TARGET_EXPR we want to take advantage of the optimization below. */ - tree t = fold_indirect_ref (*from_p); - if (t != *from_p) + tree t = fold_indirect_ref_rhs (TREE_OPERAND (*from_p, 0)); + if (t) { *from_p = t; ret = GS_OK; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 118f493..c04fe33 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -613,7 +613,17 @@ copy_body_r (tree *tp, int *walk_subtrees, void *data) n = splay_tree_lookup (id->decl_map, (splay_tree_key) decl); if (n) { - *tp = build_fold_indirect_ref ((tree)n->value); + /* If we happen to get an ADDR_EXPR in n->value, strip + it manually here as we'll eventually get ADDR_EXPRs + which lie about their types pointed to. In this case + build_fold_indirect_ref wouldn't strip the INDIRECT_REF, + but we absolutely rely on that. */ + if (TREE_CODE ((tree)n->value) == ADDR_EXPR) + *tp = TREE_OPERAND ((tree)n->value, 0); + else + *tp = build1 (INDIRECT_REF, + TREE_TYPE (TREE_TYPE ((tree)n->value)), + (tree)n->value); *walk_subtrees = 0; return NULL; } |