OSDN Git Service

Fix PR32824.
[pf3gnuchains/gcc-fork.git] / gcc / tree-cfgcleanup.c
index eae0c84..b8f5a54 100644 (file)
@@ -1,5 +1,5 @@
 /* CFG cleanup for trees.
 /* 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.
    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 "coretypes.h"
 #include "tm.h"
 #include "tree.h"
-#include "rtl.h"
 #include "tm_p.h"
 #include "tm_p.h"
-#include "hard-reg-set.h"
 #include "basic-block.h"
 #include "output.h"
 #include "toplev.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.  */
            /* 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 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);
              }
                  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 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),
                  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;
 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
 
   /* 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
 
   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;
   /* 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;
     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,
   }
 
   /* 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;
        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
          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);
 
 
   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;
 
       && remove_forwarder_block (bb))
     return true;