OSDN Git Service

* src/x86/win32.S (_ffi_closure_STDCALL): New function.
[pf3gnuchains/gcc-fork.git] / gcc / tree-nrv.c
index 40e7508..c1e9d60 100644 (file)
@@ -1,5 +1,5 @@
 /* Language independent return value optimizations
-   Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -56,6 +56,7 @@ struct nrv_data
   /* This is the function's RESULT_DECL.  We will replace all occurrences
      of VAR with RESULT_DECL when we apply this optimization.  */
   tree result;
+  int modified;
 };
 
 static tree finalize_nrv_r (tree *, int *, void *);
@@ -83,7 +84,10 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
 
   /* Otherwise replace all occurrences of VAR with RESULT.  */
   else if (*tp == dp->var)
-    *tp = dp->result;
+    {
+      *tp = dp->result;
+      dp->modified = 1;
+    }
 
   /* Keep iterating.  */
   return NULL_TREE;
@@ -121,6 +125,10 @@ tree_nrv (void)
   if (is_gimple_reg_type (result_type))
     return 0;
 
+  /* If the front end already did something like this, don't do it here.  */
+  if (DECL_NAME (result))
+    return 0;
+
   /* Look through each block for assignments to the RESULT_DECL.  */
   FOR_EACH_BB (bb)
     {
@@ -138,8 +146,8 @@ tree_nrv (void)
              if (ret_val)
                gcc_assert (ret_val == result);
            }
-         else if (is_gimple_assign (stmt)
-                  && gimple_assign_lhs (stmt) == result)
+         else if (gimple_has_lhs (stmt)
+                  && gimple_get_lhs (stmt) == result)
            {
               tree rhs;
 
@@ -173,9 +181,9 @@ tree_nrv (void)
                                                TREE_TYPE (found)))
                return 0;
            }
-         else if (is_gimple_assign (stmt))
+         else if (gimple_has_lhs (stmt))
            {
-             tree addr = get_base_address (gimple_assign_lhs (stmt));
+             tree addr = get_base_address (gimple_get_lhs (stmt));
               /* If there's any MODIFY of component of RESULT, 
                  then bail out.  */
              if (addr && addr == result)
@@ -199,10 +207,17 @@ tree_nrv (void)
 
   /* At this point we know that all the return statements return the
      same local which has suitable attributes for NRV.   Copy debugging
-     information from FOUND to RESULT.  */
-  DECL_NAME (result) = DECL_NAME (found);
-  DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found);
-  DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found);
+     information from FOUND to RESULT if it will be useful.  But don't set
+     DECL_ABSTRACT_ORIGIN to point at another function.  */
+  if (!DECL_IGNORED_P (found)
+      && !(DECL_ABSTRACT_ORIGIN (found)
+          && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (found)) != current_function_decl))
+    {
+      DECL_NAME (result) = DECL_NAME (found);
+      DECL_SOURCE_LOCATION (result) = DECL_SOURCE_LOCATION (found);
+      DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found);
+    }
+
   TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found);
 
   /* Now walk through the function changing all references to VAR to be
@@ -218,13 +233,19 @@ tree_nrv (void)
          if (gimple_assign_copy_p (stmt)
              && gimple_assign_lhs (stmt) == result
              && gimple_assign_rhs1 (stmt) == found)
-           gsi_remove (&gsi, true);
+           {
+             unlink_stmt_vdef (stmt);
+             gsi_remove (&gsi, true);
+           }
          else
            {
              struct walk_stmt_info wi;
              memset (&wi, 0, sizeof (wi));
              wi.info = &data;
+             data.modified = 0;
              walk_gimple_op (stmt, finalize_nrv_r, &wi);
+             if (data.modified)
+               update_stmt (stmt);
              gsi_next (&gsi);
            }
        }
@@ -252,7 +273,7 @@ struct gimple_opt_pass pass_nrv =
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
   TV_TREE_NRV,                         /* tv_id */
-  PROP_cfg,                            /* properties_required */
+  PROP_ssa | PROP_cfg,                         /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
@@ -338,8 +359,8 @@ struct gimple_opt_pass pass_return_slot =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
-  PROP_ssa | PROP_alias,               /* properties_required */
+  TV_NONE,                             /* tv_id */
+  PROP_ssa,                            /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */