re PR middle-end/25505 (gcc uses way too much stack space for this code)
authorJosh Conner <jconner@apple.com>
Fri, 1 Sep 2006 16:56:14 +0000 (16:56 +0000)
committerJosh Conner <jconner@gcc.gnu.org>
Fri, 1 Sep 2006 16:56:14 +0000 (16:56 +0000)
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

gcc/ChangeLog
gcc/tree-nrv.c

index 246de0c70cc3c07110c1df77404117833ca19d53..922caa534c7ee098a2be6fa9b46c7bd9064722e4 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2006-08-31  Josh Conner  <jconner@apple.com>
 
        PR c++/25505
index 54b964f258343a3d35fdc898884be4d30dfd7b2f..f51afdb258c2d9d554ad4bd2e95772ce4be5a00a 100644 (file)
@@ -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;