diff mbox

[PR,debug/46931] don't crash propagating removed DEFs into debug stmts

Message ID orfwtqzclc.fsf@livre.localdomain
State New
Headers show

Commit Message

Alexandre Oliva Dec. 22, 2010, 3:54 a.m. UTC
On Dec 21, 2010, Alexandre Oliva <aoliva@redhat.com> wrote:

> The is_gimple_min_invariant() test was a last-minute thought that was
> supposed to be extended so as to handle the case at hand but not other
> expressions that can't be moved about, but that I forgot about before
> testing and posting the patch.  Oops ;-)

Here's a revised version.  Regression-tested on x86_64-linux-gnu after
bootstrap with BOOT_CFLAGS='-O2 -g -ftree-vectorize'.
diff mbox

Patch

for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/46931
	* tree-ssa.c (insert_debug_temp_for_var_def): Handle removed
	assignments.

Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2010-12-18 06:04:11.804255840 -0200
+++ gcc/tree-ssa.c	2010-12-21 05:05:56.394238678 -0200
@@ -305,6 +305,8 @@  insert_debug_temp_for_var_def (gimple_st
   gimple def_stmt = NULL;
   int usecount = 0;
   tree value = NULL;
+  tree value_unshare = NULL;
+  tree temp_value = NULL;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
@@ -421,6 +423,30 @@  insert_debug_temp_for_var_def (gimple_st
 		  || is_gimple_min_invariant (value)))
 	  || is_gimple_reg (value))
 	value = unshare_expr (value);
+      else if (!gsi && !gimple_bb (def_stmt))
+	{
+	  if (is_gimple_val (value))
+	    value_unshare = value;
+	  else if (TREE_SIDE_EFFECTS (value)
+		   || TREE_THIS_VOLATILE (value)
+		   || !is_gimple_assign (def_stmt))
+	    value_unshare = NULL;
+	  else if (!gimple_assign_single_p (def_stmt))
+	    value_unshare = value;
+	  else if (gimple_has_volatile_ops (def_stmt))
+	    value_unshare = NULL;
+	  else
+	    {
+	      enum tree_code_class tcc;
+	      tcc = TREE_CODE_CLASS (gimple_assign_rhs_code (def_stmt));
+	      if (tcc == tcc_reference || tcc == tcc_declaration)
+		value_unshare = NULL;
+	      else
+		value_unshare = value;
+	    }
+
+	  value = NULL;
+	}
       else
 	{
 	  gimple def_temp;
@@ -454,13 +480,48 @@  insert_debug_temp_for_var_def (gimple_st
       if (!gimple_debug_bind_p (stmt))
 	continue;
 
+      /* If we have a value that needs unsharing, unshare it.  Then,
+	 if the debug stmt binds to VAR, we can replace it, otherwise
+	 we'll create a debug temp, bind it to the unshared value
+	 right before STMT, and replace uses of VAR with the debug
+	 temp.  We reuse the same temp for multiple uses, but we don't
+	 attempt to avoid emitting debug temps that would be dominated
+	 by identical debug bind stmts.  */
+      if (value_unshare)
+	{
+	  value = unshare_expr (value_unshare);
+	  if (gimple_debug_bind_get_value (stmt) != var)
+	    {
+	      gimple def_temp;
+	      gimple_stmt_iterator ngsi = gsi_for_stmt (stmt);
+
+	      if (!temp_value)
+		{
+		  temp_value = make_node (DEBUG_EXPR_DECL);
+
+		  DECL_ARTIFICIAL (temp_value) = 1;
+		  TREE_TYPE (temp_value) = TREE_TYPE (value);
+		  if (DECL_P (value))
+		    DECL_MODE (temp_value) = DECL_MODE (value);
+		  else
+		    DECL_MODE (temp_value) = TYPE_MODE (TREE_TYPE (value));
+		}
+
+	      def_temp = gimple_build_debug_bind (temp_value, value,
+						  def_stmt);
+
+	      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+
+	      value = temp_value;
+	    }
+	}
+
       if (value)
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  /* unshare_expr is not needed here.  vexpr is either a
+	  /* unshare_expr is not needed here.  value is either a
 	     SINGLE_RHS, that can be safely shared, some other RHS
 	     that was unshared when we found it had a single debug
-	     use, or a DEBUG_EXPR_DECL, that can be safely
-	     shared.  */
+	     use, or a DEBUG_EXPR_DECL, that can be safely shared.  */
 	  SET_USE (use_p, value);
       else
 	gimple_debug_bind_reset_value (stmt);