summaryrefslogtreecommitdiff
path: root/gcc/gimplify.c
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-27 17:23:30 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-27 17:23:30 +0000
commit51fc648ffc1a616d7a4233332b443033308d7855 (patch)
tree62ea9650b917f6874d18e3dfbb1662d57f77d04b /gcc/gimplify.c
parent0fc97fb009a8b5d085a5050cb8e01db0c8dde3e6 (diff)
downloadgcc-51fc648ffc1a616d7a4233332b443033308d7855.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@100267 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r--gcc/gimplify.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 9452973004e..657d5311e5b 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;