diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-06-23 14:44:21 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-06-23 14:44:21 +0000 |
commit | ea523851e65ca645bcddff0657ed711cd846f9e6 (patch) | |
tree | 672b804a497a6d4d52b747f00969c6d7b30ebbfb /gcc/gimplify.c | |
parent | 44cb69ffb21cd8ef9163ffbc022ec4195f6201d9 (diff) | |
download | gcc-ea523851e65ca645bcddff0657ed711cd846f9e6.tar.gz |
PR c++/19317
Leave the return slot target in the MODIFY_EXPR rather than making
it an argument, but only use it if the CALL_EXPR has a flag set.
* tree.h (CALL_EXPR_HAS_RETURN_SLOT_ADDR): Rename to
CALL_EXPR_RETURN_SLOT_OPT.
* calls.c (expand_call): Adjust.
* tree-inline.c (expand_call_inline): Adjust.
* tree-pretty-print.c (dump_generic_node): Adjust.
And set the flag as appropriate.
* gimplify.c (gimplify_modify_expr_rhs): Set
CALL_EXPR_HAS_RETURN_SLOT_ADDR where the LHS is obviously safe.
* tree-nrv.c (execute_return_slot_opt): Set
CALL_EXPR_HAS_RETURN_SLOT_ADDR based on escape analysis.
* tree-pass.h: Declare pass_return_slot.
* tree-optimize.c (init_tree_optimization_passes): Add it.
* cp/semantics.c (simplify_aggr_init_expr): Use
CALL_EXPR_RETURN_SLOT_OPT, not CALL_EXPR_HAS_RETURN_SLOT_ADDR.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@101269 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/gimplify.c')
-rw-r--r-- | gcc/gimplify.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/gcc/gimplify.c b/gcc/gimplify.c index df93bc5dde8..81512728dc5 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3015,6 +3015,46 @@ 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 (!CALL_EXPR_RETURN_SLOT_OPT (*from_p) + && aggregate_value_p (*from_p, *from_p)) + { + bool use_target; + + if (TREE_CODE (*to_p) == RESULT_DECL + && needs_to_live_in_memory (*to_p)) + /* It's always OK to use the return slot directly. */ + use_target = true; + else if (!is_gimple_non_addressable (*to_p)) + /* Don't use the original target if it's 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; see c++/19317. + When optimizing, the return_slot pass marks more functions + as safe after we have escape info. */ + use_target = false; + else if (DECL_GIMPLE_FORMAL_TEMP_P (*to_p)) + /* Don't use the original target if it's a formal temp; we + don't want to take their addresses. */ + use_target = false; + else if (is_gimple_reg_type (TREE_TYPE (*to_p))) + /* Also don't force regs into memory. */ + use_target = false; + else + use_target = true; + + if (use_target) + { + CALL_EXPR_RETURN_SLOT_OPT (*from_p) = 1; + lang_hooks.mark_addressable (*to_p); + } + } + + ret = GS_UNHANDLED; + break; + default: ret = GS_UNHANDLED; break; |