Commit 07b2f2fd by Jason Merrill Committed by Jason Merrill

c-common.h (RETURN_NULLIFIED_P): Lose.

        * c-common.h (RETURN_NULLIFIED_P): Lose.
        * c-semantics.c (genrtl_return_stmt): Don't check it.

        Support named return value optimization for inlines, too.
        * decl.c (finish_function): Nullify returns here.
        * semantics.c (genrtl_start_function): Not here.
        (cp_expand_stmt): Don't mess with CLEANUP_STMTs.
        (nullify_returns_r): No longer static.  Just clear RETURN_EXPR.
        Also nullify the CLEANUP_STMT for the nrv.
        * cp-tree.h: Declare it.
        * optimize.c (declare_return_variable): Replace the nrv with the
        return variable.
        * typeck.c (check_return_expr): Be more flexible on alignment check.
        Ignore cv-quals when checking for a matching type.

From-SVN: r44762
parent 67070ffe
2001-08-08 Jason Merrill <jason_merrill@redhat.com>
* c-common.h (RETURN_NULLIFIED_P): Lose.
* c-semantics.c (genrtl_return_stmt): Don't check it.
2001-08-10 Richard Sandiford <rsandifo@redhat.com> 2001-08-10 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.c (mips_add_large_offset_to_sp): New function. * config/mips/mips.c (mips_add_large_offset_to_sp): New function.
......
...@@ -32,7 +32,6 @@ Boston, MA 02111-1307, USA. */ ...@@ -32,7 +32,6 @@ Boston, MA 02111-1307, USA. */
SCOPE_BEGIN_P (in SCOPE_STMT) SCOPE_BEGIN_P (in SCOPE_STMT)
DECL_PRETTY_FUNCTION_P (in VAR_DECL) DECL_PRETTY_FUNCTION_P (in VAR_DECL)
NEW_FOR_SCOPE_P (in FOR_STMT) NEW_FOR_SCOPE_P (in FOR_STMT)
RETURN_NULLIFIED_P (in RETURN_STMT)
ASM_INPUT_P (in ASM_STMT) ASM_INPUT_P (in ASM_STMT)
1: C_DECLARED_LABEL_FLAG (in LABEL_DECL) 1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
STMT_IS_FULL_EXPR_P (in _STMT) STMT_IS_FULL_EXPR_P (in _STMT)
...@@ -597,7 +596,6 @@ extern tree strip_array_types PARAMS ((tree)); ...@@ -597,7 +596,6 @@ extern tree strip_array_types PARAMS ((tree));
return statement, and whether it should be ignored when expanding return statement, and whether it should be ignored when expanding
(as opposed to inlining). */ (as opposed to inlining). */
#define RETURN_EXPR(NODE) TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0) #define RETURN_EXPR(NODE) TREE_OPERAND (RETURN_STMT_CHECK (NODE), 0)
#define RETURN_NULLIFIED_P(NODE) TREE_LANG_FLAG_0 (RETURN_STMT_CHECK (NODE))
/* EXPR_STMT accessor. This gives the expression associated with an /* EXPR_STMT accessor. This gives the expression associated with an
expression statement. */ expression statement. */
......
...@@ -462,12 +462,6 @@ genrtl_return_stmt (stmt) ...@@ -462,12 +462,6 @@ genrtl_return_stmt (stmt)
{ {
tree expr; tree expr;
/* If RETURN_NULLIFIED_P is set, the frontend has arranged to set up
the return value separately, so just return the return value
itself. This is used for the C++ named return value optimization. */
if (RETURN_NULLIFIED_P (stmt))
expr = DECL_RESULT (current_function_decl);
else
expr = RETURN_EXPR (stmt); expr = RETURN_EXPR (stmt);
emit_line_note (input_filename, lineno); emit_line_note (input_filename, lineno);
......
2001-08-07 Jason Merrill <jason_merrill@redhat.com>
Support named return value optimization for inlines, too.
* decl.c (finish_function): Nullify returns here.
* semantics.c (genrtl_start_function): Not here.
(cp_expand_stmt): Don't mess with CLEANUP_STMTs.
(nullify_returns_r): No longer static. Just clear RETURN_EXPR.
Also nullify the CLEANUP_STMT for the nrv.
* cp-tree.h: Declare it.
* optimize.c (declare_return_variable): Replace the nrv with the
return variable.
* typeck.c (check_return_expr): Be more flexible on alignment check.
Ignore cv-quals when checking for a matching type.
2001-08-09 Richard Henderson <rth@redhat.com> 2001-08-09 Richard Henderson <rth@redhat.com>
* decl2.c (finish_objects): Use target hooks instead of * decl2.c (finish_objects): Use target hooks instead of
......
...@@ -4129,6 +4129,7 @@ extern tree finish_typeof PARAMS ((tree)); ...@@ -4129,6 +4129,7 @@ extern tree finish_typeof PARAMS ((tree));
extern void finish_decl_cleanup PARAMS ((tree, tree)); extern void finish_decl_cleanup PARAMS ((tree, tree));
extern void finish_named_return_value PARAMS ((tree, tree)); extern void finish_named_return_value PARAMS ((tree, tree));
extern void expand_body PARAMS ((tree)); extern void expand_body PARAMS ((tree));
extern tree nullify_returns_r PARAMS ((tree *, int *, void *));
extern void do_pushlevel PARAMS ((void)); extern void do_pushlevel PARAMS ((void));
extern tree do_poplevel PARAMS ((void)); extern tree do_poplevel PARAMS ((void));
extern void finish_mem_initializers PARAMS ((tree)); extern void finish_mem_initializers PARAMS ((tree));
......
...@@ -13955,6 +13955,28 @@ finish_function (flags) ...@@ -13955,6 +13955,28 @@ finish_function (flags)
my_friendly_abort (122); my_friendly_abort (122);
poplevel (1, 0, 1); poplevel (1, 0, 1);
/* Set up the named return value optimization, if we can. Here, we
eliminate the copy from the nrv into the RESULT_DECL and any cleanup
for the nrv. genrtl_start_function and declare_return_variable
handle making the nrv and RESULT_DECL share space. */
if (current_function_return_value)
{
tree r = current_function_return_value;
/* This is only worth doing for fns that return in memory--and
simpler, since we don't have to worry about promoted modes. */
if (r != error_mark_node
&& aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
{
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
}
else
/* Clear it so genrtl_start_function and declare_return_variable
know we're not optimizing. */
current_function_return_value = NULL_TREE;
}
/* Remember that we were in class scope. */ /* Remember that we were in class scope. */
if (current_class_name) if (current_class_name)
ctype = current_class_type; ctype = current_class_type;
......
...@@ -602,6 +602,23 @@ declare_return_variable (id, use_stmt) ...@@ -602,6 +602,23 @@ declare_return_variable (id, use_stmt)
(splay_tree_key) result, (splay_tree_key) result,
(splay_tree_value) var); (splay_tree_value) var);
if (DECL_SAVED_FUNCTION_DATA (fn))
{
tree nrv = DECL_SAVED_FUNCTION_DATA (fn)->x_return_value;
if (nrv)
{
/* We have a named return value; copy the name and source
position so we can get reasonable debugging information, and
register the return variable as its equivalent. */
DECL_NAME (var) = DECL_NAME (nrv);
DECL_SOURCE_FILE (var) = DECL_SOURCE_FILE (nrv);
DECL_SOURCE_LINE (var) = DECL_SOURCE_LINE (nrv);
splay_tree_insert (id->decl_map,
(splay_tree_key) nrv,
(splay_tree_value) var);
}
}
/* Build the USE_STMT. */ /* Build the USE_STMT. */
*use_stmt = build_stmt (EXPR_STMT, var); *use_stmt = build_stmt (EXPR_STMT, var);
......
...@@ -50,7 +50,6 @@ ...@@ -50,7 +50,6 @@
static tree maybe_convert_cond PARAMS ((tree)); static tree maybe_convert_cond PARAMS ((tree));
static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *)); static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
static tree nullify_returns_r PARAMS ((tree *, int *, void *));
static void deferred_type_access_control PARAMS ((void)); static void deferred_type_access_control PARAMS ((void));
static void emit_associated_thunks PARAMS ((tree)); static void emit_associated_thunks PARAMS ((tree));
static void genrtl_try_block PARAMS ((tree)); static void genrtl_try_block PARAMS ((tree));
...@@ -2196,10 +2195,6 @@ cp_expand_stmt (t) ...@@ -2196,10 +2195,6 @@ cp_expand_stmt (t)
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case CLEANUP_STMT: case CLEANUP_STMT:
if (CLEANUP_DECL (t)
&& CLEANUP_DECL (t) == current_function_return_value)
/* Don't destroy the chosen named return value. */;
else
genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t)); genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
break; break;
...@@ -2504,20 +2499,27 @@ expand_body (fn) ...@@ -2504,20 +2499,27 @@ expand_body (fn)
timevar_pop (TV_EXPAND); timevar_pop (TV_EXPAND);
} }
/* Helper function for walk_tree, used by genrtl_start_function to override /* Helper function for walk_tree, used by finish_function to override all
all the RETURN_STMTs for the named return value optimization. */ the RETURN_STMTs and pertinent CLEANUP_STMTs for the named return
value optimization. */
static tree tree
nullify_returns_r (tp, walk_subtrees, data) nullify_returns_r (tp, walk_subtrees, data)
tree *tp; tree *tp;
int *walk_subtrees; int *walk_subtrees;
void *data ATTRIBUTE_UNUSED; void *data;
{ {
/* No need to walk into types. */ tree nrv = (tree) data;
/* No need to walk into types. There wouldn't be any need to walk into
non-statements, except that we have to consider STMT_EXPRs. */
if (TYPE_P (*tp)) if (TYPE_P (*tp))
*walk_subtrees = 0; *walk_subtrees = 0;
else if (TREE_CODE (*tp) == RETURN_STMT) else if (TREE_CODE (*tp) == RETURN_STMT)
RETURN_NULLIFIED_P (*tp) = 1; RETURN_EXPR (*tp) = NULL_TREE;
else if (TREE_CODE (*tp) == CLEANUP_STMT
&& CLEANUP_DECL (*tp) == nrv)
CLEANUP_EXPR (*tp) = NULL_TREE;
/* Keep iterating. */ /* Keep iterating. */
return NULL_TREE; return NULL_TREE;
...@@ -2601,21 +2603,9 @@ genrtl_start_function (fn) ...@@ -2601,21 +2603,9 @@ genrtl_start_function (fn)
cleanup-generated temporaries. */ cleanup-generated temporaries. */
expand_start_bindings (2); expand_start_bindings (2);
/* Set up the named return value optimization, if we can. */ /* Give our named return value the same RTL as our RESULT_DECL. */
if (current_function_return_value if (current_function_return_value)
&& current_function_return_value != error_mark_node) COPY_DECL_RTL (DECL_RESULT (fn), current_function_return_value);
{
tree r = current_function_return_value;
/* This is only worth doing for fns that return in memory--and
simpler, since we don't have to worry about promoted modes. */
if (aggregate_value_p (TREE_TYPE (TREE_TYPE (fn))))
{
COPY_DECL_RTL (DECL_RESULT (fn), r);
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fn));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
nullify_returns_r, NULL_TREE);
}
}
} }
/* Finish generating the RTL for FN. */ /* Finish generating the RTL for FN. */
......
...@@ -6668,15 +6668,25 @@ check_return_expr (retval) ...@@ -6668,15 +6668,25 @@ check_return_expr (retval)
&& retval != current_class_ref) && retval != current_class_ref)
cp_warning ("`operator=' should return a reference to `*this'"); cp_warning ("`operator=' should return a reference to `*this'");
/* The fabled Named Return Value optimization: If this is a /* The fabled Named Return Value optimization, as per [class.copy]/15:
value-returning function that always returns the same local
variable, remember it. [...] For a function with a class return type, if the expression
in the return statement is the name of a local object, and the cv-
unqualified type of the local object is the same as the function
return type, an implementation is permitted to omit creating the tem-
porary object to hold the function return value [...]
So, if this is a value-returning function that always returns the same
local variable, remember it.
It might be nice to be more flexible, and choose the first suitable It might be nice to be more flexible, and choose the first suitable
variable even if the function sometimes returns something else, but variable even if the function sometimes returns something else, but
then we run the risk of clobbering the variable we chose if the other then we run the risk of clobbering the variable we chose if the other
returned expression uses the chosen variable somehow. And people expect returned expression uses the chosen variable somehow. And people expect
this restriction, anyway. (jason 2000-11-19) */ this restriction, anyway. (jason 2000-11-19)
See finish_function, genrtl_start_function, and declare_return_variable
for other pieces of this optimization. */
if (fn_returns_value_p && flag_elide_constructors) if (fn_returns_value_p && flag_elide_constructors)
{ {
...@@ -6687,9 +6697,11 @@ check_return_expr (retval) ...@@ -6687,9 +6697,11 @@ check_return_expr (retval)
&& DECL_CONTEXT (retval) == current_function_decl && DECL_CONTEXT (retval) == current_function_decl
&& ! TREE_STATIC (retval) && ! TREE_STATIC (retval)
&& (DECL_ALIGN (retval) && (DECL_ALIGN (retval)
== DECL_ALIGN (DECL_RESULT (current_function_decl))) >= DECL_ALIGN (DECL_RESULT (current_function_decl)))
&& same_type_p (TREE_TYPE (retval), && same_type_p ((TYPE_MAIN_VARIANT
TREE_TYPE (TREE_TYPE (current_function_decl)))) (TREE_TYPE (retval))),
(TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_TYPE (current_function_decl))))))
current_function_return_value = retval; current_function_return_value = retval;
else else
current_function_return_value = error_mark_node; current_function_return_value = error_mark_node;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment