OSDN Git Service

* gcc-interface/gigi.h (gnat_mark_addressable): Rename parameter.
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfgcleanup.c
index eae0c84..b8f5a54 100644 (file)
@@ -1,5 +1,5 @@
 /* CFG cleanup for trees.
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -23,9 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "toplev.h"
@@ -103,20 +101,28 @@ cleanup_control_expr_graph (basic_block bb, gimple_stmt_iterator gsi)
            /* For conditions try harder and lookup single-argument
               PHI nodes.  Only do so from the same basic-block though
               as other basic-blocks may be dead already.  */
-           if (TREE_CODE (lhs) == SSA_NAME)
+           if (TREE_CODE (lhs) == SSA_NAME
+               && !name_registered_for_update_p (lhs))
              {
                gimple def_stmt = SSA_NAME_DEF_STMT (lhs);
                if (gimple_code (def_stmt) == GIMPLE_PHI
                    && gimple_phi_num_args (def_stmt) == 1
-                   && gimple_bb (def_stmt) == gimple_bb (stmt))
+                   && gimple_bb (def_stmt) == gimple_bb (stmt)
+                   && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
+                       || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
+                                                                      0))))
                  lhs = PHI_ARG_DEF (def_stmt, 0);
              }
-           if (TREE_CODE (rhs) == SSA_NAME)
+           if (TREE_CODE (rhs) == SSA_NAME
+               && !name_registered_for_update_p (rhs))
              {
                gimple def_stmt = SSA_NAME_DEF_STMT (rhs);
                if (gimple_code (def_stmt) == GIMPLE_PHI
                    && gimple_phi_num_args (def_stmt) == 1
-                   && gimple_bb (def_stmt) == gimple_bb (stmt))
+                   && gimple_bb (def_stmt) == gimple_bb (stmt)
+                   && (TREE_CODE (PHI_ARG_DEF (def_stmt, 0)) != SSA_NAME
+                       || !name_registered_for_update_p (PHI_ARG_DEF (def_stmt,
+                                                                      0))))
                  rhs = PHI_ARG_DEF (def_stmt, 0);
              }
            val = fold_binary_loc (loc, gimple_cond_code (stmt),
@@ -259,6 +265,7 @@ static bool
 tree_forwarder_block_p (basic_block bb, bool phi_wanted)
 {
   gimple_stmt_iterator gsi;
+  location_t locus;
 
   /* BB must have a single outgoing edge.  */
   if (single_succ_p (bb) != 1
@@ -277,6 +284,8 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
   gcc_assert (bb != ENTRY_BLOCK_PTR);
 #endif
 
+  locus = single_succ_edge (bb)->goto_locus;
+
   /* There should not be an edge coming from entry, or an EH edge.  */
   {
     edge_iterator ei;
@@ -285,6 +294,10 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
     FOR_EACH_EDGE (e, ei, bb->preds)
       if (e->src == ENTRY_BLOCK_PTR || (e->flags & EDGE_EH))
        return false;
+      /* If goto_locus of any of the edges differs, prevent removing
+        the forwarder block for -O0.  */
+      else if (optimize == 0 && e->goto_locus != locus)
+       return false;
   }
 
   /* Now walk through the statements backward.  We can ignore labels,
@@ -298,6 +311,8 @@ tree_forwarder_block_p (basic_block bb, bool phi_wanted)
        case GIMPLE_LABEL:
          if (DECL_NONLOCAL (gimple_label_label (stmt)))
            return false;
+         if (optimize == 0 && gimple_location (stmt) != locus)
+           return false;
          break;
 
          /* ??? For now, hope there's a corresponding debug
@@ -600,11 +615,7 @@ cleanup_tree_cfg_bb (basic_block bb)
 
   retval = cleanup_control_flow_bb (bb);
 
-  /* Forwarder blocks can carry line number information which is
-     useful when debugging, so we only clean them up when
-     optimizing.  */
-  if (optimize > 0
-      && tree_forwarder_block_p (bb, false)
+  if (tree_forwarder_block_p (bb, false)
       && remove_forwarder_block (bb))
     return true;