OSDN Git Service

PR 45189
[pf3gnuchains/gcc-fork.git] / gcc / tree-nrv.c
index c2e49d3..8ee3b8b 100644 (file)
@@ -1,5 +1,6 @@
 /* Language independent return value optimizations
-   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -22,16 +23,17 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "function.h"
 #include "basic-block.h"
-#include "expr.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
 #include "tree-flow.h"
 #include "timevar.h"
 #include "tree-dump.h"
 #include "tree-pass.h"
 #include "langhooks.h"
+#include "flags.h"     /* For "optimize" in gate_pass_return_slot.
+                          FIXME: That should be up to the pass manager,
+                          but pass_nrv is not in pass_all_optimizations.  */
 
 /* This file implements return value optimizations for functions which
    return aggregate types.
@@ -257,6 +259,9 @@ tree_nrv (void)
        }
     }
 
+  SET_DECL_VALUE_EXPR (found, result);
+  DECL_HAS_VALUE_EXPR_P (found) = 1;
+
   /* FOUND is no longer used.  Ensure it gets removed.  */
   var_ann (found)->used = 0;
   return 0;
@@ -291,7 +296,7 @@ struct gimple_opt_pass pass_nrv =
    optimization, where DEST is expected to be the LHS of a modify
    expression where the RHS is a function returning an aggregate.
 
-   DEST is available if it is not clobbered by the call.  */
+   DEST is available if it is not clobbered or used by the call.  */
 
 static bool
 dest_safe_for_nrv_p (gimple call)
@@ -305,7 +310,8 @@ dest_safe_for_nrv_p (gimple call)
   if (TREE_CODE (dest) == SSA_NAME)
     return true;
 
-  if (call_may_clobber_ref_p (call, dest))
+  if (call_may_clobber_ref_p (call, dest)
+      || ref_maybe_used_by_stmt_p (call, dest))
     return false;
 
   return true;
@@ -340,8 +346,7 @@ execute_return_slot_opt (void)
              && gimple_call_lhs (stmt)
              && !gimple_call_return_slot_opt_p (stmt)
              && aggregate_value_p (TREE_TYPE (gimple_call_lhs (stmt)),
-                                   gimple_call_fndecl (stmt))
-            )
+                                   gimple_call_fndecl (stmt)))
            {
              /* Check if the location being assigned to is
                 clobbered by the call.  */