summaryrefslogtreecommitdiff
path: root/gcc/tree-nrv.c
diff options
context:
space:
mode:
authorJosh Conner <jconner@apple.com>2006-09-01 16:56:14 +0000
committerJosh Conner <jconner@gcc.gnu.org>2006-09-01 16:56:14 +0000
commitf0ce78583abfc8db21dfa0c577c606c565ef0708 (patch)
tree286ce80371b7865cb1da34874fff2c1465e4f864 /gcc/tree-nrv.c
parent69afd3217ed5b3a232363a518bb1e2174e8797fc (diff)
downloadgcc-f0ce78583abfc8db21dfa0c577c606c565ef0708.tar.gz
re PR middle-end/25505 (gcc uses way too much stack space for this code)
2006-09-01 Josh Conner <jconner@apple.com> PR c++/25505 * tree-nrv.c (dest_safe_for_nrv_p): New function. (execute_return_slot_opt): Use it. From-SVN: r116633
Diffstat (limited to 'gcc/tree-nrv.c')
-rw-r--r--gcc/tree-nrv.c62
1 files changed, 37 insertions, 25 deletions
diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c
index 54b964f2583..f51afdb258c 100644
--- a/gcc/tree-nrv.c
+++ b/gcc/tree-nrv.c
@@ -231,6 +231,39 @@ struct tree_opt_pass pass_nrv =
0 /* letter */
};
+/* Determine (pessimistically) whether DEST is available for NRV
+ optimization, where DEST is expected to be the LHS of a modify
+ expression where the RHS is a function returning an aggregate.
+
+ We search for a base VAR_DECL and look to see if it, or any of its
+ subvars are clobbered. Note that we could do better, for example, by
+ attempting to doing points-to analysis on INDIRECT_REFs. */
+
+static bool
+dest_safe_for_nrv_p (tree dest)
+{
+ switch (TREE_CODE (dest))
+ {
+ case VAR_DECL:
+ {
+ subvar_t subvar;
+ if (is_call_clobbered (dest))
+ return false;
+ for (subvar = get_subvars_for_var (dest);
+ subvar;
+ subvar = subvar->next)
+ if (is_call_clobbered (subvar->var))
+ return false;
+ return true;
+ }
+ case ARRAY_REF:
+ case COMPONENT_REF:
+ return dest_safe_for_nrv_p (TREE_OPERAND (dest, 0));
+ default:
+ return false;
+ }
+}
+
/* Walk through the function looking for MODIFY_EXPRs with calls that
return in memory on the RHS. For each of these, determine whether it is
safe to pass the address of the LHS as the return slot, and mark the
@@ -261,31 +294,10 @@ execute_return_slot_opt (void)
TREE_CODE (call) == CALL_EXPR)
&& !CALL_EXPR_RETURN_SLOT_OPT (call)
&& aggregate_value_p (call, call))
- {
- def_operand_p def_p;
- ssa_op_iter op_iter;
-
- /* We determine whether or not the LHS address escapes by
- asking whether it is call clobbered. When the LHS isn't a
- simple decl, we need to check the VDEFs, so it's simplest
- to just loop through all the DEFs. */
- FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_ALL_DEFS)
- {
- tree def = DEF_FROM_PTR (def_p);
- if (TREE_CODE (def) == SSA_NAME)
- def = SSA_NAME_VAR (def);
- if (is_call_clobbered (def))
- goto unsafe;
- }
-
- /* No defs are call clobbered, so the optimization is safe. */
- CALL_EXPR_RETURN_SLOT_OPT (call) = 1;
- /* This is too late to mark the target addressable like we do
- in gimplify_modify_expr_rhs, but that's OK; anything that
- wasn't already addressable was handled there. */
-
- unsafe:;
- }
+ /* Check if the location being assigned to is
+ call-clobbered. */
+ CALL_EXPR_RETURN_SLOT_OPT (call) =
+ dest_safe_for_nrv_p (TREE_OPERAND (stmt, 0)) ? 1 : 0;
}
}
return 0;