OSDN Git Service

* doc/tm.texi (defmac SMALL_REGISTER_CLASSES): Remove.
[pf3gnuchains/gcc-fork.git] / gcc / tree-nrv.c
index c1e9d60..c2e49d3 100644 (file)
@@ -44,7 +44,7 @@ along with GCC; see the file COPYING3.  If not see
    That copy can often be avoided by directly constructing the return value
    into the final destination mandated by the target's ABI.
 
-   This is basically a generic equivalent to the C++ front-end's 
+   This is basically a generic equivalent to the C++ front-end's
    Named Return Value optimization.  */
 
 struct nrv_data
@@ -104,7 +104,7 @@ finalize_nrv_r (tree *tp, int *walk_subtrees, void *data)
    ever encounter languages which prevent this kind of optimization,
    then we could either have the languages register the optimization or
    we could change the gating function to check the current language.  */
-   
+
 static unsigned int
 tree_nrv (void)
 {
@@ -129,6 +129,12 @@ tree_nrv (void)
   if (DECL_NAME (result))
     return 0;
 
+  /* If the result has its address taken then it might be modified
+     by means not detected in the following loop.  Bail out in this
+     case.  */
+  if (TREE_ADDRESSABLE (result))
+    return 0;
+
   /* Look through each block for assignments to the RESULT_DECL.  */
   FOR_EACH_BB (bb)
     {
@@ -178,13 +184,13 @@ tree_nrv (void)
                  || TREE_ADDRESSABLE (found)
                  || DECL_ALIGN (found) > DECL_ALIGN (result)
                  || !useless_type_conversion_p (result_type,
-                                               TREE_TYPE (found)))
+                                                TREE_TYPE (found)))
                return 0;
            }
          else if (gimple_has_lhs (stmt))
            {
              tree addr = get_base_address (gimple_get_lhs (stmt));
-              /* If there's any MODIFY of component of RESULT, 
+              /* If there's any MODIFY of component of RESULT,
                  then bail out.  */
              if (addr && addr == result)
                return 0;
@@ -218,7 +224,7 @@ tree_nrv (void)
       DECL_ABSTRACT_ORIGIN (result) = DECL_ABSTRACT_ORIGIN (found);
     }
 
-  TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (found);
+  TREE_ADDRESSABLE (result) |= TREE_ADDRESSABLE (found);
 
   /* Now walk through the function changing all references to VAR to be
      RESULT.  */
@@ -262,7 +268,7 @@ gate_pass_return_slot (void)
   return optimize > 0;
 }
 
-struct gimple_opt_pass pass_nrv = 
+struct gimple_opt_pass pass_nrv =
 {
  {
   GIMPLE_PASS,
@@ -285,23 +291,21 @@ 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.
 
-   We search for a base VAR_DECL and look to see if it is call clobbered.
-   Note that we could do better, for example, by
-   attempting to doing points-to analysis on INDIRECT_REFs.  */
+   DEST is available if it is not clobbered by the call.  */
 
 static bool
-dest_safe_for_nrv_p (tree dest)
+dest_safe_for_nrv_p (gimple call)
 {
-  while (handled_component_p (dest))
-    dest = TREE_OPERAND (dest, 0);
+  tree dest = gimple_call_lhs (call);
 
-  if (! SSA_VAR_P (dest))
+  dest = get_base_address (dest);
+  if (! dest)
     return false;
 
   if (TREE_CODE (dest) == SSA_NAME)
-    dest = SSA_NAME_VAR (dest);
+    return true;
 
-  if (is_call_used (dest))
+  if (call_may_clobber_ref_p (call, dest))
     return false;
 
   return true;
@@ -340,8 +344,8 @@ execute_return_slot_opt (void)
             )
            {
              /* Check if the location being assigned to is
-                call-clobbered.  */
-             slot_opt_p = dest_safe_for_nrv_p (gimple_call_lhs (stmt));
+                clobbered by the call.  */
+             slot_opt_p = dest_safe_for_nrv_p (stmt);
              gimple_call_set_return_slot_opt (stmt, slot_opt_p);
            }
        }
@@ -349,7 +353,7 @@ execute_return_slot_opt (void)
   return 0;
 }
 
-struct gimple_opt_pass pass_return_slot = 
+struct gimple_opt_pass pass_return_slot =
 {
  {
   GIMPLE_PASS,