diff gcc/tree-cfgcleanup.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children f6334be47118
line wrap: on
line diff
--- a/gcc/tree-cfgcleanup.c	Fri Feb 12 23:41:23 2010 +0900
+++ b/gcc/tree-cfgcleanup.c	Mon May 24 12:47:05 2010 +0900
@@ -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 @@
 #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"
@@ -90,9 +88,55 @@
       edge e;
       edge_iterator ei;
       bool warned;
+      location_t loc;
 
       fold_defer_overflow_warnings ();
-      val = gimple_fold (stmt);
+      loc = gimple_location (stmt);
+      switch (gimple_code (stmt))
+	{
+	case GIMPLE_COND:
+	  {
+	    tree lhs = gimple_cond_lhs (stmt);
+	    tree rhs = gimple_cond_rhs (stmt);
+	    /* 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
+		&& !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)
+		    && (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
+		&& !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)
+		    && (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),
+				   boolean_type_node, lhs, rhs);
+	    break;
+	  }
+
+	case GIMPLE_SWITCH:
+	  val = gimple_switch_index (stmt);
+	  break;
+
+	default:
+	  val = NULL_TREE;
+	}
       taken_edge = find_taken_edge (bb, val);
       if (!taken_edge)
 	{
@@ -221,6 +265,7 @@
 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
@@ -239,6 +284,8 @@
   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;
@@ -247,6 +294,10 @@
     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,
@@ -260,6 +311,8 @@
 	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
@@ -338,7 +391,7 @@
   gimple label;
   edge_iterator ei;
   gimple_stmt_iterator gsi, gsi_to;
-  bool seen_abnormal_edge = false;
+  bool can_move_debug_stmts;
 
   /* We check for infinite loops already in tree_forwarder_block_p.
      However it may happen that the infinite loop is created
@@ -346,12 +399,13 @@
   if (dest == bb)
     return false;
 
-  /* If the destination block consists of a nonlocal label, do not merge
-     it.  */
+  /* If the destination block consists of a nonlocal label or is a
+     EH landing pad, do not merge it.  */
   label = first_stmt (dest);
   if (label
       && gimple_code (label) == GIMPLE_LABEL
-      && DECL_NONLOCAL (gimple_label_label (label)))
+      && (DECL_NONLOCAL (gimple_label_label (label))
+	  || EH_LANDING_PAD_NR (gimple_label_label (label)) != 0))
     return false;
 
   /* If there is an abnormal edge to basic block BB, but not into
@@ -365,14 +419,10 @@
 
      So if there is an abnormal edge to BB, proceed only if there is
      no abnormal edge to DEST and there are no phi nodes in DEST.  */
-  if (has_abnormal_incoming_edge_p (bb))
-    {
-      seen_abnormal_edge = true;
-
-      if (has_abnormal_incoming_edge_p (dest)
-	  || !gimple_seq_empty_p (phi_nodes (dest)))
-	return false;
-    }
+  if (has_abnormal_incoming_edge_p (bb)
+      && (has_abnormal_incoming_edge_p (dest)
+	  || !gimple_seq_empty_p (phi_nodes (dest))))
+    return false;
 
   /* If there are phi nodes in DEST, and some of the blocks that are
      predecessors of BB are also predecessors of DEST, check that the
@@ -390,6 +440,8 @@
 	}
     }
 
+  can_move_debug_stmts = single_pred_p (dest);
+
   /* Redirect the edges.  */
   for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); )
     {
@@ -419,19 +471,44 @@
 	}
     }
 
-  if (seen_abnormal_edge)
+  /* Move nonlocal labels and computed goto targets as well as user
+     defined labels and labels with an EH landing pad number to the
+     new block, so that the redirection of the abnormal edges works,
+     jump targets end up in a sane place and debug information for
+     labels is retained.  */
+  gsi_to = gsi_start_bb (dest);
+  for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
     {
-      /* Move the labels to the new block, so that the redirection of
-	 the abnormal edges works.  */
-      gsi_to = gsi_start_bb (dest);
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
+      tree decl;
+      label = gsi_stmt (gsi);
+      if (is_gimple_debug (label))
+	break;
+      decl = gimple_label_label (label);
+      if (EH_LANDING_PAD_NR (decl) != 0
+	  || DECL_NONLOCAL (decl)
+	  || FORCED_LABEL (decl)
+	  || !DECL_ARTIFICIAL (decl))
 	{
-	  label = gsi_stmt (gsi);
-	  gcc_assert (gimple_code (label) == GIMPLE_LABEL
-		      || is_gimple_debug (label));
 	  gsi_remove (&gsi, false);
 	  gsi_insert_before (&gsi_to, label, GSI_SAME_STMT);
 	}
+      else
+	gsi_next (&gsi);
+    }
+
+  /* Move debug statements if the destination has just a single
+     predecessor.  */
+  if (can_move_debug_stmts)
+    {
+      gsi_to = gsi_after_labels (dest);
+      for (gsi = gsi_after_labels (bb); !gsi_end_p (gsi); )
+	{
+	  gimple debug = gsi_stmt (gsi);
+	  if (!is_gimple_debug (debug))
+	    break;
+	  gsi_remove (&gsi, false);
+	  gsi_insert_before (&gsi_to, debug, GSI_SAME_STMT);
+	}
     }
 
   bitmap_set_bit (cfgcleanup_altered_bbs, dest->index);
@@ -538,11 +615,7 @@
 
   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;
 
@@ -856,7 +929,7 @@
 
       /* We have to feed into another basic block with PHI
 	 nodes.  */
-      if (!phi_nodes (dest)
+      if (gimple_seq_empty_p (phi_nodes (dest))
 	  /* We don't want to deal with a basic block with
 	     abnormal edges.  */
 	  || has_abnormal_incoming_edge_p (bb))