aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2005-02-13 06:43:58 +0000
committerJason Merrill <jason@redhat.com>2005-02-13 06:43:58 +0000
commit85611153654f543a0f93071624b2f6dfd68734ba (patch)
treec43953a2f4ab67d576c5e64bbca5f4aa01d20a3c
parentb6e1362f2a78092e9739228a4e2e59474da5dcff (diff)
PR mudflap/19319
* gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return slot explicit. PR c++/16405 * fold-const.c (fold_indirect_ref_1): Split out from... (build_fold_indirect_ref): Here. (fold_indirect_ref): New fn. * tree.h: Declare it. * gimplify.c (gimplify_compound_lval): Call fold_indirect_ref. (gimplify_modify_expr_rhs): Likewise. (gimplify_expr): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@94979 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/fold-const.c42
-rw-r--r--gcc/gimplify.c80
-rw-r--r--gcc/tree.h1
4 files changed, 119 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 35f46de3d7c..aa96a6ac7fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2005-02-13 Jason Merrill <jason@redhat.com>
+
+ PR mudflap/19319
+ * gimplify.c (gimplify_modify_expr_rhs) [CALL_EXPR]: Make return
+ slot explicit.
+
+ PR c++/16405
+ * fold-const.c (fold_indirect_ref_1): Split out from...
+ (build_fold_indirect_ref): Here.
+ (fold_indirect_ref): New fn.
+ * tree.h: Declare it.
+ * gimplify.c (gimplify_compound_lval): Call fold_indirect_ref.
+ (gimplify_modify_expr_rhs): Likewise.
+ (gimplify_expr): Likewise.
+
2005-02-13 James A. Morrison <phython@gcc.gnu.org>
PR tree-optimization/14303
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 601f023ce9a..afe3afc4663 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -11217,17 +11217,21 @@ build_fold_addr_expr (tree t)
return build_fold_addr_expr_with_type (t, build_pointer_type (TREE_TYPE (t)));
}
-/* Builds an expression for an indirection through T, simplifying some
- cases. */
+/* Given a pointer value T, return a simplified version of an indirection
+ through T, or NULL_TREE if no simplification is possible. */
-tree
-build_fold_indirect_ref (tree t)
+static tree
+fold_indirect_ref_1 (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);
@@ -11242,7 +11246,6 @@ build_fold_indirect_ref (tree t)
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
- subtype = TREE_TYPE (sub);
if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE
&& lang_hooks.types_compatible_p (type, TREE_TYPE (TREE_TYPE (subtype))))
{
@@ -11250,7 +11253,34 @@ build_fold_indirect_ref (tree t)
return build4 (ARRAY_REF, type, sub, size_zero_node, NULL_TREE, NULL_TREE);
}
- return build1 (INDIRECT_REF, type, t);
+ return NULL_TREE;
+}
+
+/* Builds an expression for an indirection through T, simplifying some
+ cases. */
+
+tree
+build_fold_indirect_ref (tree t)
+{
+ tree sub = fold_indirect_ref_1 (t);
+
+ if (sub)
+ return sub;
+ else
+ return build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t);
+}
+
+/* Given an INDIRECT_REF T, return either T or a simplified version. */
+
+tree
+fold_indirect_ref (tree t)
+{
+ tree sub = fold_indirect_ref_1 (TREE_OPERAND (t, 0));
+
+ if (sub)
+ return sub;
+ else
+ return t;
}
/* Strip non-trapping, non-side-effecting tree nodes from an expression
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 0fd39436325..ddb72bc63be 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -1433,8 +1433,15 @@ gimplify_compound_lval (tree *expr_p, tree *pre_p,
VARRAY_GENERIC_PTR_NOGC_INIT (stack, 10, "stack");
/* We can handle anything that get_inner_reference can deal with. */
- for (p = expr_p; handled_component_p (*p); p = &TREE_OPERAND (*p, 0))
- VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
+ for (p = expr_p; ; p = &TREE_OPERAND (*p, 0))
+ {
+ /* Fold INDIRECT_REFs now to turn them into ARRAY_REFs. */
+ if (TREE_CODE (*p) == INDIRECT_REF)
+ *p = fold_indirect_ref (*p);
+ if (!handled_component_p (*p))
+ break;
+ VARRAY_PUSH_GENERIC_PTR_NOGC (stack, *p);
+ }
gcc_assert (VARRAY_ACTIVE_SIZE (stack));
@@ -2845,16 +2852,10 @@ 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 pointer;
-
- pointer = TREE_OPERAND (*from_p, 0);
- STRIP_NOPS (pointer);
- if (TREE_CODE (pointer) == ADDR_EXPR
- && (lang_hooks.types_compatible_p
- (TREE_TYPE (TREE_OPERAND (pointer, 0)),
- TREE_TYPE (*from_p))))
+ tree t = fold_indirect_ref (*from_p);
+ if (t != *from_p)
{
- *from_p = TREE_OPERAND (pointer, 0);
+ *from_p = t;
ret = GS_OK;
}
else
@@ -2912,6 +2913,55 @@ gimplify_modify_expr_rhs (tree *expr_p, tree *from_p, tree *to_p, tree *pre_p,
ret = GS_UNHANDLED;
break;
+ case CALL_EXPR:
+ /* For calls that return in memory, give *to_p as the CALL_EXPR's
+ return slot so that we don't generate a temporary. */
+ if (aggregate_value_p (*from_p, *from_p))
+ {
+ tree init = *from_p;
+ tree fn = TREE_OPERAND (init, 0);
+ tree args = TREE_OPERAND (init, 1);
+ tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
+ tree arg = *to_p;
+ tree type;
+
+ /* Only use the original target if *to_p isn't already
+ addressable; if its address escapes, and the called function
+ uses the NRV optimization, a conforming program could see
+ *to_p change before the called function returns. */
+ bool use_temp = !is_gimple_non_addressable (*to_p);
+ if (use_temp)
+ {
+ arg = create_tmp_var (rettype, "ret");
+ *from_p = arg;
+ }
+
+ type = TREE_TYPE (arg);
+ /* FIXME: Mark the address as not escaping. */
+ lang_hooks.mark_addressable (arg);
+ arg = build1 (ADDR_EXPR, build_pointer_type (type), arg);
+ /* The return type might have different cv-quals from arg. */
+ arg = convert (build_pointer_type (rettype), arg);
+ args = tree_cons (NULL_TREE, arg, args);
+ init = build3 (CALL_EXPR, rettype, fn, args, NULL_TREE);
+ CALL_EXPR_HAS_RETURN_SLOT_ADDR (init) = 1;
+ TREE_USED (init) = 1;
+
+ if (use_temp)
+ gimplify_and_add (init, pre_p);
+ else if (want_value)
+ {
+ gimplify_and_add (init, pre_p);
+ *expr_p = *to_p;
+ }
+ else
+ *expr_p = init;
+ ret = GS_OK;
+ }
+ else
+ ret = GS_UNHANDLED;
+ break;
+
default:
ret = GS_UNHANDLED;
break;
@@ -3544,7 +3594,7 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
ret = GS_OK;
if (TREE_CODE (init) == BIND_EXPR)
gimplify_bind_expr (&init, temp, pre_p);
- if (init != temp)
+ if (init != temp)
{
init = build (MODIFY_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt,
@@ -3795,9 +3845,13 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
recalculate_side_effects (*expr_p);
break;
+ case INDIRECT_REF:
+ *expr_p = fold_indirect_ref (*expr_p);
+ if (*expr_p != save_expr)
+ break;
+ /* else fall through. */
case ALIGN_INDIRECT_REF:
case MISALIGNED_INDIRECT_REF:
- case INDIRECT_REF:
ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
is_gimple_reg, fb_rvalue);
recalculate_side_effects (*expr_p);
diff --git a/gcc/tree.h b/gcc/tree.h
index dea3136e009..62e9bb332bb 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -3546,6 +3546,7 @@ extern tree fold_build_cleanup_point_expr (tree type, tree expr);
extern tree fold_strip_sign_ops (tree);
extern tree build_fold_addr_expr_with_type (tree, tree);
extern tree build_fold_indirect_ref (tree);
+extern tree fold_indirect_ref (tree);
extern tree constant_boolean_node (int, tree);
extern tree build_low_bits_mask (tree, unsigned);