OSDN Git Service

* trans.c (convert_with_check): Update call to real_2expN.
[pf3gnuchains/gcc-fork.git] / gcc / tree-nrv.c
index f51afdb..9acfb60 100644 (file)
@@ -1,11 +1,11 @@
 /* Language independent return value optimizations
-   Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -133,10 +132,10 @@ tree_nrv (void)
              if (ret_expr)
                gcc_assert (ret_expr == result);
            }
-         else if (TREE_CODE (stmt) == MODIFY_EXPR
-                  && TREE_OPERAND (stmt, 0) == result)
+         else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+                  && GIMPLE_STMT_OPERAND (stmt, 0) == result)
            {
-             ret_expr = TREE_OPERAND (stmt, 1);
+             ret_expr = GIMPLE_STMT_OPERAND (stmt, 1);
 
              /* Now verify that this return statement uses the same value
                 as any previously encountered return statement.  */
@@ -159,8 +158,16 @@ tree_nrv (void)
                  || TREE_STATIC (found)
                  || TREE_ADDRESSABLE (found)
                  || DECL_ALIGN (found) > DECL_ALIGN (result)
-                 || !lang_hooks.types_compatible_p (TREE_TYPE (found), 
-                                                    result_type))
+                 || !useless_type_conversion_p (result_type,
+                                               TREE_TYPE (found)))
+               return 0;
+           }
+         else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT)
+           {
+             tree addr = get_base_address (GIMPLE_STMT_OPERAND (stmt, 0));
+              /* If there's any MODIFY of component of RESULT, 
+                 then bail out.  */
+             if (addr && addr == result)
                return 0;
            }
        }
@@ -197,9 +204,9 @@ tree_nrv (void)
        {
          tree *tp = bsi_stmt_ptr (bsi);
          /* If this is a copy from VAR to RESULT, remove it.  */
-         if (TREE_CODE (*tp) == MODIFY_EXPR
-             && TREE_OPERAND (*tp, 0) == result
-             && TREE_OPERAND (*tp, 1) == found)
+         if (TREE_CODE (*tp) == GIMPLE_MODIFY_STMT
+             && GIMPLE_STMT_OPERAND (*tp, 0) == result
+             && GIMPLE_STMT_OPERAND (*tp, 1) == found)
            bsi_remove (&bsi, true);
          else
            {
@@ -242,29 +249,26 @@ struct tree_opt_pass pass_nrv =
 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;
-    }
+  subvar_t subvar;
+
+  while (handled_component_p (dest))
+    dest = TREE_OPERAND (dest, 0);
+
+  if (! SSA_VAR_P (dest))
+    return false;
+
+  if (TREE_CODE (dest) == SSA_NAME)
+    dest = SSA_NAME_VAR (dest);
+
+  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;
 }
 
-/* Walk through the function looking for MODIFY_EXPRs with calls that
+/* Walk through the function looking for GIMPLE_MODIFY_STMTs 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
    call appropriately if so.
@@ -289,15 +293,15 @@ execute_return_slot_opt (void)
          tree stmt = bsi_stmt (i);
          tree call;
 
-         if (TREE_CODE (stmt) == MODIFY_EXPR
-             && (call = TREE_OPERAND (stmt, 1),
+         if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+             && (call = GIMPLE_STMT_OPERAND (stmt, 1),
                  TREE_CODE (call) == CALL_EXPR)
              && !CALL_EXPR_RETURN_SLOT_OPT (call)
              && aggregate_value_p (call, call))
            /* 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;
+             dest_safe_for_nrv_p (GIMPLE_STMT_OPERAND (stmt, 0)) ? 1 : 0;
        }
     }
   return 0;