public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PR debug/41343] introduce debug expr temps
@ 2009-09-22 19:51 Alexandre Oliva
  2009-09-23  8:42 ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-09-22 19:51 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3126 bytes --]

This patch enables VTA to assign debug-only names to expressions
formerly computed at a certain point in the code stream, and then use
these names to replace the removed/modified identifiers, instead of
substituting the identifiers for the assigned expression.

IOW, if we start from:

foo_3 = a_1 + b_2;
...
# DEBUG x => foo_3 + bar_4

if we remove the DEF of foo_3, we should get:

# DEBUG D#1 => a_1 + b_2
...
# DEBUG x => D#1 + bar_4

D# are names for debug temps, represented as another kind of
declaration, that never appears in expressions other than debug stmts,
and with counters that don't interfere with the regular declaration
counters (messing with the would cause codegen differences).

This idea came out of Andrew Macleod's debug locus specification.  The
exponential growth of expressions in debug stmts, reported in PR 41343,
made it obvious that we needed something along these lines sooner rather
than later.


I'm not entirely happy with this patch, but it might serve as a stopgap
for the time being.  Some of the points that could be improved are:

- use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
inferred from the TYPE), and an RTL expansion

- avoid emitting multiple redundant copies of the same debug bind stmt
when removing an SSA DEF (*)

- maybe linking VALUEs of DEBUG_EXPR_DECL and the corresponding
expression by VALUE equivalence, rather than handling DECL_EXPR_DECLs as
another kind of variable in var-tracking

- use the explicit presence of DEBUG_EXPR_DECLs to decide whether to use
DW_OP_calls for complex sub-expressions, or inline the subexpressions in
location encoding

- use tuple assign-like forms for debug bind stmts, now possible because
the expression forms are simpler

(*)

ATM we decide to propagate the DEF into debug stmts, we no longer know
even in which block it used to be.  If it has already been unlinked, we
can't even emit the debug bind stmt right before or right after it.

I ended up implementing code to emit multiple copies of the debug bind
stmt, right before each USE.

We could do much better, emitting always a single copy of the debug bind
stmt, say at the block that dominates all USEs, right before the
earliest USE in that block, if there is any, or at the end of the block
otherwise.

But it would be much simpler to just emit the DEBUG use when unlinking
the DEF, so that it remains in the right place.  Failing that, we might
have to be concerned about expressions that vary between the DEF point
and the USE point, say references to global variables or memory
locations.  Code that was in place before simply disregarded that, but
introducing debug temps always at the def point would be a simple and
clean way to fix this, for var-tracking already takes care of noticing
changes and dropping equivalences.


In spite of all these shortcomings, I'd like to propose that we put this
patch in now, while I (we?) work on other urgent issues, and then on
making the improvements mentioned above.

This was regstrapped on x86_64-linux-gnu.  Ok to install?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 15823 bytes --]

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

	PR debug/41343
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (insert_debug_temp_before): New.
	(propagate_var_def_into_debug_stmts): Emit debug temps.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_generic_node): Likewise.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/tree.def	2009-09-22 15:37:13.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-09-22 15:27:26.000000000 -0300
+++ gcc/rtl.def	2009-09-22 15:37:13.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/gengtype.c	2009-09-22 15:37:13.000000000 -0300
@@ -1116,6 +1116,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-09-22 15:27:26.000000000 -0300
+++ gcc/tree-ssa.c	2009-09-22 15:39:55.000000000 -0300
@@ -295,6 +295,16 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
+/* Insert DEF_TEMP before STMT.  */
+
+static void
+insert_debug_temp_before (gimple def_temp, gimple stmt)
+{
+  gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+
+  gsi_insert_before (&gsi, def_temp, GSI_SAME_STMT);
+}
+
 /* Given a VAR whose definition STMT is to be moved to the iterator
    position TOGSIP in the TOBB basic block, verify whether we're
    moving it across any of the debug statements that use it, and
@@ -306,10 +316,11 @@ propagate_var_def_into_debug_stmts (tree
 				    const gimple_stmt_iterator *togsip)
 {
   imm_use_iterator imm_iter;
-  gimple stmt;
+  gimple stmt, def_temp = NULL;
   use_operand_p use_p;
   tree value = NULL;
   bool no_value = false;
+  bool first = true;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
@@ -405,13 +416,45 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else
+	    {
+	      tree temp = make_node (DEBUG_EXPR_DECL);
+
+	      def_temp = gimple_build_debug_bind (temp, unshare_expr (value),
+						  def_stmt);
+
+	      DECL_ARTIFICIAL (temp) = 1;
+	      TREE_TYPE (temp) = TREE_TYPE (value);
+	      if (DECL_P (value))
+		DECL_MODE (temp) = DECL_MODE (value);
+	      else
+		DECL_MODE (temp) = TYPE_MODE (TREE_TYPE (value));
+
+	      value = temp;
+
+	      if (gimple_bb (def_stmt))
+		{
+		  insert_debug_temp_before (def_temp, def_stmt);
+		  def_temp = NULL;
+		}
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
       else
-	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	{
+	  if (def_temp)
+	    {
+	      if (!first)
+		def_temp = gimple_copy (def_temp);
+	      first = false;
+	      insert_debug_temp_before (def_temp, stmt);
+	    }
+
+	  FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
+	    SET_USE (use_p, value);
+	}
 
       update_stmt (stmt);
     }
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/tree.c	2009-09-22 15:37:13.000000000 -0300
@@ -152,6 +152,8 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +874,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +953,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-09-22 15:37:08.000000000 -0300
+++ gcc/cfgexpand.c	2009-09-22 15:37:13.000000000 -0300
@@ -2358,6 +2358,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/var-tracking.c	2009-09-22 15:37:13.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6253,11 +6257,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6279,22 +6284,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6314,7 +6328,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6364,6 +6378,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-09-22 15:27:26.000000000 -0300
+++ gcc/cselib.c	2009-09-22 15:50:35.000000000 -0300
@@ -1213,6 +1213,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-09-22 15:37:13.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-09-22 15:27:28.000000000 -0300
+++ gcc/emit-rtl.c	2009-09-22 15:37:13.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/rtl.c	2009-09-22 15:47:37.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-09-22 15:27:28.000000000 -0300
+++ gcc/print-rtl.c	2009-09-22 15:37:13.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", -DECL_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-09-22 15:27:27.000000000 -0300
+++ gcc/sched-vis.c	2009-09-22 15:37:13.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", -DECL_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 -DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-09-22 15:27:28.000000000 -0300
+++ gcc/tree-dump.c	2009-09-22 15:37:13.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", -DECL_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-09-22 15:27:26.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-09-22 15:37:13.000000000 -0300
@@ -1059,6 +1059,10 @@ dump_generic_node (pretty_printer *buffe
       pp_string (buffer, "<retval>");
       break;
 
+    case DEBUG_EXPR_DECL:
+      pp_printf (buffer, "D#%i", -DECL_UID (node));
+      break;
+
     case COMPONENT_REF:
       op0 = TREE_OPERAND (node, 0);
       str = ".";

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-22 19:51 [PR debug/41343] introduce debug expr temps Alexandre Oliva
@ 2009-09-23  8:42 ` Richard Guenther
  2009-09-23 11:54   ` Richard Guenther
  2009-10-02  7:10   ` Alexandre Oliva
  0 siblings, 2 replies; 25+ messages in thread
From: Richard Guenther @ 2009-09-23  8:42 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Tue, Sep 22, 2009 at 9:32 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> This patch enables VTA to assign debug-only names to expressions
> formerly computed at a certain point in the code stream, and then use
> these names to replace the removed/modified identifiers, instead of
> substituting the identifiers for the assigned expression.
>
> IOW, if we start from:
>
> foo_3 = a_1 + b_2;
> ...
> # DEBUG x => foo_3 + bar_4
>
> if we remove the DEF of foo_3, we should get:
>
> # DEBUG D#1 => a_1 + b_2
> ...
> # DEBUG x => D#1 + bar_4
>
> D# are names for debug temps, represented as another kind of
> declaration, that never appears in expressions other than debug stmts,
> and with counters that don't interfere with the regular declaration
> counters (messing with the would cause codegen differences).
>
> This idea came out of Andrew Macleod's debug locus specification.  The
> exponential growth of expressions in debug stmts, reported in PR 41343,
> made it obvious that we needed something along these lines sooner rather
> than later.
>
>
> I'm not entirely happy with this patch, but it might serve as a stopgap
> for the time being.  Some of the points that could be improved are:
>
> - use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
> don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
> inferred from the TYPE), and an RTL expansion

Use an SSA name with a single unique base variable?

> - avoid emitting multiple redundant copies of the same debug bind stmt
> when removing an SSA DEF (*)

I don't know if you do it (didn't look into the patch yet), but you can avoid
the DEBU_STMTs for single- and zero-use names by keep propagating
or doing nothing.

> - maybe linking VALUEs of DEBUG_EXPR_DECL and the corresponding
> expression by VALUE equivalence, rather than handling DECL_EXPR_DECLs as
> another kind of variable in var-tracking
>
> - use the explicit presence of DEBUG_EXPR_DECLs to decide whether to use
> DW_OP_calls for complex sub-expressions, or inline the subexpressions in
> location encoding
>
> - use tuple assign-like forms for debug bind stmts, now possible because
> the expression forms are simpler

Which wouldn't work anymore if you'd propagate in the single-use case
(but for the time being that would save some stmts and decls).

> (*)
>
> ATM we decide to propagate the DEF into debug stmts, we no longer know
> even in which block it used to be.  If it has already been unlinked, we
> can't even emit the debug bind stmt right before or right after it.
>
> I ended up implementing code to emit multiple copies of the debug bind
> stmt, right before each USE.
>
> We could do much better, emitting always a single copy of the debug bind
> stmt, say at the block that dominates all USEs, right before the
> earliest USE in that block, if there is any, or at the end of the block
> otherwise.
>
> But it would be much simpler to just emit the DEBUG use when unlinking
> the DEF, so that it remains in the right place.  Failing that, we might
> have to be concerned about expressions that vary between the DEF point
> and the USE point, say references to global variables or memory
> locations.  Code that was in place before simply disregarded that, but
> introducing debug temps always at the def point would be a simple and
> clean way to fix this, for var-tracking already takes care of noticing
> changes and dropping equivalences.

Uh.  Please rework that to emit the debug temps at the place of the
DEF.

> In spite of all these shortcomings, I'd like to propose that we put this
> patch in now, while I (we?) work on other urgent issues, and then on
> making the improvements mentioned above.

IMHO there is no need to hurry and not address some of the serious
shortcomings first.

But, I'll have a look at the patch later.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-23  8:42 ` Richard Guenther
@ 2009-09-23 11:54   ` Richard Guenther
  2009-09-23 12:02     ` Richard Guenther
  2009-10-02  7:10   ` Alexandre Oliva
  1 sibling, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-09-23 11:54 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Sep 23, 2009 at 10:17 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Tue, Sep 22, 2009 at 9:32 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> This patch enables VTA to assign debug-only names to expressions
>> formerly computed at a certain point in the code stream, and then use
>> these names to replace the removed/modified identifiers, instead of
>> substituting the identifiers for the assigned expression.
>>
>> IOW, if we start from:
>>
>> foo_3 = a_1 + b_2;
>> ...
>> # DEBUG x => foo_3 + bar_4
>>
>> if we remove the DEF of foo_3, we should get:
>>
>> # DEBUG D#1 => a_1 + b_2
>> ...
>> # DEBUG x => D#1 + bar_4
>>
>> D# are names for debug temps, represented as another kind of
>> declaration, that never appears in expressions other than debug stmts,
>> and with counters that don't interfere with the regular declaration
>> counters (messing with the would cause codegen differences).
>>
>> This idea came out of Andrew Macleod's debug locus specification.  The
>> exponential growth of expressions in debug stmts, reported in PR 41343,
>> made it obvious that we needed something along these lines sooner rather
>> than later.
>>
>>
>> I'm not entirely happy with this patch, but it might serve as a stopgap
>> for the time being.  Some of the points that could be improved are:
>>
>> - use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
>> don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
>> inferred from the TYPE), and an RTL expansion
>
> Use an SSA name with a single unique base variable?
>
>> - avoid emitting multiple redundant copies of the same debug bind stmt
>> when removing an SSA DEF (*)
>
> I don't know if you do it (didn't look into the patch yet), but you can avoid
> the DEBU_STMTs for single- and zero-use names by keep propagating
> or doing nothing.
>
>> - maybe linking VALUEs of DEBUG_EXPR_DECL and the corresponding
>> expression by VALUE equivalence, rather than handling DECL_EXPR_DECLs as
>> another kind of variable in var-tracking
>>
>> - use the explicit presence of DEBUG_EXPR_DECLs to decide whether to use
>> DW_OP_calls for complex sub-expressions, or inline the subexpressions in
>> location encoding
>>
>> - use tuple assign-like forms for debug bind stmts, now possible because
>> the expression forms are simpler
>
> Which wouldn't work anymore if you'd propagate in the single-use case
> (but for the time being that would save some stmts and decls).
>
>> (*)
>>
>> ATM we decide to propagate the DEF into debug stmts, we no longer know
>> even in which block it used to be.  If it has already been unlinked, we
>> can't even emit the debug bind stmt right before or right after it.
>>
>> I ended up implementing code to emit multiple copies of the debug bind
>> stmt, right before each USE.
>>
>> We could do much better, emitting always a single copy of the debug bind
>> stmt, say at the block that dominates all USEs, right before the
>> earliest USE in that block, if there is any, or at the end of the block
>> otherwise.
>>
>> But it would be much simpler to just emit the DEBUG use when unlinking
>> the DEF, so that it remains in the right place.  Failing that, we might
>> have to be concerned about expressions that vary between the DEF point
>> and the USE point, say references to global variables or memory
>> locations.  Code that was in place before simply disregarded that, but
>> introducing debug temps always at the def point would be a simple and
>> clean way to fix this, for var-tracking already takes care of noticing
>> changes and dropping equivalences.
>
> Uh.  Please rework that to emit the debug temps at the place of the
> DEF.

Hmhm.  Thinking about this I'm not sure how new debug temps at the definition
site would work.  Consider

  a = 1;
# DEBUG D#1 => a
..
  a = 0;
# DEBUG i => D#1

how would the debug info look like so that gdb picks up the correct
value of a if we do 'print i' at the location of the debug stmt for it?
How would things work here if the debug temp would be placed before
the use like

  a = 1;
...
  a = 0;
# DEBUG D#1 => a
# DEBUG i => D#1

?  Not any easier I guess.  In fact it seems that propagating a non-expression
or register RHS is always bogus and possibly creates wrong debug information
if it doesn't consult alias information?

Testcase:

int a;

int foo()
{
  int tmp = a;
  int tmp2 = a;
  int tmp3;
  int res;
  a = 0;
  tmp3 = tmp2;
  res = tmp - tmp2 + 1;
  return res;
}

and after the copyprop after FRE we have

<bb 2>:
  # DEBUG tmp => a
  # DEBUG tmp2 => a
  a = 0;
  # DEBUG tmp3 => a
  res_5 = 1;
  # DEBUG res => res_5
  return res_5;

so suddenly printing tmp3 will print 0.

>> In spite of all these shortcomings, I'd like to propose that we put this
>> patch in now, while I (we?) work on other urgent issues, and then on
>> making the improvements mentioned above.
>
> IMHO there is no need to hurry and not address some of the serious
> shortcomings first.
>
> But, I'll have a look at the patch later.

In the propagate_var_def_into_debug_stmts hunk I notice you seem to
insert the debug temp stmt at the definition for each use stmt instead
of just once?  But really that function is now very hard to follow.

From looking at the patch using SSA names instead of DEBUG_EXRP_DECL
would be a lot easier I think, not requiring next_debug_decl_uid and
saving you memory even.  You'd even have use-def links from debug stmt
uses to debug temp definitions ... (well, ideally you'd simply mark the
original stmt as "for debugging only" but keep it as is, not propagating).

Most of the rest of the patch really builds on the DECL idea, so I'm waiting
for you to wake up and comment on my comments.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-23 11:54   ` Richard Guenther
@ 2009-09-23 12:02     ` Richard Guenther
  2009-09-30  8:24       ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-09-23 12:02 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Sep 23, 2009 at 1:37 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Sep 23, 2009 at 10:17 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Tue, Sep 22, 2009 at 9:32 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> This patch enables VTA to assign debug-only names to expressions
>>> formerly computed at a certain point in the code stream, and then use
>>> these names to replace the removed/modified identifiers, instead of
>>> substituting the identifiers for the assigned expression.
>>>
>>> IOW, if we start from:
>>>
>>> foo_3 = a_1 + b_2;
>>> ...
>>> # DEBUG x => foo_3 + bar_4
>>>
>>> if we remove the DEF of foo_3, we should get:
>>>
>>> # DEBUG D#1 => a_1 + b_2
>>> ...
>>> # DEBUG x => D#1 + bar_4
>>>
>>> D# are names for debug temps, represented as another kind of
>>> declaration, that never appears in expressions other than debug stmts,
>>> and with counters that don't interfere with the regular declaration
>>> counters (messing with the would cause codegen differences).
>>>
>>> This idea came out of Andrew Macleod's debug locus specification.  The
>>> exponential growth of expressions in debug stmts, reported in PR 41343,
>>> made it obvious that we needed something along these lines sooner rather
>>> than later.
>>>
>>>
>>> I'm not entirely happy with this patch, but it might serve as a stopgap
>>> for the time being.  Some of the points that could be improved are:
>>>
>>> - use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
>>> don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
>>> inferred from the TYPE), and an RTL expansion
>>
>> Use an SSA name with a single unique base variable?
>>
>>> - avoid emitting multiple redundant copies of the same debug bind stmt
>>> when removing an SSA DEF (*)
>>
>> I don't know if you do it (didn't look into the patch yet), but you can avoid
>> the DEBU_STMTs for single- and zero-use names by keep propagating
>> or doing nothing.
>>
>>> - maybe linking VALUEs of DEBUG_EXPR_DECL and the corresponding
>>> expression by VALUE equivalence, rather than handling DECL_EXPR_DECLs as
>>> another kind of variable in var-tracking
>>>
>>> - use the explicit presence of DEBUG_EXPR_DECLs to decide whether to use
>>> DW_OP_calls for complex sub-expressions, or inline the subexpressions in
>>> location encoding
>>>
>>> - use tuple assign-like forms for debug bind stmts, now possible because
>>> the expression forms are simpler
>>
>> Which wouldn't work anymore if you'd propagate in the single-use case
>> (but for the time being that would save some stmts and decls).
>>
>>> (*)
>>>
>>> ATM we decide to propagate the DEF into debug stmts, we no longer know
>>> even in which block it used to be.  If it has already been unlinked, we
>>> can't even emit the debug bind stmt right before or right after it.
>>>
>>> I ended up implementing code to emit multiple copies of the debug bind
>>> stmt, right before each USE.
>>>
>>> We could do much better, emitting always a single copy of the debug bind
>>> stmt, say at the block that dominates all USEs, right before the
>>> earliest USE in that block, if there is any, or at the end of the block
>>> otherwise.
>>>
>>> But it would be much simpler to just emit the DEBUG use when unlinking
>>> the DEF, so that it remains in the right place.  Failing that, we might
>>> have to be concerned about expressions that vary between the DEF point
>>> and the USE point, say references to global variables or memory
>>> locations.  Code that was in place before simply disregarded that, but
>>> introducing debug temps always at the def point would be a simple and
>>> clean way to fix this, for var-tracking already takes care of noticing
>>> changes and dropping equivalences.
>>
>> Uh.  Please rework that to emit the debug temps at the place of the
>> DEF.
>
> Hmhm.  Thinking about this I'm not sure how new debug temps at the definition
> site would work.  Consider
>
>  a = 1;
> # DEBUG D#1 => a
> ..
>  a = 0;
> # DEBUG i => D#1
>
> how would the debug info look like so that gdb picks up the correct
> value of a if we do 'print i' at the location of the debug stmt for it?
> How would things work here if the debug temp would be placed before
> the use like
>
>  a = 1;
> ...
>  a = 0;
> # DEBUG D#1 => a
> # DEBUG i => D#1
>
> ?  Not any easier I guess.  In fact it seems that propagating a non-expression
> or register RHS is always bogus and possibly creates wrong debug information
> if it doesn't consult alias information?
>
> Testcase:
>
> int a;
>
> int foo()
> {
>  int tmp = a;
>  int tmp2 = a;
>  int tmp3;
>  int res;
>  a = 0;
>  tmp3 = tmp2;
>  res = tmp - tmp2 + 1;
>  return res;
> }
>
> and after the copyprop after FRE we have
>
> <bb 2>:
>  # DEBUG tmp => a
>  # DEBUG tmp2 => a
>  a = 0;
>  # DEBUG tmp3 => a
>  res_5 = 1;
>  # DEBUG res => res_5
>  return res_5;
>
> so suddenly printing tmp3 will print 0.

In fact nothing is preventing the a = 0; store to be moved before
the two other debug stmts either - so whenever we do such thing
(code hoisting, scheduling, sinking) all debug insns that "alias" and
we happen to cross have to be invalidated.

:/

I think there's a load of wrong-debug issues latent right now.

Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-23 12:02     ` Richard Guenther
@ 2009-09-30  8:24       ` Alexandre Oliva
  2009-09-30  9:54         ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-09-30  8:24 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Sep 23, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

>> Hmhm.  Thinking about this I'm not sure how new debug temps at the definition
>> site would work.  Consider

>> a = 1;
>> # DEBUG D#1 => a
>> ..
>> a = 0;
>> # DEBUG i => D#1

>> how would the debug info look like so that gdb picks up the correct
>> value of a if we do 'print i' at the location of the debug stmt for it?

Remember that a lot of stuff happens between having notes and emtting
the actual debug info, and don't forget that the debug bind statements
bind values, rather than locations.

In var-tracking, when we reach the D#1 => a debug insn (it won't be a
any longer, but a REG or MEM, but that's a detail we can disregard),
we'll note that D#1 binds to a VALUE rtx that is, at that point,
equivalent to the REG or MEM where the (const_int 1) was stored, and to
the constant integer itself.

Later on, when var-tracking notices that that REG or MEM is modified, it
discards the equivalence between the VALUE and the REG or MEM.

Then, when i is bound to the value of D#1, we emit a location for i
corresponding to the equivalences of that VALUE at the bind point of i.
The REG or MEM will have already been discarded.

Likewise, if D#1 was a regular variable, rather than a debug temp, we'd
emit a location note for D#1 at its bind point, and when we reached “a =
0“, we'd emit another location note reflecting the change to the value.

>> How would things work here if the debug temp would be placed before
>> the use like
>> 
>>  a = 1;
>> ...
>>  a = 0;
>> # DEBUG D#1 => a
>> # DEBUG i => D#1

This transformation would be an error.  It should not happen.  I don't
have any evidence that it does.

The current propagation of debug values may indeed be introducing this
kind of distortion when it comes to non-gimple-regs, mems, etc.  An
upcoming version of this patch should fix it, emitting debug temps
*always* at the location of the removed assignment.

>> <bb 2>:
>>  # DEBUG tmp => a
>>  # DEBUG tmp2 => a
>>  a = 0;
>>  # DEBUG tmp3 => a
>>  res_5 = 1;
>>  # DEBUG res => res_5
>>  return res_5;
>> 
>> so suddenly printing tmp3 will print 0.

> In fact nothing is preventing the a = 0; store to be moved before
> the two other debug stmts either

What's preventing it is the same code that prevents us from breaking
executable code.  Say, if we had:

  <bb 2>
    foo = a;
    a = 0

we wouldn't be allowed to move a = 0 before foo = a.  Optimizers
shouldn't ignore uses along the way, and although they might have to
disregard debug stmts when making decision, they ought to adjust them
just like they would should they make transformations that would affect
executable code.

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-30  8:24       ` Alexandre Oliva
@ 2009-09-30  9:54         ` Richard Guenther
  2009-10-02  6:06           ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-09-30  9:54 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Sep 30, 2009 at 9:25 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Sep 23, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>>> Hmhm.  Thinking about this I'm not sure how new debug temps at the definition
>>> site would work.  Consider
>
>>> a = 1;
>>> # DEBUG D#1 => a
>>> ..
>>> a = 0;
>>> # DEBUG i => D#1
>
>>> how would the debug info look like so that gdb picks up the correct
>>> value of a if we do 'print i' at the location of the debug stmt for it?
>
> Remember that a lot of stuff happens between having notes and emtting
> the actual debug info, and don't forget that the debug bind statements
> bind values, rather than locations.
>
> In var-tracking, when we reach the D#1 => a debug insn (it won't be a
> any longer, but a REG or MEM, but that's a detail we can disregard),
> we'll note that D#1 binds to a VALUE rtx that is, at that point,
> equivalent to the REG or MEM where the (const_int 1) was stored, and to
> the constant integer itself.
>
> Later on, when var-tracking notices that that REG or MEM is modified, it
> discards the equivalence between the VALUE and the REG or MEM.
>
> Then, when i is bound to the value of D#1, we emit a location for i
> corresponding to the equivalences of that VALUE at the bind point of i.
> The REG or MEM will have already been discarded.
>
> Likewise, if D#1 was a regular variable, rather than a debug temp, we'd
> emit a location note for D#1 at its bind point, and when we reached “a =
> 0“, we'd emit another location note reflecting the change to the value.
>
>>> How would things work here if the debug temp would be placed before
>>> the use like
>>>
>>>  a = 1;
>>> ...
>>>  a = 0;
>>> # DEBUG D#1 => a
>>> # DEBUG i => D#1
>
> This transformation would be an error.  It should not happen.  I don't
> have any evidence that it does.
>
> The current propagation of debug values may indeed be introducing this
> kind of distortion when it comes to non-gimple-regs, mems, etc.  An
> upcoming version of this patch should fix it, emitting debug temps
> *always* at the location of the removed assignment.
>
>>> <bb 2>:
>>>  # DEBUG tmp => a
>>>  # DEBUG tmp2 => a
>>>  a = 0;
>>>  # DEBUG tmp3 => a
>>>  res_5 = 1;
>>>  # DEBUG res => res_5
>>>  return res_5;
>>>
>>> so suddenly printing tmp3 will print 0.
>
>> In fact nothing is preventing the a = 0; store to be moved before
>> the two other debug stmts either
>
> What's preventing it is the same code that prevents us from breaking
> executable code.  Say, if we had:
>
>  <bb 2>
>    foo = a;
>    a = 0
>
> we wouldn't be allowed to move a = 0 before foo = a.  Optimizers
> shouldn't ignore uses along the way, and although they might have to
> disregard debug stmts when making decision, they ought to adjust them
> just like they would should they make transformations that would affect
> executable code.

But they don't see the DEBUG_STMT uses because DEBUG_STMTs
do not have virtual operands.

Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-30  9:54         ` Richard Guenther
@ 2009-10-02  6:06           ` Alexandre Oliva
  0 siblings, 0 replies; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-02  6:06 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Sep 30, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> On Wed, Sep 30, 2009 at 9:25 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> What's preventing it is the same code that prevents us from breaking
>> executable code.  Say, if we had:
>> 
>>  <bb 2>
>>    foo = a;
>>    a = 0
>> 
>> we wouldn't be allowed to move a = 0 before foo = a.  Optimizers
>> shouldn't ignore uses along the way, and although they might have to
>> disregard debug stmts when making decision, they ought to adjust them
>> just like they would should they make transformations that would affect
>> executable code.

> But they don't see the DEBUG_STMT uses because DEBUG_STMTs
> do not have virtual operands.

Uhh...  Maybe debug stmts should have VOPs, then...  I don't remember
having thought much about whether or not they should.  I ended up doing
without them, but from what you say I conclude it was a mistake.  Ugh.

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-09-23  8:42 ` Richard Guenther
  2009-09-23 11:54   ` Richard Guenther
@ 2009-10-02  7:10   ` Alexandre Oliva
  2009-10-03 15:02     ` Richard Guenther
  1 sibling, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-02  7:10 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1498 bytes --]

On Sep 23, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> On Tue, Sep 22, 2009 at 9:32 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> - use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
>> don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
>> inferred from the TYPE), and an RTL expansion

> Use an SSA name with a single unique base variable?

If you mean using objects with SSA_NAME tree code, I'd rather not.  I
think this would make for a lot of ambiguity and trouble.  We can't even
use the same version namespace, for varying version numbers has also
been known to cause codegen differences.

Now, if you mean some other tree code that uses the same tree_ssa_name
data structure, that's an idea, but the only field in it that's relevant
is the version number, and it doesn't have room for the corresponding
RTX.

Besides, as far as var-tracking is concerned, there are short-term
benefits to having a DECL, for var-tracking already knows how to deal
with DECLs.  Adding support for yet another type of object (tree or rtx)
would be a bit of a pain, and it could make var-tracking quite slower.

I'm thinking of maybe introducing another data type with a common prefix
to decl_minimal, or even another base type for decl_minimal.  But that's
something for another version of the patch.

> Uh.  Please rework that to emit the debug temps at the place of the
> DEF.

Done.  Here's the updated patch.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 25040 bytes --]

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

	PR debug/41343
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace, gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_bittest, move_computations_stmt): Drop
	propagation into debug stmts.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-09-30 05:44:40.000000000 -0300
+++ gcc/tree.def	2009-09-30 05:48:53.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-09-30 05:44:39.000000000 -0300
+++ gcc/rtl.def	2009-09-30 05:48:53.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-09-30 05:48:00.000000000 -0300
+++ gcc/gengtype.c	2009-09-30 05:48:53.000000000 -0300
@@ -1118,6 +1118,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-09-30 05:44:37.000000000 -0300
+++ gcc/tree-ssa.c	2009-09-30 13:36:04.000000000 -0300
@@ -295,15 +295,12 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
   gimple stmt;
@@ -316,49 +313,25 @@ propagate_var_def_into_debug_stmts (tree
 
   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
-
       if (!is_gimple_debug (stmt))
 	continue;
 
-      if (tobb)
-	{
-	  bb = gimple_bb (stmt);
-
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
-
-	      if (gsi_end_p (si))
-		continue;
-
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
-
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
-
       /* Here we compute (lazily) the value assigned to VAR, but we
 	 remember if we tried before and failed, so that we don't try
 	 again.  */
       if (!value && !no_value)
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  gimple def_stmt;
 
+	  if (gsi)
+	    def_stmt = gsi_stmt (*gsi);
+	  else
+	    def_stmt = SSA_NAME_DEF_STMT (var);
+
+	  /* If we didn't get an insertion point, and the stmt has
+	     already been removed, we won't be able to insert the
+	     debug bind stmt, so we'll have to drop debug
+	     information.  */
 	  if (is_gimple_assign (def_stmt))
 	    {
 	      if (!dom_info_available_p (CDI_DOMINATORS))
@@ -395,7 +368,9 @@ propagate_var_def_into_debug_stmts (tree
 		     wrong order, so we don't even check for dead SSA
 		     NAMEs.  SSA verification shall catch any
 		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
+		  if ((!gsi && !gimple_bb (def_stmt))
+		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+					  &wi))
 		    no_value = true;
 		}
 
@@ -405,42 +380,68 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else
+	    {
+	      tree temp = make_node (DEBUG_EXPR_DECL);
+	      gimple def_temp;
+
+	      def_temp = gimple_build_debug_bind (temp, unshare_expr (value),
+						  def_stmt);
+
+	      DECL_ARTIFICIAL (temp) = 1;
+	      TREE_TYPE (temp) = TREE_TYPE (value);
+	      if (DECL_P (value))
+		DECL_MODE (temp) = DECL_MODE (value);
+	      else
+		DECL_MODE (temp) = TYPE_MODE (TREE_TYPE (value));
+
+	      value = temp;
+
+	      if (gsi)
+		gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+	      else
+		{
+		  gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+		  gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+		}
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
       else
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  SET_USE (use_p, value);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-09-30 05:44:39.000000000 -0300
+++ gcc/tree.c	2009-09-30 05:48:53.000000000 -0300
@@ -152,6 +152,8 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +874,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +953,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-09-30 05:44:39.000000000 -0300
+++ gcc/cfgexpand.c	2009-09-30 05:48:53.000000000 -0300
@@ -2358,6 +2358,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-09-30 05:44:40.000000000 -0300
+++ gcc/var-tracking.c	2009-09-30 05:48:53.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-09-30 05:44:38.000000000 -0300
+++ gcc/cselib.c	2009-09-30 05:48:53.000000000 -0300
@@ -1213,6 +1213,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-09-30 05:44:40.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-09-30 05:48:53.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-09-30 05:44:41.000000000 -0300
+++ gcc/emit-rtl.c	2009-09-30 05:48:53.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-09-30 05:44:39.000000000 -0300
+++ gcc/rtl.c	2009-09-30 05:48:53.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-09-30 05:44:41.000000000 -0300
+++ gcc/print-rtl.c	2009-09-30 05:48:53.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", -DECL_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-09-30 05:44:40.000000000 -0300
+++ gcc/sched-vis.c	2009-09-30 05:48:53.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", -DECL_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 -DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-09-30 05:44:41.000000000 -0300
+++ gcc/tree-dump.c	2009-09-30 05:48:53.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", -DECL_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-09-30 05:44:38.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-09-30 05:48:53.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", -DECL_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-09-30 05:44:38.000000000 -0300
+++ gcc/gimple-iterator.c	2009-09-30 05:48:53.000000000 -0300
@@ -368,6 +368,8 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  insert_debug_temps_for_defs (gsi);
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +472,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-09-30 05:44:38.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-09-30 05:48:53.000000000 -0300
@@ -879,7 +879,6 @@ rewrite_bittest (gimple_stmt_iterator *b
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
       gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
       gsi_replace (bsi, stmt2, true);
 
       return stmt1;
@@ -1060,7 +1059,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-09-30 05:44:37.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-09-30 05:48:53.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-09-30 05:44:40.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-09-30 05:48:53.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-09-30 05:44:41.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-09-30 05:48:53.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-09-30 05:44:37.000000000 -0300
+++ gcc/tree-ssanames.c	2009-09-30 06:31:07.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-09-30 05:48:50.000000000 -0300
+++ gcc/tree-flow.h	2009-09-30 06:30:41.000000000 -0300
@@ -636,10 +636,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-02  7:10   ` Alexandre Oliva
@ 2009-10-03 15:02     ` Richard Guenther
  2009-10-06  6:43       ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-03 15:02 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Fri, Oct 2, 2009 at 9:10 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Sep 23, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>> On Tue, Sep 22, 2009 at 9:32 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
>>> - use something smaller than a DECL structure for DEBUG_EXPR_DECLs.  We
>>> don't need all the stuff in a DECL, just a uid, a TYPE, a MODE (could be
>>> inferred from the TYPE), and an RTL expansion
>
>> Use an SSA name with a single unique base variable?
>
> If you mean using objects with SSA_NAME tree code, I'd rather not.  I
> think this would make for a lot of ambiguity and trouble.  We can't even
> use the same version namespace, for varying version numbers has also
> been known to cause codegen differences.
>
> Now, if you mean some other tree code that uses the same tree_ssa_name
> data structure, that's an idea, but the only field in it that's relevant
> is the version number, and it doesn't have room for the corresponding
> RTX.
>
> Besides, as far as var-tracking is concerned, there are short-term
> benefits to having a DECL, for var-tracking already knows how to deal
> with DECLs.  Adding support for yet another type of object (tree or rtx)
> would be a bit of a pain, and it could make var-tracking quite slower.
>
> I'm thinking of maybe introducing another data type with a common prefix
> to decl_minimal, or even another base type for decl_minimal.  But that's
> something for another version of the patch.

Hm, ok.  One reason why I liked the idea of using SSA_NAMEs much is
that it would make it very easy to get rid of old no longer used debug
temps.  How do you address this?

That is, I'd very much like to see some statistics on the number of
debug temps (vs. debug-binds and vs. regular stmts).

>> Uh.  Please rework that to emit the debug temps at the place of the
>> DEF.
>
> Done.  Here's the updated patch.

Any reason why in

+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+       DECL_UID (t) = --next_debug_decl_uid;

you count backward?  You always print the negative value later...

@@ -368,6 +368,8 @@ gsi_replace (gimple_stmt_iterator *gsi,
   if (stmt == orig_stmt)
     return;

+  insert_debug_temps_for_defs (gsi);
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));

@@ -470,6 +472,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);

+  insert_debug_temps_for_defs (i);
+

for both gsi_replace and gsi_remove you shouldn't really insert
debug-temps.  The replaced/removed stmt may be inserted elsewhere
again and this makes these operations very expensive.  Please leave
the debug handling in the few callers that did this before.

@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));

       if (MAY_HAVE_DEBUG_STMTS)
-       propagate_var_def_into_debug_stmts (var, NULL, NULL);
+       insert_debug_temp_for_var_def (NULL, var);

and here I thought that doesn't work because the stmt is already
unlinked?

If you want it more generic I'd say we want to have a release_defs_p
argument to gsi_remove () / gsi_replace () that controls whether
the removed/replaced stmt is going to die.  Just like we have for phi nodes.

On the RTL parts I don't have a strong opinion - though I wonder why
VALUE flows in here so much (I though that was only a cselib thing).

Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-03 15:02     ` Richard Guenther
@ 2009-10-06  6:43       ` Alexandre Oliva
  2009-10-06 10:30         ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-06  6:43 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 3042 bytes --]

On Oct  3, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> Hm, ok.  One reason why I liked the idea of using SSA_NAMEs much is
> that it would make it very easy to get rid of old no longer used debug
> temps.  How do you address this?

I don't.  I'm not sure we're going to have very many of these.  Say, a
debug temp bind should only become dead if we were to remove the basic
block containing the only reference to the debug temp.  In general we do
this only when the block is unreachable.  But if the block is
unreachable, we'd remove it before the debug temp was introduced, and
the absence of references to the DEF would prevent the creation of the
debug temp in the first place.

Of course we could construct cases in which the order of creation of the
debug temp and the removal of the blocks would cause it to remain
around.  I have an intuition that this won't happen very often, though.
I guess I should try to substantiate this intuition ;-)

Anyhow, if we find it not to be true, it shouldn't be too hard to get
debug temps into SSA operands, especially if we're to add vops to debug
bind stmts as well.

> Any reason why in

> +      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
> +       DECL_UID (t) = --next_debug_decl_uid;

> you count backward?  You always print the negative value later...

Mainly to make accidental overlaps with DECL_UIDs less likely.  I
figured negative values would cause crashes or errors if we used
DECL_UIDs inappropriately.

> for both gsi_replace and gsi_remove you shouldn't really insert
> debug-temps.  The replaced/removed stmt may be inserted elsewhere
> again

But the bind point is that where the stmt was before, and the moved DEF
might very well be referenced at a point between the bind point and the
reinsertion point.

> @@ -206,7 +206,7 @@ release_ssa_name (tree var)
>        use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));

>        if (MAY_HAVE_DEBUG_STMTS)
> -       propagate_var_def_into_debug_stmts (var, NULL, NULL);
> +       insert_debug_temp_for_var_def (NULL, var);

> and here I thought that doesn't work because the stmt is already
> unlinked?

It works, but it will drop debug expressions that refer to the removed
DEF, instead of replacing them with a debug temp.

> If you want it more generic I'd say we want to have a release_defs_p
> argument to gsi_remove () / gsi_replace () that controls whether
> the removed/replaced stmt is going to die.

That's not enough, and it would require bringing back the sequential
searching for uses in the same block, and the requirements for
domination information, that isn't always available.

> On the RTL parts I don't have a strong opinion - though I wonder why
> VALUE flows in here so much (I though that was only a cselib thing).

VTA uses cselib heavily.


Here's an updated patch I'm testing, that fixes a debug regression in
tree-ssa-dce: when removing a SSA DEF that caused a debug bind stmt to
be introduced, we'd remove debug bind stmts shortly thereafter, because
they wouldn't be marked as necessary.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 26630 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace, gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_bittest, move_computations_stmt): Drop
	propagation into debug stmts.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.
	* tree-ssa-dce.c (eliminate_unnecessary_stmts): Don't discard
	just-inserted debug stmts.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/tree.def	2009-10-02 03:02:54.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/rtl.def	2009-10-02 03:02:54.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/gengtype.c	2009-10-02 03:02:54.000000000 -0300
@@ -1118,6 +1118,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-10-02 02:56:06.000000000 -0300
+++ gcc/tree-ssa.c	2009-10-02 03:02:55.000000000 -0300
@@ -295,15 +295,12 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
   gimple stmt;
@@ -316,49 +313,25 @@ propagate_var_def_into_debug_stmts (tree
 
   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
-
       if (!is_gimple_debug (stmt))
 	continue;
 
-      if (tobb)
-	{
-	  bb = gimple_bb (stmt);
-
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
-
-	      if (gsi_end_p (si))
-		continue;
-
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
-
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
-
       /* Here we compute (lazily) the value assigned to VAR, but we
 	 remember if we tried before and failed, so that we don't try
 	 again.  */
       if (!value && !no_value)
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  gimple def_stmt;
 
+	  if (gsi)
+	    def_stmt = gsi_stmt (*gsi);
+	  else
+	    def_stmt = SSA_NAME_DEF_STMT (var);
+
+	  /* If we didn't get an insertion point, and the stmt has
+	     already been removed, we won't be able to insert the
+	     debug bind stmt, so we'll have to drop debug
+	     information.  */
 	  if (is_gimple_assign (def_stmt))
 	    {
 	      if (!dom_info_available_p (CDI_DOMINATORS))
@@ -395,7 +368,9 @@ propagate_var_def_into_debug_stmts (tree
 		     wrong order, so we don't even check for dead SSA
 		     NAMEs.  SSA verification shall catch any
 		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
+		  if ((!gsi && !gimple_bb (def_stmt))
+		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+					  &wi))
 		    no_value = true;
 		}
 
@@ -405,42 +380,68 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else
+	    {
+	      tree temp = make_node (DEBUG_EXPR_DECL);
+	      gimple def_temp;
+
+	      def_temp = gimple_build_debug_bind (temp, unshare_expr (value),
+						  def_stmt);
+
+	      DECL_ARTIFICIAL (temp) = 1;
+	      TREE_TYPE (temp) = TREE_TYPE (value);
+	      if (DECL_P (value))
+		DECL_MODE (temp) = DECL_MODE (value);
+	      else
+		DECL_MODE (temp) = TYPE_MODE (TREE_TYPE (value));
+
+	      value = temp;
+
+	      if (gsi)
+		gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+	      else
+		{
+		  gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+		  gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+		}
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
       else
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  SET_USE (use_p, value);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/tree.c	2009-10-02 03:02:55.000000000 -0300
@@ -152,6 +152,8 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +874,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +953,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/cfgexpand.c	2009-10-02 03:02:55.000000000 -0300
@@ -2358,6 +2358,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/var-tracking.c	2009-10-02 03:02:55.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/cselib.c	2009-10-02 03:02:55.000000000 -0300
@@ -1213,6 +1213,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-10-02 03:02:55.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-10-02 02:56:09.000000000 -0300
+++ gcc/emit-rtl.c	2009-10-02 03:02:55.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/rtl.c	2009-10-02 03:02:55.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-10-02 02:56:09.000000000 -0300
+++ gcc/print-rtl.c	2009-10-02 03:02:55.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", -DECL_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/sched-vis.c	2009-10-02 03:02:55.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", -DECL_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 -DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-10-02 02:56:09.000000000 -0300
+++ gcc/tree-dump.c	2009-10-02 03:02:55.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", -DECL_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-10-02 03:02:55.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", -DECL_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/gimple-iterator.c	2009-10-02 03:02:55.000000000 -0300
@@ -368,6 +368,8 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  insert_debug_temps_for_defs (gsi);
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +472,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-10-02 02:56:07.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-10-02 03:02:55.000000000 -0300
@@ -879,7 +879,6 @@ rewrite_bittest (gimple_stmt_iterator *b
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
       gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
       gsi_replace (bsi, stmt2, true);
 
       return stmt1;
@@ -1060,7 +1059,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-10-02 02:56:06.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-10-02 03:02:55.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-10-02 03:02:55.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-10-02 02:56:08.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-10-02 03:02:55.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-10-02 02:56:06.000000000 -0300
+++ gcc/tree-ssanames.c	2009-10-02 03:02:55.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-10-02 02:56:12.000000000 -0300
+++ gcc/tree-flow.h	2009-10-02 03:02:55.000000000 -0300
@@ -636,10 +636,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-09-22 15:11:30.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-10-06 01:46:01.000000000 -0300
@@ -1071,7 +1071,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1111,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
 	{
 	  stmt = gsi_stmt (gsi);
 
+	  psi = gsi;
+	  gsi_prev (&psi);
+
 	  stats.total++;
 
 	  /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1125,6 @@ eliminate_unnecessary_stmts (void)
 	    {
 	      remove_dead_stmt (&gsi, bb);
 	      something_changed = true;
-
-	      /* If stmt was the last stmt in the block, we want to
-		 move gsi to the stmt that became the last stmt, but
-		 gsi_prev would crash.  */
-	      if (gsi_end_p (gsi))
-		gsi = gsi_last_bb (bb);
-	      else
-		gsi_prev (&gsi);
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
@@ -1159,10 +1154,7 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_prev (&gsi);
 	    }
-	  else
-	    gsi_prev (&gsi);
 	}
     }
 

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-06  6:43       ` Alexandre Oliva
@ 2009-10-06 10:30         ` Richard Guenther
  2009-10-07  8:35           ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-06 10:30 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Tue, Oct 6, 2009 at 7:29 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Oct  3, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>> Hm, ok.  One reason why I liked the idea of using SSA_NAMEs much is
>> that it would make it very easy to get rid of old no longer used debug
>> temps.  How do you address this?
>
> I don't.  I'm not sure we're going to have very many of these.  Say, a
> debug temp bind should only become dead if we were to remove the basic
> block containing the only reference to the debug temp.  In general we do
> this only when the block is unreachable.  But if the block is
> unreachable, we'd remove it before the debug temp was introduced, and
> the absence of references to the DEF would prevent the creation of the
> debug temp in the first place.
>
> Of course we could construct cases in which the order of creation of the
> debug temp and the removal of the blocks would cause it to remain
> around.  I have an intuition that this won't happen very often, though.
> I guess I should try to substantiate this intuition ;-)

Well, your intuition at least sounds appealing...

> Anyhow, if we find it not to be true, it shouldn't be too hard to get
> debug temps into SSA operands, especially if we're to add vops to debug
> bind stmts as well.

Gah.  Over my dead body!

:/

(seriously I'd rather cripple debug stmts for 4.5 to fix wrong-debug
issues because of the lack of virtual operands that to try to make
virtual operands for debug stmts working during stage3)

>> Any reason why in
>
>> +      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
>> +       DECL_UID (t) = --next_debug_decl_uid;
>
>> you count backward?  You always print the negative value later...
>
> Mainly to make accidental overlaps with DECL_UIDs less likely.  I
> figured negative values would cause crashes or errors if we used
> DECL_UIDs inappropriately.

Fair enough.  Mind adding a comment here?  Mind adding
a DEBUG_DECL_UID macro that encapsulates the negation?

>> for both gsi_replace and gsi_remove you shouldn't really insert
>> debug-temps.  The replaced/removed stmt may be inserted elsewhere
>> again
>
> But the bind point is that where the stmt was before, and the moved DEF
> might very well be referenced at a point between the bind point and the
> reinsertion point.

Please get some numbers here - I think this will for example
artificially add debug stmts on basic block removal.

>> @@ -206,7 +206,7 @@ release_ssa_name (tree var)
>>        use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
>
>>        if (MAY_HAVE_DEBUG_STMTS)
>> -       propagate_var_def_into_debug_stmts (var, NULL, NULL);
>> +       insert_debug_temp_for_var_def (NULL, var);
>
>> and here I thought that doesn't work because the stmt is already
>> unlinked?
>
> It works, but it will drop debug expressions that refer to the removed
> DEF, instead of replacing them with a debug temp.

Ah, ok.

Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-06 10:30         ` Richard Guenther
@ 2009-10-07  8:35           ` Alexandre Oliva
  2009-10-07 10:24             ` Richard Guenther
  2009-10-09  7:48             ` Alexandre Oliva
  0 siblings, 2 replies; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-07  8:35 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Oct  6, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

>> Anyhow, if we find it not to be true, it shouldn't be too hard to get
>> debug temps into SSA operands, especially if we're to add vops to debug
>> bind stmts as well.

> Gah.  Over my dead body!

:-)

> Fair enough.  Mind adding a comment here?  Mind adding
> a DEBUG_DECL_UID macro that encapsulates the negation?

Will do.

>> But the bind point is that where the stmt was before, and the moved DEF
>> might very well be referenced at a point between the bind point and the
>> reinsertion point.

> Please get some numbers here - I think this will for example
> artificially add debug stmts on basic block removal.

We remove basic blocks “backwards” too, from last to first stmt, and
dominated before dominator.  So, since the newly-added code only adds a
debug stmt if it finds the removed SSA DEF is USEd in a debug stmt, it
would only add a deug stmt if we were to remove a dominator without
removing its dominated, i.e., if we were to remove an SSA DEF without
removing its corresponding USEs.  We don't do that, do we?

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-07  8:35           ` Alexandre Oliva
@ 2009-10-07 10:24             ` Richard Guenther
  2009-10-08 19:48               ` Alexandre Oliva
  2009-10-09  7:48             ` Alexandre Oliva
  1 sibling, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-07 10:24 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Wed, Oct 7, 2009 at 9:48 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Oct  6, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>>> Anyhow, if we find it not to be true, it shouldn't be too hard to get
>>> debug temps into SSA operands, especially if we're to add vops to debug
>>> bind stmts as well.
>
>> Gah.  Over my dead body!
>
> :-)
>
>> Fair enough.  Mind adding a comment here?  Mind adding
>> a DEBUG_DECL_UID macro that encapsulates the negation?
>
> Will do.
>
>>> But the bind point is that where the stmt was before, and the moved DEF
>>> might very well be referenced at a point between the bind point and the
>>> reinsertion point.
>
>> Please get some numbers here - I think this will for example
>> artificially add debug stmts on basic block removal.
>
> We remove basic blocks “backwards” too, from last to first stmt, and
> dominated before dominator.  So, since the newly-added code only adds a
> debug stmt if it finds the removed SSA DEF is USEd in a debug stmt, it
> would only add a deug stmt if we were to remove a dominator without
> removing its dominated, i.e., if we were to remove an SSA DEF without
> removing its corresponding USEs.  We don't do that, do we?

I'm not sure.  While we don't remove definitions that are still
used for regular SSA name uses we still can have debug-uses
in another basic-block, no?  Like

 if (0)
   {
     a_1 = ...;
   }
 else
   {
      ...
    }
 # DEBUG i => a_1

here when eliminating the unreachable block we would create
a debug-temp for a_1 just to remove it immediately again
(if that works at all and we're not confused here).

Richard.

> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist      Red Hat Brazil Compiler Engineer
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-07 10:24             ` Richard Guenther
@ 2009-10-08 19:48               ` Alexandre Oliva
  0 siblings, 0 replies; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-08 19:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

On Oct  7, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> On Wed, Oct 7, 2009 at 9:48 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
>> We remove basic blocks “backwards” too, from last to first stmt, and
>> dominated before dominator.  So, since the newly-added code only adds a
>> debug stmt if it finds the removed SSA DEF is USEd in a debug stmt, it
>> would only add a deug stmt if we were to remove a dominator without
>> removing its dominated, i.e., if we were to remove an SSA DEF without
>> removing its corresponding USEs.  We don't do that, do we?

> I'm not sure.  While we don't remove definitions that are still
> used for regular SSA name uses we still can have debug-uses
> in another basic-block, no?

Yeah, but since it's SSA, USEs are always dominated by DEFs.

>  if (0)
>    {
>      a_1 = ...;
>    }
>  else
>    {
>       ...
>     }
>  # DEBUG i => a_1

> here when eliminating the unreachable block we would create
> a debug-temp for a_1 just to remove it immediately again

This would be malformed SSA.  We'd instead have something like:

if (0)
  a_1 = ...;
else
  ...
a_2 = PHI <a_1(if-true),a_0(if-false)>
# DEBUG i => a_2

a_1 could only be referenced in blocks dominated by (if-true), so we'd
end up removing them all, dominators last.

Now, removing the (if-true) BB would cause a_2 to simplify to a_0.  I
haven't double-checked that whatever it is that propagates a_2 = a_0
into uses of a_2 takes care of debug stmts as well, but I don't see why
it wouldn't and, if it doesn't, that would be another bug.

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-07  8:35           ` Alexandre Oliva
  2009-10-07 10:24             ` Richard Guenther
@ 2009-10-09  7:48             ` Alexandre Oliva
  2009-10-09 11:29               ` Richard Guenther
  1 sibling, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-09  7:48 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1622 bytes --]

On Oct  7, 2009, Alexandre Oliva <aoliva@redhat.com> wrote:

> On Oct  6, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>>> Anyhow, if we find it not to be true, it shouldn't be too hard to get
>>> debug temps into SSA operands, especially if we're to add vops to debug
>>> bind stmts as well.

>> Gah.  Over my dead body!

> :-)

>> Fair enough.  Mind adding a comment here?  Mind adding
>> a DEBUG_DECL_UID macro that encapsulates the negation?

> Will do.

The patch below introduces DEBUG_TEMP_UID, it removes debug temp bind
stmts without values during SSA updates (removing them upon reset would
invalidate iterators), and it avoids the creation of debug temp bind
stmts when the expressions are safe to move, i.e., if they refer to SSA
names or to constants.

So, given:

  a_1 = b_2;
  c_3 = -d_4;
  e_5 = f_6 + g_7;
  # DEBUG h => a_1
  # DEBUG i => c_3
  # DEBUG j => e_5
  # DEBUG k => a_1 + c_3
  # DEBUG l => -e_5

if a_1, c_3 and e_5 are removed, we'll emit:

  ;; (nothing for a_1 = b_2)
  # DEBUG D#1 => -d_4
  # DEBUG D#2 => f_6 + g_7
  # DEBUG h => b_2
  # DEBUG i => -d_4
  # DEBUG j => f_6 + g_7
  # DEBUG k => b_2 + D#1
  # DEBUG l => -D#2

i.e., if the SSA name whose DEF is being removed is by itself in a debug
bind stmt's value, we'll use the expression formerly assigned to the
DEF.  If it's not by itself, we'll only use the expression if it's an
SSA name or constant.

I also added the testcases from the bug reports, and I realized cselib
did not distinguish between different DEBUG_EXPR_DECLs, so I fixed that.

Here's the patch I'm testing now.  Ok to install if it regstraps?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 33493 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.h (DEBUG_TEMP_UID): New.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace, gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_bittest, move_computations_stmt): Drop
	propagation into debug stmts.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.
	* tree-ssa-dce.c (eliminate_unnecessary_stmts): Don't discard
	just-inserted debug stmts.

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* gcc.dg/guality/pr41447-1.c: New.
	* gcc.dg/debug/pr41264-1.c: New.
	* gcc.dg/debug/pr41343-1.c: New.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree.def	2009-10-08 16:58:29.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/rtl.def	2009-10-08 16:58:29.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/gengtype.c	2009-10-08 16:58:29.000000000 -0300
@@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa.c	2009-10-09 01:29:17.000000000 -0300
@@ -295,70 +295,44 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
   gimple stmt;
   use_operand_p use_p;
   tree value = NULL;
+  tree vexpr = NULL;
   bool no_value = false;
+  bool vsafe = false;
+  gimple def_stmt = NULL;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
   FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
-
       if (!is_gimple_debug (stmt))
 	continue;
 
-      if (tobb)
-	{
-	  bb = gimple_bb (stmt);
-
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
-
-	      if (gsi_end_p (si))
-		continue;
-
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
-
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
-
       /* Here we compute (lazily) the value assigned to VAR, but we
 	 remember if we tried before and failed, so that we don't try
 	 again.  */
       if (!value && !no_value)
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  if (gsi)
+	    def_stmt = gsi_stmt (*gsi);
+	  else
+	    def_stmt = SSA_NAME_DEF_STMT (var);
 
+	  /* If we didn't get an insertion point, and the stmt has
+	     already been removed, we won't be able to insert the
+	     debug bind stmt, so we'll have to drop debug
+	     information.  */
 	  if (is_gimple_assign (def_stmt))
 	    {
 	      if (!dom_info_available_p (CDI_DOMINATORS))
@@ -395,7 +369,9 @@ propagate_var_def_into_debug_stmts (tree
 		     wrong order, so we don't even check for dead SSA
 		     NAMEs.  SSA verification shall catch any
 		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
+		  if ((!gsi && !gimple_bb (def_stmt))
+		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+					  &wi))
 		    no_value = true;
 		}
 
@@ -405,42 +381,111 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else if (is_gimple_min_invariant (value)
+		   || is_gimple_reg (value))
+	    {
+	      vsafe = true;
+	      vexpr = value;
+	    }
+	  else
+	    {
+	      switch (get_gimple_rhs_class (TREE_CODE (value)))
+		{
+		case GIMPLE_BINARY_RHS:
+		  vsafe
+		    = ((is_gimple_min_invariant (TREE_OPERAND (value, 0))
+			|| is_gimple_reg (TREE_OPERAND (value, 0)))
+		       && (is_gimple_min_invariant (TREE_OPERAND (value, 1))
+			   || is_gimple_reg (TREE_OPERAND (value, 1))));
+		  break;
+
+		case GIMPLE_UNARY_RHS:
+		  vsafe
+		    = (is_gimple_min_invariant (TREE_OPERAND (value, 0))
+		       || is_gimple_reg (TREE_OPERAND (value, 0)));
+		  break;
+
+		case GIMPLE_SINGLE_RHS:
+		  vsafe
+		    = (is_gimple_min_invariant (value)
+		       || is_gimple_reg (value));
+		  if (vsafe)
+		    vexpr = value;
+		  break;
+
+		default:
+		  gcc_unreachable ();
+		}
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
+      /* If VAR is the entire value expression, and the definition of
+	 VAR is safe to move about, use it.  */
+      else if (vsafe && gimple_debug_bind_get_value (stmt) == var)
+	gimple_debug_bind_set_value (stmt, unshare_expr (value));
+      /* Otherwise, create a debug temp expression and use it.  */
       else
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  {
+	    if (!vexpr)
+	      {
+		gimple def_temp;
+
+		vexpr = make_node (DEBUG_EXPR_DECL);
+		def_temp = gimple_build_debug_bind (vexpr,
+						    unshare_expr (value),
+						    def_stmt);
+
+		DECL_ARTIFICIAL (vexpr) = 1;
+		TREE_TYPE (vexpr) = TREE_TYPE (value);
+		if (DECL_P (value))
+		  DECL_MODE (vexpr) = DECL_MODE (value);
+		else
+		  DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
+
+		if (gsi)
+		  gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+		else
+		  {
+		    gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+		    gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+		  }
+	      }
+
+	    SET_USE (use_p, unshare_expr (vexpr));
+	  }
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree.h	2009-10-08 16:58:29.000000000 -0300
@@ -2455,6 +2455,10 @@ struct function;
 /* Every ..._DECL node gets a unique number.  */
 #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
 
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+   uses.  */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
 /* These two fields describe where in the source code the declaration
    was.  If the declaration appears in several places (as for a C
    function that is declared first and then defined later), this
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree.c	2009-10-08 16:58:29.000000000 -0300
@@ -152,6 +152,9 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/cfgexpand.c	2009-10-08 16:58:29.000000000 -0300
@@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/var-tracking.c	2009-10-08 16:58:29.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/cselib.c	2009-10-09 04:29:50.000000000 -0300
@@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     {
     case CONST_DOUBLE:
     case CONST_FIXED:
+    case DEBUG_EXPR:
       return 0;
 
     case LABEL_REF:
@@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
 
       return e->value;
 
+    case DEBUG_EXPR:
+      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      return hash ? hash : (unsigned int) DEBUG_EXPR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
@@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-10-08 16:58:29.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/emit-rtl.c	2009-10-08 16:58:29.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/rtl.c	2009-10-08 16:58:29.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/print-rtl.c	2009-10-08 16:58:29.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/sched-vis.c	2009-10-08 16:58:29.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-dump.c	2009-10-08 16:58:29.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-10-08 16:58:29.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/gimple-iterator.c	2009-10-08 16:58:29.000000000 -0300
@@ -368,6 +368,8 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  insert_debug_temps_for_defs (gsi);
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +472,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-10-08 16:58:29.000000000 -0300
@@ -879,7 +879,6 @@ rewrite_bittest (gimple_stmt_iterator *b
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
       gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
       gsi_replace (bsi, stmt2, true);
 
       return stmt1;
@@ -1060,7 +1059,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-10-08 16:58:29.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-10-08 16:58:29.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-10-08 16:58:29.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssanames.c	2009-10-08 16:58:29.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-flow.h	2009-10-08 16:58:29.000000000 -0300
@@ -637,10 +637,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-10-08 16:45:22.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-10-08 16:58:29.000000000 -0300
@@ -1071,7 +1071,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1111,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
 	{
 	  stmt = gsi_stmt (gsi);
 
+	  psi = gsi;
+	  gsi_prev (&psi);
+
 	  stats.total++;
 
 	  /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1125,6 @@ eliminate_unnecessary_stmts (void)
 	    {
 	      remove_dead_stmt (&gsi, bb);
 	      something_changed = true;
-
-	      /* If stmt was the last stmt in the block, we want to
-		 move gsi to the stmt that became the last stmt, but
-		 gsi_prev would crash.  */
-	      if (gsi_end_p (gsi))
-		gsi = gsi_last_bb (bb);
-	      else
-		gsi_prev (&gsi);
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
@@ -1159,10 +1154,7 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_prev (&gsi);
 	    }
-	  else
-	    gsi_prev (&gsi);
 	}
     }
 
Index: gcc/tree-into-ssa.c
===================================================================
--- gcc/tree-into-ssa.c.orig	2009-10-08 17:59:27.000000000 -0300
+++ gcc/tree-into-ssa.c	2009-10-09 04:29:53.000000000 -0300
@@ -2079,11 +2079,29 @@ rewrite_update_enter_block (struct dom_w
 
   /* Step 2.  Rewrite every variable used in each statement in the block.  */
   if (TEST_BIT (interesting_blocks, bb->index))
-   {
-     gcc_assert (bitmap_bit_p (blocks_to_update, bb->index));
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
-        rewrite_update_stmt (gsi_stmt (gsi));
-   }
+    {
+      gcc_assert (bitmap_bit_p (blocks_to_update, bb->index));
+      gsi = gsi_start_bb (bb);
+      while (!gsi_end_p (gsi))
+	{
+	  gimple stmt = gsi_stmt (gsi);
+
+	  if (gimple_debug_bind_p (stmt)
+	      && !gimple_debug_bind_has_value_p (stmt)
+	      && TREE_CODE (gimple_debug_bind_get_var (stmt)) == DEBUG_EXPR_DECL)
+	    {
+	      gimple_stmt_iterator gsic = gsi;
+
+	      gsi_next (&gsi);
+	      gsi_remove (&gsic, true);
+	    }
+	  else
+	    {
+	      rewrite_update_stmt (stmt);
+	      gsi_next (&gsi);
+	    }
+	}
+    }
 
   /* Step 3.  Update PHI nodes.  */
   rewrite_update_phi_arguments (bb);
Index: gcc/testsuite/gcc.dg/guality/pr41447-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/guality/pr41447-1.c	2009-10-08 21:27:20.000000000 -0300
@@ -0,0 +1,25 @@
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-g -O2" } */
+
+#include "guality.h"
+
+int a;
+
+int foo()
+{
+  int tmp = a;
+  int tmp2 = a;
+  int tmp3;
+  int res;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  a = 0;
+  tmp3 = tmp2;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  GUALCHKVAL (tmp3);
+  res = tmp - tmp2 + 1;
+  return res;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41264-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41264-1.c	2009-10-09 01:26:51.000000000 -0300
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+typedef unsigned int hashval_t;
+static hashval_t __attribute__((always_inline))
+iterative_hash_host_wide_int (long val, hashval_t val2)
+{
+  hashval_t a = (hashval_t) val;
+  int zero = 0;
+  hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+
+  a -= b; a -= val2; a ^= (val2>>13);
+  b -= val2; b -= a; b ^= (a<< 8);
+  val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
+  a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
+  b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
+  a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
+  b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
+  return val2;
+}
+
+hashval_t
+bla (int nunits, int mode)
+{
+  hashval_t hashcode = 0;
+
+
+  hashcode = iterative_hash_host_wide_int (14, hashcode);
+  hashcode = iterative_hash_host_wide_int (nunits, hashcode);
+  hashcode = iterative_hash_host_wide_int (mode, hashcode);
+  if (nunits)
+    return 0;
+  else
+    return hashcode;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41343-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41343-1.c	2009-10-09 04:13:40.000000000 -0300
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#define X(new,old) int i ## new = i ## old + i ## old;
+#define Y(pfx) X(pfx ## 1, pfx) \
+  X(pfx ## 2, pfx ## 1) \
+  X(pfx ## 3, pfx ## 2) \
+  X(pfx ## 4, pfx ## 3) \
+  X(pfx ## 5, pfx ## 4) \
+  X(pfx ## 6, pfx ## 5) \
+  X(pfx ## 7, pfx ## 6) \
+  X(pfx ## 8, pfx ## 7) \
+  X(pfx ## 9, pfx ## 8)
+
+void foo (int i1)
+{
+  Y(1)
+  Y(11)
+  Y(111)
+  asm ("" : : "X" (i1));
+}

[-- Attachment #3: Type: text/plain, Size: 258 bytes --]



-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-09  7:48             ` Alexandre Oliva
@ 2009-10-09 11:29               ` Richard Guenther
  2009-10-11 13:05                 ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-09 11:29 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Fri, Oct 9, 2009 at 9:36 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Oct  7, 2009, Alexandre Oliva <aoliva@redhat.com> wrote:
>
>> On Oct  6, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>>>> Anyhow, if we find it not to be true, it shouldn't be too hard to get
>>>> debug temps into SSA operands, especially if we're to add vops to debug
>>>> bind stmts as well.
>
>>> Gah.  Over my dead body!
>
>> :-)
>
>>> Fair enough.  Mind adding a comment here?  Mind adding
>>> a DEBUG_DECL_UID macro that encapsulates the negation?
>
>> Will do.
>
> The patch below introduces DEBUG_TEMP_UID, it removes debug temp bind
> stmts without values during SSA updates (removing them upon reset would
> invalidate iterators),

Hm.  Please instead replace them with GIMPLE_NOPs on reset, it should
be possible to do that in-place.  If there isn't a nice suitable way of doing
it already please add a helper function in gimple.c that does this.
gimple_make_nop whould be a suitable name for this.

> and it avoids the creation of debug temp bind
> stmts when the expressions are safe to move, i.e., if they refer to SSA
> names or to constants.
>
> So, given:
>
>  a_1 = b_2;
>  c_3 = -d_4;
>  e_5 = f_6 + g_7;
>  # DEBUG h => a_1
>  # DEBUG i => c_3
>  # DEBUG j => e_5
>  # DEBUG k => a_1 + c_3
>  # DEBUG l => -e_5
>
> if a_1, c_3 and e_5 are removed, we'll emit:
>
>  ;; (nothing for a_1 = b_2)
>  # DEBUG D#1 => -d_4
>  # DEBUG D#2 => f_6 + g_7
>  # DEBUG h => b_2
>  # DEBUG i => -d_4
>  # DEBUG j => f_6 + g_7
>  # DEBUG k => b_2 + D#1
>  # DEBUG l => -D#2
>
> i.e., if the SSA name whose DEF is being removed is by itself in a debug
> bind stmt's value, we'll use the expression formerly assigned to the
> DEF.  If it's not by itself, we'll only use the expression if it's an
> SSA name or constant.

I'd like to see

# DEBUG j => D#2

here.  Thus restrict the "if the SSA name whose DEF is being removed
is by itself
in a debug bind stmt's value, we'll use the expression formerly assigned to the
DEF." to the case where there is a single use.

              if (!no_value)
                value = gimple_assign_rhs_to_tree (def_stmt);
            }
          if (!value)
            no_value = true;
+         else if (is_gimple_min_invariant (value)
+                  || is_gimple_reg (value))
+           {
+             vsafe = true;
+             vexpr = value;
+           }
+         else
+           {
+             switch (get_gimple_rhs_class (TREE_CODE (value)))
+               {
+               case GIMPLE_BINARY_RHS:
+                 vsafe
+                   = ((is_gimple_min_invariant (TREE_OPERAND (value, 0))
...
+                 if (vsafe)
+                   vexpr = value;
+                 break;
+
+               default:
+                 gcc_unreachable ();
+               }
+           }

vsafe computation can be simplified.

  vsafe = (!gimple_assign_single_p (def_stmt)
             || is_gimple_min_invariant (value)
            || is_gimple_reg (value));

For the single-use issue add

  if (!gimple_assign_single_p (def_stmt)
      && !has_single_use (var))
    vsafe = false;

well - of course with a proper has_single_use that also counts debug stmts.

> I also added the testcases from the bug reports, and I realized cselib
> did not distinguish between different DEBUG_EXPR_DECLs, so I fixed that.
>
> Here's the patch I'm testing now.  Ok to install if it regstraps?

Ok with the above changes.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-09 11:29               ` Richard Guenther
@ 2009-10-11 13:05                 ` Alexandre Oliva
  2009-10-11 14:26                   ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-11 13:05 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1279 bytes --]

On Oct  9, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> Hm.  Please instead replace them with GIMPLE_NOPs on reset, it should
> be possible to do that in-place.

That brought about some complications (releasing operands), so we
settled on IRC for not marking such stmts as necessary in DCE, which is
where they'd be removed anyway.

> Thus restrict the "if the SSA name whose DEF is being removed is by
> itself in a debug bind stmt's value, we'll use the expression formerly
> assigned to the DEF." to the case where there is a single use.

Done.

>> I also added the testcases from the bug reports, and I realized cselib
>> did not distinguish between different DEBUG_EXPR_DECLs, so I fixed that.
>> 
>> Here's the patch I'm testing now.  Ok to install if it regstraps?

> Ok with the above changes.

It wasn't :-( Inserting debug stmts on gsi_replace caused lowering
problems in complex lowering: the lowered expressions would remain in
debug stmts, causing compile errors in expand.  Fixed avoiding the
introduction of debug stmts in gsi_replace, checking that the the
replacement defines the same LHS.  rewrite_bittest triggered an error in
this assertion, so I fixed it.

Here's the patch, regstrapped on x86_64-linux-gnu.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 36430 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	Scan early for use count and kind in debug stmts.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.h (DEBUG_TEMP_UID): New.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
	(cselib_hash_rtx): Likewise.
	(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace): Check for same lhs.
	(gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
	(move_computations_stmt): Drop explicit propagation into debug stmts.
	(rewrite_bittest): Likewise.  Use gsi_remove for propagation.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
	debug temps without values.
	(eliminate_unnecessary_stmts): Don't discard just-inserted
	debug stmts.

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* gcc.dg/guality/pr41447-1.c: New.
	* gcc.dg/debug/pr41264-1.c: New.
	* gcc.dg/debug/pr41343-1.c: New.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/tree.def	2009-10-09 17:33:21.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/rtl.def	2009-10-09 17:33:21.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/gengtype.c	2009-10-09 17:33:21.000000000 -0300
@@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-10-09 17:32:31.000000000 -0300
+++ gcc/tree-ssa.c	2009-10-09 19:12:48.000000000 -0300
@@ -295,70 +295,66 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
-  gimple stmt;
   use_operand_p use_p;
-  tree value = NULL;
+  gimple stmt;
+  gimple def_stmt = NULL;
+  bool found = false;
+  bool usetemp = false;
   bool no_value = false;
+  tree value = NULL;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+  /* First of all, check whether there are debug stmts that reference
+     this variable and, if there are, decide whether we can */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
+      stmt = USE_STMT (use_p);
 
-      if (!is_gimple_debug (stmt))
+      if (!gimple_debug_bind_p (stmt))
 	continue;
 
-      if (tobb)
+      if (found || gimple_debug_bind_get_value (stmt) != var)
 	{
-	  bb = gimple_bb (stmt);
-
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
+	  found = true;
+	  usetemp = true;
+	  break;
+	}
 
-	      if (gsi_end_p (si))
-		continue;
+      found = true;
+    }
 
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
+  if (!found)
+    return;
 
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
+  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+    {
+      if (!gimple_debug_bind_p (stmt))
+	continue;
 
       /* Here we compute (lazily) the value assigned to VAR, but we
 	 remember if we tried before and failed, so that we don't try
 	 again.  */
       if (!value && !no_value)
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  if (gsi)
+	    def_stmt = gsi_stmt (*gsi);
+	  else
+	    def_stmt = SSA_NAME_DEF_STMT (var);
 
+	  /* If we didn't get an insertion point, and the stmt has
+	     already been removed, we won't be able to insert the
+	     debug bind stmt, so we'll have to drop debug
+	     information.  */
 	  if (is_gimple_assign (def_stmt))
 	    {
 	      if (!dom_info_available_p (CDI_DOMINATORS))
@@ -395,7 +391,9 @@ propagate_var_def_into_debug_stmts (tree
 		     wrong order, so we don't even check for dead SSA
 		     NAMEs.  SSA verification shall catch any
 		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
+		  if ((!gsi && !gimple_bb (def_stmt))
+		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+					  &wi))
 		    no_value = true;
 		}
 
@@ -405,42 +403,126 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else
+	    {
+	      tree vexpr = NULL;
+
+	      if (!usetemp)
+		{
+		  bool vsafe;
+
+		  /* Check whether VALUE is safe to move in the code
+		     stream.  If it is, we might be able to replace
+		     occurrences of VAR with it.  */
+		  switch (get_gimple_rhs_class (TREE_CODE (value)))
+		    {
+		    case GIMPLE_BINARY_RHS:
+		      vsafe
+			= ((is_gimple_min_invariant (TREE_OPERAND (value, 0))
+			    || is_gimple_reg (TREE_OPERAND (value, 0)))
+			   && (is_gimple_min_invariant (TREE_OPERAND (value, 1))
+			       || is_gimple_reg (TREE_OPERAND (value, 1))));
+		      break;
+
+		    case GIMPLE_UNARY_RHS:
+		      vsafe
+			= (is_gimple_min_invariant (TREE_OPERAND (value, 0))
+			   || is_gimple_reg (TREE_OPERAND (value, 0)));
+		      break;
+
+		    case GIMPLE_SINGLE_RHS:
+		      vsafe
+			= (is_gimple_min_invariant (value)
+			   || is_gimple_reg (value));
+		      if (vsafe)
+			vexpr = value;
+		      break;
+
+		    default:
+		      gcc_unreachable ();
+		    }
+
+		  /* If there's more than one use of VAR in debug stmts
+		     and VALUE is not a SINGLE_RHS, we want to generate a
+		     debug temp to avoid redundancy.
+
+		     Likewise, if there's any such use in a debug stmt in
+		     which VAR is not the whole expression, we want to
+		     generate a debug temp to keep expressions in a gimple
+		     RHS-like form.  */
+		  if (vsafe && !vexpr)
+		    vexpr = unshare_expr (value);
+		}
+
+	      if (!vexpr)
+		{
+		  gimple def_temp;
+
+		  vexpr = make_node (DEBUG_EXPR_DECL);
+		  def_temp = gimple_build_debug_bind (vexpr,
+						      unshare_expr (value),
+						      def_stmt);
+
+		  DECL_ARTIFICIAL (vexpr) = 1;
+		  TREE_TYPE (vexpr) = TREE_TYPE (value);
+		  if (DECL_P (value))
+		    DECL_MODE (vexpr) = DECL_MODE (value);
+		  else
+		    DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
+
+		  if (gsi)
+		    gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+		  else
+		    {
+		      gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+		      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+		    }
+		}
+
+	      value = vexpr;
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
       else
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  /* unshare_expr is not needed here.  vexpr 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.  */
+	  SET_USE (use_p, value);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2009-10-09 17:32:33.000000000 -0300
+++ gcc/tree.h	2009-10-09 17:33:21.000000000 -0300
@@ -2455,6 +2455,10 @@ struct function;
 /* Every ..._DECL node gets a unique number.  */
 #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
 
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+   uses.  */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
 /* These two fields describe where in the source code the declaration
    was.  If the declaration appears in several places (as for a C
    function that is declared first and then defined later), this
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-09 17:32:33.000000000 -0300
+++ gcc/tree.c	2009-10-09 17:33:21.000000000 -0300
@@ -152,6 +152,9 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/cfgexpand.c	2009-10-09 17:33:21.000000000 -0300
@@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/var-tracking.c	2009-10-09 17:33:21.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/cselib.c	2009-10-09 17:33:21.000000000 -0300
@@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     {
     case CONST_DOUBLE:
     case CONST_FIXED:
+    case DEBUG_EXPR:
       return 0;
 
     case LABEL_REF:
@@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
 
       return e->value;
 
+    case DEBUG_EXPR:
+      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      return hash ? hash : (unsigned int) DEBUG_EXPR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
@@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-10-09 17:33:21.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-10-09 17:32:35.000000000 -0300
+++ gcc/emit-rtl.c	2009-10-09 17:33:21.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-10-09 17:32:33.000000000 -0300
+++ gcc/rtl.c	2009-10-09 17:33:21.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-10-09 17:32:35.000000000 -0300
+++ gcc/print-rtl.c	2009-10-09 17:33:21.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/sched-vis.c	2009-10-09 17:33:21.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/tree-dump.c	2009-10-09 17:33:21.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-10-09 17:33:21.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/gimple-iterator.c	2009-10-09 17:33:21.000000000 -0300
@@ -358,7 +358,8 @@ gsi_split_seq_before (gimple_stmt_iterat
 
 /* Replace the statement pointed-to by GSI to STMT.  If UPDATE_EH_INFO
    is true, the exception handling information of the original
-   statement is moved to the new statement.  */
+   statement is moved to the new statement.  Assignments must only be
+   replaced with assignments to the same LHS.  */
 
 void
 gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
@@ -368,6 +369,16 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  {
+    tree lhs;
+
+    gcc_assert (!(lhs = gimple_get_lhs (orig_stmt))
+		|| lhs == gimple_get_lhs (stmt));
+
+    /* If the assertion above fails, we may want to conditionally call
+       insert_debug_temps_for_defs (gsi).  */
+  }
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +481,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-10-09 17:32:31.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-10-10 01:10:31.000000000 -0300
@@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator
   gimple stmt, stmt1, stmt2;
   tree var, name, lhs, type;
   tree real_one;
+  gimple_stmt_iterator gsi;
 
   stmt = gsi_stmt (*bsi);
   lhs = gimple_assign_lhs (stmt);
@@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator
   /* Replace division stmt with reciprocal and multiply stmts.
      The multiply stmt is not invariant, so update iterator
      and avoid rescanning.  */
-  gsi_replace (bsi, stmt1, true);
-  gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
+  gsi = *bsi;
+  gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+  gsi_replace (&gsi, stmt2, true);
 
   /* Continue processing with invariant reciprocal statement.  */
   return stmt1;
@@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *b
   if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
       && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
     {
+      gimple_stmt_iterator rsi;
+
       /* 1 << B */
       var = create_tmp_var (TREE_TYPE (a), "shifttmp");
       add_referenced_var (var);
@@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *b
       SET_USE (use, name);
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
-      gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
-      gsi_replace (bsi, stmt2, true);
+      /* Don't use gsi_replace here, none of the new assignments sets
+	 the variable originally set in stmt.  Move bsi to stmt1, and
+	 then remove the original stmt, so that we get a chance to
+	 retain debug info for it.  */
+      rsi = *bsi;
+      gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+      gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
+      gsi_remove (&rsi, true);
 
       return stmt1;
     }
@@ -1060,7 +1069,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-10-09 17:32:31.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-10-09 17:33:21.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-10-09 17:33:21.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-10-09 17:32:34.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-10-09 17:33:21.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-10-09 17:32:31.000000000 -0300
+++ gcc/tree-ssanames.c	2009-10-09 17:33:21.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-10-09 17:32:35.000000000 -0300
+++ gcc/tree-flow.h	2009-10-09 17:33:21.000000000 -0300
@@ -637,10 +637,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-10-09 17:32:32.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-10-09 17:55:21.000000000 -0300
@@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple
       break;
 
     case GIMPLE_DEBUG:
-      mark_stmt_necessary (stmt, false);
+      /* Debug temps without a value are not useful.  ??? If we could
+	 easily locate the debug temp bind stmt for a use thereof,
+	 would could refrain from marking all debug temps here, and
+	 mark them only if they're used.  */
+      if (gimple_debug_bind_has_value_p (stmt)
+	  || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
+	mark_stmt_necessary (stmt, false);
       return;
 
     case GIMPLE_GOTO:
@@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
 	{
 	  stmt = gsi_stmt (gsi);
 
+	  psi = gsi;
+	  gsi_prev (&psi);
+
 	  stats.total++;
 
 	  /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1131,6 @@ eliminate_unnecessary_stmts (void)
 	    {
 	      remove_dead_stmt (&gsi, bb);
 	      something_changed = true;
-
-	      /* If stmt was the last stmt in the block, we want to
-		 move gsi to the stmt that became the last stmt, but
-		 gsi_prev would crash.  */
-	      if (gsi_end_p (gsi))
-		gsi = gsi_last_bb (bb);
-	      else
-		gsi_prev (&gsi);
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
@@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_prev (&gsi);
 	    }
-	  else
-	    gsi_prev (&gsi);
 	}
     }
 
Index: gcc/testsuite/gcc.dg/guality/pr41447-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/guality/pr41447-1.c	2009-10-09 17:33:21.000000000 -0300
@@ -0,0 +1,25 @@
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-g -O2" } */
+
+#include "guality.h"
+
+int a;
+
+int foo()
+{
+  int tmp = a;
+  int tmp2 = a;
+  int tmp3;
+  int res;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  a = 0;
+  tmp3 = tmp2;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  GUALCHKVAL (tmp3);
+  res = tmp - tmp2 + 1;
+  return res;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41264-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41264-1.c	2009-10-09 17:33:21.000000000 -0300
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+typedef unsigned int hashval_t;
+static hashval_t __attribute__((always_inline))
+iterative_hash_host_wide_int (long val, hashval_t val2)
+{
+  hashval_t a = (hashval_t) val;
+  int zero = 0;
+  hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+
+  a -= b; a -= val2; a ^= (val2>>13);
+  b -= val2; b -= a; b ^= (a<< 8);
+  val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
+  a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
+  b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
+  a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
+  b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
+  return val2;
+}
+
+hashval_t
+bla (int nunits, int mode)
+{
+  hashval_t hashcode = 0;
+
+
+  hashcode = iterative_hash_host_wide_int (14, hashcode);
+  hashcode = iterative_hash_host_wide_int (nunits, hashcode);
+  hashcode = iterative_hash_host_wide_int (mode, hashcode);
+  if (nunits)
+    return 0;
+  else
+    return hashcode;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41343-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41343-1.c	2009-10-09 17:33:21.000000000 -0300
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#define X(new,old) int i ## new = i ## old + i ## old;
+#define Y(pfx) X(pfx ## 1, pfx) \
+  X(pfx ## 2, pfx ## 1) \
+  X(pfx ## 3, pfx ## 2) \
+  X(pfx ## 4, pfx ## 3) \
+  X(pfx ## 5, pfx ## 4) \
+  X(pfx ## 6, pfx ## 5) \
+  X(pfx ## 7, pfx ## 6) \
+  X(pfx ## 8, pfx ## 7) \
+  X(pfx ## 9, pfx ## 8)
+
+void foo (int i1)
+{
+  Y(1)
+  Y(11)
+  Y(111)
+  asm ("" : : "X" (i1));
+}

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-11 13:05                 ` Alexandre Oliva
@ 2009-10-11 14:26                   ` Richard Guenther
  2009-10-12  6:36                     ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-11 14:26 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Sun, Oct 11, 2009 at 3:03 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Oct  9, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>> Hm.  Please instead replace them with GIMPLE_NOPs on reset, it should
>> be possible to do that in-place.
>
> That brought about some complications (releasing operands), so we
> settled on IRC for not marking such stmts as necessary in DCE, which is
> where they'd be removed anyway.
>
>> Thus restrict the "if the SSA name whose DEF is being removed is by
>> itself in a debug bind stmt's value, we'll use the expression formerly
>> assigned to the DEF." to the case where there is a single use.
>
> Done.

+  /* First of all, check whether there are debug stmts that reference
+     this variable and, if there are, decide whether we can */

missing '. '

+                 /* Check whether VALUE is safe to move in the code
+                    stream.  If it is, we might be able to replace
+                    occurrences of VAR with it.  */
+                 switch (get_gimple_rhs_class (TREE_CODE (value)))
+                   {
+                   case GIMPLE_BINARY_RHS:
+                     vsafe
+                       = ((is_gimple_min_invariant (TREE_OPERAND (value, 0))
+                           || is_gimple_reg (TREE_OPERAND (value, 0)))

you didn't address my review comment here.  All this checking is
completely unnecessary.  GIMPLE_BINARY_RHS and GIMPLE_UNARY_RHS
can only ever have reg or constant operands, only the GIMPLE_SINGLE_RHS
case is interesting.

Btw, I think I miss a

  if (is_gimple_min_invariant (value)
      || is_gimple_reg (value))
    usetemp = false;

before these checks.

-         SET_USE (use_p, unshare_expr (value));
+         /* unshare_expr is not needed here.  vexpr 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.  */
+         SET_USE (use_p, value);

that's not true.  Value could be &a.b.c.  If you want to save memory
you have to tighten is_gimple_min_invariant (value) to CONSTANT_CLASS_P (value).

@@ -368,6 +369,16 @@ gsi_replace (gimple_stmt_iterator *gsi,
   if (stmt == orig_stmt)
     return;

+  {
+    tree lhs;
+
+    gcc_assert (!(lhs = gimple_get_lhs (orig_stmt))
+               || lhs == gimple_get_lhs (stmt));
+
+    /* If the assertion above fails, we may want to conditionally call
+       insert_debug_temps_for_defs (gsi).  */
+  }

I think it's better to write this as

   gcc_assert (!gimple_has_lhs (orig_stmt)
                      || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));

no need for local braces or a temporary variable.

Ok with the above changes.

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-11 14:26                   ` Richard Guenther
@ 2009-10-12  6:36                     ` Alexandre Oliva
  2009-10-12  8:58                       ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-12  6:36 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 6887 bytes --]

On Oct 11, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> +  /* First of all, check whether there are debug stmts that reference
> +     this variable and, if there are, decide whether we can */

> missing '. '

Uhh...  That, and more.  I clearly didn't finish it.

> you didn't address my review comment here.  All this checking is
> completely unnecessary.  GIMPLE_BINARY_RHS and GIMPLE_UNARY_RHS
> can only ever have reg or constant operands, only the GIMPLE_SINGLE_RHS
> case is interesting.

Aah, I thought you meant a different simplification.

> Btw, I think I miss a

>   if (is_gimple_min_invariant (value)
>       || is_gimple_reg (value))
>     usetemp = false;

> before these checks.

Indeed.  The simplified logic in the revised patch sort of obviates (or
implies) it.

> -         SET_USE (use_p, unshare_expr (value));
> +         /* unshare_expr is not needed here.  vexpr 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.  */
> +         SET_USE (use_p, value);

> that's not true.  Value could be &a.b.c

Oh!  I thought that would have been unary, rather than single.  Wow.
Learning new things every day ;-)

> If you want to save memory you have to tighten is_gimple_min_invariant
> (value) to CONSTANT_CLASS_P (value).

*nod*  Fixed.

> I think it's better to write this as

>    gcc_assert (!gimple_has_lhs (orig_stmt)
>                       || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));

Agreed.

Here's the revised insert_debug_temp_for_var_def(), currently under
testing, followed by the revised patch.


/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
   by other DEBUG stmts, and replace uses of the DEF with the
   newly-created debug temp.  */

void
insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
{
  imm_use_iterator imm_iter;
  use_operand_p use_p;
  gimple stmt;
  gimple def_stmt = NULL;
  bool no_value = false;
  int usecount = 0;
  tree value = NULL;

  if (!MAY_HAVE_DEBUG_STMTS)
    return;

  /* First of all, check whether there are debug stmts that reference
     this variable and, if there are, decide whether we should use a
     debug temp.  */
  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
    {
      stmt = USE_STMT (use_p);

      if (!gimple_debug_bind_p (stmt))
	continue;

      if (usecount++)
	break;

      if (gimple_debug_bind_get_value (stmt) != var)
	{
	  /* Count this as an additional use, so as to make sure we
	     use a temp unless VAR's definition has a SINGLE_RHS that
	     can be shared.  */
	  usecount++;
	  break;
	}
    }

  if (!usecount)
    return;

  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
    {
      if (!gimple_debug_bind_p (stmt))
	continue;

      /* Here we compute (lazily) the value assigned to VAR, but we
	 remember if we tried before and failed, so that we don't try
	 again.  */
      if (!value && !no_value)
	{
	  if (gsi)
	    def_stmt = gsi_stmt (*gsi);
	  else
	    def_stmt = SSA_NAME_DEF_STMT (var);

	  /* If we didn't get an insertion point, and the stmt has
	     already been removed, we won't be able to insert the
	     debug bind stmt, so we'll have to drop debug
	     information.  */
	  if (is_gimple_assign (def_stmt))
	    {
	      if (!dom_info_available_p (CDI_DOMINATORS))
		{
		  struct walk_stmt_info wi;

		  memset (&wi, 0, sizeof (wi));

		  /* When removing blocks without following reverse
		     dominance order, we may sometimes encounter SSA_NAMEs
		     that have already been released, referenced in other
		     SSA_DEFs that we're about to release.  Consider:

		     <bb X>:
		     v_1 = foo;

		     <bb Y>:
		     w_2 = v_1 + bar;
		     # DEBUG w => w_2

		     If we deleted BB X first, propagating the value of
		     w_2 won't do us any good.  It's too late to recover
		     their original definition of v_1: when it was
		     deleted, it was only referenced in other DEFs, it
		     couldn't possibly know it should have been retained,
		     and propagating every single DEF just in case it
		     might have to be propagated into a DEBUG STMT would
		     probably be too wasteful.

		     When dominator information is not readily
		     available, we check for and accept some loss of
		     debug information.  But if it is available,
		     there's no excuse for us to remove blocks in the
		     wrong order, so we don't even check for dead SSA
		     NAMEs.  SSA verification shall catch any
		     errors.  */
		  if ((!gsi && !gimple_bb (def_stmt))
		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
					  &wi))
		    no_value = true;
		}

	      if (!no_value)
		value = gimple_assign_rhs_to_tree (def_stmt);
	    }

	  if (!value)
	    no_value = true;
	  else
	    {
	      bool no_temp;

	      /* If there's a single use, and VAR is the entire
		 expression (usecount would have been incremented
		 again if not), then we can propagate VALUE into this
		 single use, avoiding the temp.

		 We can also avoid using a temp if VALUE can be shared
		 and propagated into all uses, without generating
		 expressions that wouldn't be valid gimple RHSs.

		 Other cases that would require unsharing or
		 non-gimple RHSs are deferred to a debug temp,
		 although we could avoid temps at the expense of
		 duplication of expressions.  */

	      if (usecount == 1)
		no_temp = (!gimple_assign_single_p (def_stmt)
			   || is_gimple_min_invariant (value)
			   || is_gimple_reg (value));
	      else
		{
		  no_temp = (CONSTANT_CLASS_P (value)
			     || is_gimple_reg (value));
		  gcc_assert (!no_temp || unshare_expr (value) == value);
		}

	      if (no_temp)
		value = unshare_expr (value);
	      else
		{
		  gimple def_temp;
		  tree vexpr = make_node (DEBUG_EXPR_DECL);

		  def_temp = gimple_build_debug_bind (vexpr,
						      unshare_expr (value),
						      def_stmt);

		  DECL_ARTIFICIAL (vexpr) = 1;
		  TREE_TYPE (vexpr) = TREE_TYPE (value);
		  if (DECL_P (value))
		    DECL_MODE (vexpr) = DECL_MODE (value);
		  else
		    DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));

		  if (gsi)
		    gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
		  else
		    {
		      gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
		      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
		    }

		  value = vexpr;
		}
	    }
	}

      if (no_value)
	gimple_debug_bind_reset_value (stmt);
      else
	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
	  /* unshare_expr is not needed here.  vexpr 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.  */
	  SET_USE (use_p, value);

      update_stmt (stmt);
    }
}



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 35959 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	Scan early for use count and kind in debug stmts.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.h (DEBUG_TEMP_UID): New.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
	(cselib_hash_rtx): Likewise.
	(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace): Check for same lhs.
	(gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
	(move_computations_stmt): Drop explicit propagation into debug stmts.
	(rewrite_bittest): Likewise.  Use gsi_remove for propagation.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
	debug temps without values.
	(eliminate_unnecessary_stmts): Don't discard just-inserted
	debug stmts.

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* gcc.dg/guality/pr41447-1.c: New.
	* gcc.dg/debug/pr41264-1.c: New.
	* gcc.dg/debug/pr41343-1.c: New.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.def	2009-10-12 02:19:10.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/rtl.def	2009-10-12 02:19:11.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/gengtype.c	2009-10-12 02:19:11.000000000 -0300
@@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa.c	2009-10-12 03:06:46.000000000 -0300
@@ -295,70 +295,69 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
-  gimple stmt;
   use_operand_p use_p;
-  tree value = NULL;
+  gimple stmt;
+  gimple def_stmt = NULL;
   bool no_value = false;
+  int usecount = 0;
+  tree value = NULL;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+  /* First of all, check whether there are debug stmts that reference
+     this variable and, if there are, decide whether we should use a
+     debug temp.  */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
+      stmt = USE_STMT (use_p);
 
-      if (!is_gimple_debug (stmt))
+      if (!gimple_debug_bind_p (stmt))
 	continue;
 
-      if (tobb)
-	{
-	  bb = gimple_bb (stmt);
+      if (usecount++)
+	break;
 
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
-
-	      if (gsi_end_p (si))
-		continue;
+      if (gimple_debug_bind_get_value (stmt) != var)
+	{
+	  /* Count this as an additional use, so as to make sure we
+	     use a temp unless VAR's definition has a SINGLE_RHS that
+	     can be shared.  */
+	  usecount++;
+	  break;
+	}
+    }
 
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
+  if (!usecount)
+    return;
 
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
+  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+    {
+      if (!gimple_debug_bind_p (stmt))
+	continue;
 
       /* Here we compute (lazily) the value assigned to VAR, but we
 	 remember if we tried before and failed, so that we don't try
 	 again.  */
       if (!value && !no_value)
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  if (gsi)
+	    def_stmt = gsi_stmt (*gsi);
+	  else
+	    def_stmt = SSA_NAME_DEF_STMT (var);
 
+	  /* If we didn't get an insertion point, and the stmt has
+	     already been removed, we won't be able to insert the
+	     debug bind stmt, so we'll have to drop debug
+	     information.  */
 	  if (is_gimple_assign (def_stmt))
 	    {
 	      if (!dom_info_available_p (CDI_DOMINATORS))
@@ -395,7 +394,9 @@ propagate_var_def_into_debug_stmts (tree
 		     wrong order, so we don't even check for dead SSA
 		     NAMEs.  SSA verification shall catch any
 		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
+		  if ((!gsi && !gimple_bb (def_stmt))
+		      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+					  &wi))
 		    no_value = true;
 		}
 
@@ -405,42 +406,106 @@ propagate_var_def_into_debug_stmts (tree
 
 	  if (!value)
 	    no_value = true;
+	  else
+	    {
+	      bool no_temp;
+
+	      /* If there's a single use, and VAR is the entire
+		 expression (usecount would have been incremented
+		 again if not), then we can propagate VALUE into this
+		 single use, avoiding the temp.
+
+		 We can also avoid using a temp if VALUE can be shared
+		 and propagated into all uses, without generating
+		 expressions that wouldn't be valid gimple RHSs.
+
+		 Other cases that would require unsharing or
+		 non-gimple RHSs are deferred to a debug temp,
+		 although we could avoid temps at the expense of
+		 duplication of expressions.  */
+
+	      if (usecount == 1)
+		no_temp = (!gimple_assign_single_p (def_stmt)
+			   || is_gimple_min_invariant (value)
+			   || is_gimple_reg (value));
+	      else
+		{
+		  no_temp = (CONSTANT_CLASS_P (value)
+			     || is_gimple_reg (value));
+		  gcc_assert (!no_temp || unshare_expr (value) == value);
+		}
+
+	      if (no_temp)
+		value = unshare_expr (value);
+	      else
+		{
+		  gimple def_temp;
+		  tree vexpr = make_node (DEBUG_EXPR_DECL);
+
+		  def_temp = gimple_build_debug_bind (vexpr,
+						      unshare_expr (value),
+						      def_stmt);
+
+		  DECL_ARTIFICIAL (vexpr) = 1;
+		  TREE_TYPE (vexpr) = TREE_TYPE (value);
+		  if (DECL_P (value))
+		    DECL_MODE (vexpr) = DECL_MODE (value);
+		  else
+		    DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
+
+		  if (gsi)
+		    gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+		  else
+		    {
+		      gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+		      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
+		    }
+
+		  value = vexpr;
+		}
+	    }
 	}
 
       if (no_value)
 	gimple_debug_bind_reset_value (stmt);
       else
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  /* unshare_expr is not needed here.  vexpr 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.  */
+	  SET_USE (use_p, value);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.h	2009-10-12 02:19:11.000000000 -0300
@@ -2455,6 +2455,10 @@ struct function;
 /* Every ..._DECL node gets a unique number.  */
 #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
 
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+   uses.  */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
 /* These two fields describe where in the source code the declaration
    was.  If the declaration appears in several places (as for a C
    function that is declared first and then defined later), this
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.c	2009-10-12 02:19:11.000000000 -0300
@@ -152,6 +152,9 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/cfgexpand.c	2009-10-12 02:19:11.000000000 -0300
@@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/var-tracking.c	2009-10-12 02:19:11.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/cselib.c	2009-10-12 02:19:11.000000000 -0300
@@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     {
     case CONST_DOUBLE:
     case CONST_FIXED:
+    case DEBUG_EXPR:
       return 0;
 
     case LABEL_REF:
@@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
 
       return e->value;
 
+    case DEBUG_EXPR:
+      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      return hash ? hash : (unsigned int) DEBUG_EXPR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
@@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-10-12 02:19:12.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/emit-rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/print-rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/sched-vis.c	2009-10-12 02:19:12.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-dump.c	2009-10-12 02:19:12.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-10-12 02:19:12.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/gimple-iterator.c	2009-10-12 02:19:12.000000000 -0300
@@ -358,7 +358,8 @@ gsi_split_seq_before (gimple_stmt_iterat
 
 /* Replace the statement pointed-to by GSI to STMT.  If UPDATE_EH_INFO
    is true, the exception handling information of the original
-   statement is moved to the new statement.  */
+   statement is moved to the new statement.  Assignments must only be
+   replaced with assignments to the same LHS.  */
 
 void
 gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
@@ -368,6 +369,9 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  gcc_assert (!gimple_has_lhs (orig_stmt)
+	      || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +474,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-10-12 02:19:12.000000000 -0300
@@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator
   gimple stmt, stmt1, stmt2;
   tree var, name, lhs, type;
   tree real_one;
+  gimple_stmt_iterator gsi;
 
   stmt = gsi_stmt (*bsi);
   lhs = gimple_assign_lhs (stmt);
@@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator
   /* Replace division stmt with reciprocal and multiply stmts.
      The multiply stmt is not invariant, so update iterator
      and avoid rescanning.  */
-  gsi_replace (bsi, stmt1, true);
-  gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
+  gsi = *bsi;
+  gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+  gsi_replace (&gsi, stmt2, true);
 
   /* Continue processing with invariant reciprocal statement.  */
   return stmt1;
@@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *b
   if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
       && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
     {
+      gimple_stmt_iterator rsi;
+
       /* 1 << B */
       var = create_tmp_var (TREE_TYPE (a), "shifttmp");
       add_referenced_var (var);
@@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *b
       SET_USE (use, name);
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
-      gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
-      gsi_replace (bsi, stmt2, true);
+      /* Don't use gsi_replace here, none of the new assignments sets
+	 the variable originally set in stmt.  Move bsi to stmt1, and
+	 then remove the original stmt, so that we get a chance to
+	 retain debug info for it.  */
+      rsi = *bsi;
+      gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+      gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
+      gsi_remove (&rsi, true);
 
       return stmt1;
     }
@@ -1060,7 +1069,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-10-12 02:19:12.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-10-12 02:19:12.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-10-12 02:19:12.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssanames.c	2009-10-12 02:19:13.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-flow.h	2009-10-12 02:19:13.000000000 -0300
@@ -637,10 +637,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-10-12 02:19:13.000000000 -0300
@@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple
       break;
 
     case GIMPLE_DEBUG:
-      mark_stmt_necessary (stmt, false);
+      /* Debug temps without a value are not useful.  ??? If we could
+	 easily locate the debug temp bind stmt for a use thereof,
+	 would could refrain from marking all debug temps here, and
+	 mark them only if they're used.  */
+      if (gimple_debug_bind_has_value_p (stmt)
+	  || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
+	mark_stmt_necessary (stmt, false);
       return;
 
     case GIMPLE_GOTO:
@@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
 	{
 	  stmt = gsi_stmt (gsi);
 
+	  psi = gsi;
+	  gsi_prev (&psi);
+
 	  stats.total++;
 
 	  /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1131,6 @@ eliminate_unnecessary_stmts (void)
 	    {
 	      remove_dead_stmt (&gsi, bb);
 	      something_changed = true;
-
-	      /* If stmt was the last stmt in the block, we want to
-		 move gsi to the stmt that became the last stmt, but
-		 gsi_prev would crash.  */
-	      if (gsi_end_p (gsi))
-		gsi = gsi_last_bb (bb);
-	      else
-		gsi_prev (&gsi);
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
@@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_prev (&gsi);
 	    }
-	  else
-	    gsi_prev (&gsi);
 	}
     }
 
Index: gcc/testsuite/gcc.dg/guality/pr41447-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/guality/pr41447-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,25 @@
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-g -O2" } */
+
+#include "guality.h"
+
+int a;
+
+int foo()
+{
+  int tmp = a;
+  int tmp2 = a;
+  int tmp3;
+  int res;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  a = 0;
+  tmp3 = tmp2;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  GUALCHKVAL (tmp3);
+  res = tmp - tmp2 + 1;
+  return res;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41264-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41264-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+typedef unsigned int hashval_t;
+static hashval_t __attribute__((always_inline))
+iterative_hash_host_wide_int (long val, hashval_t val2)
+{
+  hashval_t a = (hashval_t) val;
+  int zero = 0;
+  hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+
+  a -= b; a -= val2; a ^= (val2>>13);
+  b -= val2; b -= a; b ^= (a<< 8);
+  val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
+  a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
+  b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
+  a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
+  b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
+  return val2;
+}
+
+hashval_t
+bla (int nunits, int mode)
+{
+  hashval_t hashcode = 0;
+
+
+  hashcode = iterative_hash_host_wide_int (14, hashcode);
+  hashcode = iterative_hash_host_wide_int (nunits, hashcode);
+  hashcode = iterative_hash_host_wide_int (mode, hashcode);
+  if (nunits)
+    return 0;
+  else
+    return hashcode;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41343-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41343-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#define X(new,old) int i ## new = i ## old + i ## old;
+#define Y(pfx) X(pfx ## 1, pfx) \
+  X(pfx ## 2, pfx ## 1) \
+  X(pfx ## 3, pfx ## 2) \
+  X(pfx ## 4, pfx ## 3) \
+  X(pfx ## 5, pfx ## 4) \
+  X(pfx ## 6, pfx ## 5) \
+  X(pfx ## 7, pfx ## 6) \
+  X(pfx ## 8, pfx ## 7) \
+  X(pfx ## 9, pfx ## 8)
+
+void foo (int i1)
+{
+  Y(1)
+  Y(11)
+  Y(111)
+  asm ("" : : "X" (i1));
+}

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-12  6:36                     ` Alexandre Oliva
@ 2009-10-12  8:58                       ` Richard Guenther
  2009-10-12 19:01                         ` Alexandre Oliva
  0 siblings, 1 reply; 25+ messages in thread
From: Richard Guenther @ 2009-10-12  8:58 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches

On Mon, Oct 12, 2009 at 8:11 AM, Alexandre Oliva <aoliva@redhat.com> wrote:
> On Oct 11, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:
>
>> +  /* First of all, check whether there are debug stmts that reference
>> +     this variable and, if there are, decide whether we can */
>
>> missing '. '
>
> Uhh...  That, and more.  I clearly didn't finish it.
>
>> you didn't address my review comment here.  All this checking is
>> completely unnecessary.  GIMPLE_BINARY_RHS and GIMPLE_UNARY_RHS
>> can only ever have reg or constant operands, only the GIMPLE_SINGLE_RHS
>> case is interesting.
>
> Aah, I thought you meant a different simplification.
>
>> Btw, I think I miss a
>
>>   if (is_gimple_min_invariant (value)
>>       || is_gimple_reg (value))
>>     usetemp = false;
>
>> before these checks.
>
> Indeed.  The simplified logic in the revised patch sort of obviates (or
> implies) it.
>
>> -         SET_USE (use_p, unshare_expr (value));
>> +         /* unshare_expr is not needed here.  vexpr 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.  */
>> +         SET_USE (use_p, value);
>
>> that's not true.  Value could be &a.b.c
>
> Oh!  I thought that would have been unary, rather than single.  Wow.
> Learning new things every day ;-)
>
>> If you want to save memory you have to tighten is_gimple_min_invariant
>> (value) to CONSTANT_CLASS_P (value).
>
> *nod*  Fixed.
>
>> I think it's better to write this as
>
>>    gcc_assert (!gimple_has_lhs (orig_stmt)
>>                       || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
>
> Agreed.
>
> Here's the revised insert_debug_temp_for_var_def(), currently under
> testing, followed by the revised patch.

Ah, nice to see this in once piece ...

>
> /* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
>   by other DEBUG stmts, and replace uses of the DEF with the
>   newly-created debug temp.  */
>
> void
> insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
> {
>  imm_use_iterator imm_iter;
>  use_operand_p use_p;
>  gimple stmt;
>  gimple def_stmt = NULL;
>  bool no_value = false;
>  int usecount = 0;
>  tree value = NULL;
>
>  if (!MAY_HAVE_DEBUG_STMTS)
>    return;
>
>  /* First of all, check whether there are debug stmts that reference
>     this variable and, if there are, decide whether we should use a
>     debug temp.  */
>  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
>    {
>      stmt = USE_STMT (use_p);
>
>      if (!gimple_debug_bind_p (stmt))
>        continue;
>
>      if (usecount++)
>        break;
>
>      if (gimple_debug_bind_get_value (stmt) != var)
>        {
>          /* Count this as an additional use, so as to make sure we
>             use a temp unless VAR's definition has a SINGLE_RHS that
>             can be shared.  */
>          usecount++;
>          break;
>        }
>    }
>
>  if (!usecount)
>    return;
>
>  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
>    {
>      if (!gimple_debug_bind_p (stmt))
>        continue;
>
>      /* Here we compute (lazily) the value assigned to VAR, but we
>         remember if we tried before and failed, so that we don't try
>         again.  */

I believe with first looping over all uses you can now move the
following block out of this loop making things a load easier to read.

>      if (!value && !no_value)
>        {
>          if (gsi)
>            def_stmt = gsi_stmt (*gsi);
>          else
>            def_stmt = SSA_NAME_DEF_STMT (var);
>
>          /* If we didn't get an insertion point, and the stmt has
>             already been removed, we won't be able to insert the
>             debug bind stmt, so we'll have to drop debug
>             information.  */
>          if (is_gimple_assign (def_stmt))
>            {
>              if (!dom_info_available_p (CDI_DOMINATORS))
>                {
>                  struct walk_stmt_info wi;
>
>                  memset (&wi, 0, sizeof (wi));
>
>                  /* When removing blocks without following reverse
>                     dominance order, we may sometimes encounter SSA_NAMEs
>                     that have already been released, referenced in other
>                     SSA_DEFs that we're about to release.  Consider:
>
>                     <bb X>:
>                     v_1 = foo;
>
>                     <bb Y>:
>                     w_2 = v_1 + bar;
>                     # DEBUG w => w_2
>
>                     If we deleted BB X first, propagating the value of
>                     w_2 won't do us any good.  It's too late to recover
>                     their original definition of v_1: when it was
>                     deleted, it was only referenced in other DEFs, it
>                     couldn't possibly know it should have been retained,
>                     and propagating every single DEF just in case it
>                     might have to be propagated into a DEBUG STMT would
>                     probably be too wasteful.
>
>                     When dominator information is not readily
>                     available, we check for and accept some loss of
>                     debug information.  But if it is available,
>                     there's no excuse for us to remove blocks in the
>                     wrong order, so we don't even check for dead SSA
>                     NAMEs.  SSA verification shall catch any
>                     errors.  */
>                  if ((!gsi && !gimple_bb (def_stmt))
>                      || !walk_gimple_op (def_stmt, find_released_ssa_name,
>                                          &wi))
>                    no_value = true;
>                }
>
>              if (!no_value)
>                value = gimple_assign_rhs_to_tree (def_stmt);
>            }
>
>          if (!value)
>            no_value = true;
>          else
>            {
>              bool no_temp;
>
>              /* If there's a single use, and VAR is the entire
>                 expression (usecount would have been incremented
>                 again if not), then we can propagate VALUE into this
>                 single use, avoiding the temp.
>
>                 We can also avoid using a temp if VALUE can be shared
>                 and propagated into all uses, without generating
>                 expressions that wouldn't be valid gimple RHSs.
>
>                 Other cases that would require unsharing or
>                 non-gimple RHSs are deferred to a debug temp,
>                 although we could avoid temps at the expense of
>                 duplication of expressions.  */
>
>              if (usecount == 1)
>                no_temp = (!gimple_assign_single_p (def_stmt)
>                           || is_gimple_min_invariant (value)
>                           || is_gimple_reg (value));
>              else
>                {
>                  no_temp = (CONSTANT_CLASS_P (value)
>                             || is_gimple_reg (value));
>                  gcc_assert (!no_temp || unshare_expr (value) == value);

Eh, drop this assert please ...

>                }
>
>              if (no_temp)
>                value = unshare_expr (value);
>              else
>                {
>                  gimple def_temp;
>                  tree vexpr = make_node (DEBUG_EXPR_DECL);
>
>                  def_temp = gimple_build_debug_bind (vexpr,
>                                                      unshare_expr (value),
>                                                      def_stmt);
>
>                  DECL_ARTIFICIAL (vexpr) = 1;
>                  TREE_TYPE (vexpr) = TREE_TYPE (value);
>                  if (DECL_P (value))
>                    DECL_MODE (vexpr) = DECL_MODE (value);
>                  else
>                    DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
>
>                  if (gsi)
>                    gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
>                  else
>                    {
>                      gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
>                      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
>                    }
>
>                  value = vexpr;
>                }
>            }
>        }

In fact you can move all of the above out of the loop IMHO.

>      if (no_value)
>        gimple_debug_bind_reset_value (stmt);
>      else
>        FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
>          /* unshare_expr is not needed here.  vexpr 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.  */
>          SET_USE (use_p, value);
>
>      update_stmt (stmt);
>    }
> }

Ok with that change.

Richard.

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-12  8:58                       ` Richard Guenther
@ 2009-10-12 19:01                         ` Alexandre Oliva
  2009-10-13  6:02                           ` Eric Botcazou
  2009-10-13 21:01                           ` Alexandre Oliva
  0 siblings, 2 replies; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-12 19:01 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, jakub

[-- Attachment #1: Type: text/plain, Size: 584 bytes --]

On Oct 12, 2009, Richard Guenther <richard.guenther@gmail.com> wrote:

> I believe with first looping over all uses you can now move the
> following block out of this loop making things a load easier to read.

Nice!  Done

>>                  gcc_assert (!no_temp || unshare_expr (value) == value);

> Eh, drop this assert please ...

Done.

> In fact you can move all of the above out of the loop IMHO.

Yup.  And get rid of some state variables, too, and limit the scope of
others.  Done.

> Ok with that change.

Thanks, here's what I'm installing.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343.patch --]
[-- Type: text/x-diff, Size: 38254 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* tree.def (DEBUG_EXPR_DECL): New.
	* rtl.def (DEBUG_EXPR): New.
	* gengtype.c (adjust_field_rtx_def): Handle it.
	* tree-ssa.c (propagate_var_def_into_debug_stmts): Rename to...
	(insert_debug_temp_for_var_def): ... this.  Drop support for
	moving.  Take iterator for def stmt; insert debug stmt before it.
	Scan early for use count and kind in debug stmts.
	(propagate_defs_into_debug_stmts): Rename to...
	(insert_debug_temps_for_defs): ... this.  Likewise.
	* tree.h (DEBUG_TEMP_UID): New.
	* tree.c (next_debug_decl_uid): New.
	(make_node_stat): Count debug decls separately.
	(copy_node_stat): Likewise.
	* cfgexpand.c (expand_debug_expr): Handle DEBUG_EXPR_DECL.
	* var-tracking.c (dv_is_decl_p): Recognize it.
	(VALUE_RECURSED_INTO): Apply to DEBUG_EXPRs too.
	(track_expr_p): Track expanded DEBUG_EXPR_DECLs.
	(vt_expand_loc_callback): Expand DEBUG_EXPRs.
	(emit_note_insn_var_location): Don't emit notes for DEBUG_EXPR_DECLs.
	* cselib.c (rtx_equal_for_cselib_p): Handle DEBUG_EXPR.
	(cselib_hash_rtx): Likewise.
	(cselib_expand_value_rtx_1): Use callback for DEBUG_EXPR.
	* tree-ssa-operands.c (get_expr_operands): Skip DEBUG_EXPR_DECLs in
	debug bind stmts.
	* emit-rtl.c (verify_rtx_sharing): Handle DEBUG_EXPR and VALUE.
	(copy_rtx_if_shared_1, reset_used_flags, set_used_flags): Likewise.
	* rtl.c (copy_rtx): Likewise.
	(rtx_equal_p_cb, rtx_equal_p): Handle DEBUG_EXPR.
	* print-rtl.c (print_rtx): Likewise.
	* sched-vis.c (print_value): Likewise.
	(print_insn): Handle DEBUG_EXPR_DECL.
	* tree-dump.c (dequeue_and_dump): Likewise.
	* tree-pretty-print.c (dump_decl_name, dump_generic_node): Likewise.
	* gimple-iterator (gsi_replace): Check for same lhs.
	(gsi_remove): Insert debug temps.
	* tree-ssa-loop-im.c (rewrite_reciprocal): Replace with same lhs.
	(move_computations_stmt): Drop explicit propagation into debug stmts.
	(rewrite_bittest): Likewise.  Use gsi_remove for propagation.
	* tree-ssa-reassoc.c (rewrite_expr_tree, linearize_expr): Likewise.
	* tree-ssa-sink.c (statement_sink_location): Likewise.
	* tree-ssa-forwprop (forward_propagate_addr_expr): Likewise.
	* tree-ssanames.c (release_ssa_name): Adjust for rename.
	* tree-flow.h: Likewise.
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Don't mark
	debug temps without values.
	(eliminate_unnecessary_stmts): Don't discard just-inserted
	debug stmts.

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* gcc.dg/guality/pr41447-1.c: New.
	* gcc.dg/debug/pr41264-1.c: New.
	* gcc.dg/debug/pr41343-1.c: New.

Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.def	2009-10-12 02:19:10.000000000 -0300
@@ -351,6 +351,10 @@ DEFTREECODE (PARM_DECL, "parm_decl", tcc
 DEFTREECODE (TYPE_DECL, "type_decl", tcc_declaration, 0)
 DEFTREECODE (RESULT_DECL, "result_decl", tcc_declaration, 0)
 
+/* A "declaration" of a debug temporary.  It should only appear in
+   DEBUG stmts.  */
+DEFTREECODE (DEBUG_EXPR_DECL, "debug_expr_decl", tcc_declaration, 0)
+
 /* A namespace declaration.  Namespaces appear in DECL_CONTEXT of other
    _DECLs, providing a hierarchy of names.  */
 DEFTREECODE (NAMESPACE_DECL, "namespace_decl", tcc_declaration, 0)
Index: gcc/rtl.def
===================================================================
--- gcc/rtl.def.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/rtl.def	2009-10-12 02:19:11.000000000 -0300
@@ -88,6 +88,10 @@ DEF_RTL_EXPR(UNKNOWN, "UnKnown", "*", RT
    DECL codes in trees.  */
 DEF_RTL_EXPR(VALUE, "value", "0", RTX_OBJ)
 
+/* The RTL generated for a DEBUG_EXPR_DECL.  It links back to the
+   DEBUG_EXPR_DECL in the first operand.  */
+DEF_RTL_EXPR(DEBUG_EXPR, "debug_expr", "0", RTX_OBJ)
+
 /* ---------------------------------------------------------------------
    Expressions used in constructing lists.
    --------------------------------------------------------------------- */
Index: gcc/gengtype.c
===================================================================
--- gcc/gengtype.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/gengtype.c	2009-10-12 02:19:11.000000000 -0300
@@ -1117,6 +1117,8 @@ adjust_field_rtx_def (type_p t, options_
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == VALUE && aindex == 0)
 		t = scalar_tp, subname = "rt_int";
+	      else if (i == DEBUG_EXPR && aindex == 0)
+		t = tree_tp, subname = "rt_tree";
 	      else if (i == REG && aindex == 1)
 		t = scalar_tp, subname = "rt_int";
 	      else if (i == REG && aindex == 2)
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa.c	2009-10-12 15:54:52.000000000 -0300
@@ -295,152 +295,198 @@ find_released_ssa_name (tree *tp, int *w
   return NULL_TREE;
 }
 
-/* Given a VAR whose definition STMT is to be moved to the iterator
-   position TOGSIP in the TOBB basic block, verify whether we're
-   moving it across any of the debug statements that use it, and
-   adjust them as needed.  If TOBB is NULL, then the definition is
-   understood as being removed, and TOGSIP is unused.  */
+/* Insert a DEBUG BIND stmt before the DEF of VAR if VAR is referenced
+   by other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
+
 void
-propagate_var_def_into_debug_stmts (tree var,
-				    basic_block tobb,
-				    const gimple_stmt_iterator *togsip)
+insert_debug_temp_for_var_def (gimple_stmt_iterator *gsi, tree var)
 {
   imm_use_iterator imm_iter;
-  gimple stmt;
   use_operand_p use_p;
+  gimple stmt;
+  gimple def_stmt = NULL;
+  int usecount = 0;
   tree value = NULL;
-  bool no_value = false;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+  /* First of all, check whether there are debug stmts that reference
+     this variable and, if there are, decide whether we should use a
+     debug temp.  */
+  FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
     {
-      basic_block bb;
-      gimple_stmt_iterator si;
+      stmt = USE_STMT (use_p);
 
-      if (!is_gimple_debug (stmt))
+      if (!gimple_debug_bind_p (stmt))
 	continue;
 
-      if (tobb)
-	{
-	  bb = gimple_bb (stmt);
+      if (usecount++)
+	break;
 
-	  if (bb != tobb)
-	    {
-	      gcc_assert (dom_info_available_p (CDI_DOMINATORS));
-	      if (dominated_by_p (CDI_DOMINATORS, bb, tobb))
-		continue;
-	    }
-	  else
-	    {
-	      si = *togsip;
+      if (gimple_debug_bind_get_value (stmt) != var)
+	{
+	  /* Count this as an additional use, so as to make sure we
+	     use a temp unless VAR's definition has a SINGLE_RHS that
+	     can be shared.  */
+	  usecount++;
+	  break;
+	}
+    }
 
-	      if (gsi_end_p (si))
-		continue;
+  if (!usecount)
+    return;
 
-	      do
-		{
-		  gsi_prev (&si);
-		  if (gsi_end_p (si))
-		    break;
-		}
-	      while (gsi_stmt (si) != stmt);
+  if (gsi)
+    def_stmt = gsi_stmt (*gsi);
+  else
+    def_stmt = SSA_NAME_DEF_STMT (var);
 
-	      if (gsi_end_p (si))
-		continue;
-	    }
-	}
+  /* If we didn't get an insertion point, and the stmt has already
+     been removed, we won't be able to insert the debug bind stmt, so
+     we'll have to drop debug information.  */
+  if (is_gimple_assign (def_stmt))
+    {
+      bool no_value = false;
 
-      /* Here we compute (lazily) the value assigned to VAR, but we
-	 remember if we tried before and failed, so that we don't try
-	 again.  */
-      if (!value && !no_value)
+      if (!dom_info_available_p (CDI_DOMINATORS))
 	{
-	  gimple def_stmt = SSA_NAME_DEF_STMT (var);
+	  struct walk_stmt_info wi;
 
-	  if (is_gimple_assign (def_stmt))
-	    {
-	      if (!dom_info_available_p (CDI_DOMINATORS))
-		{
-		  struct walk_stmt_info wi;
+	  memset (&wi, 0, sizeof (wi));
 
-		  memset (&wi, 0, sizeof (wi));
+	  /* When removing blocks without following reverse dominance
+	     order, we may sometimes encounter SSA_NAMEs that have
+	     already been released, referenced in other SSA_DEFs that
+	     we're about to release.  Consider:
+
+	     <bb X>:
+	     v_1 = foo;
+
+	     <bb Y>:
+	     w_2 = v_1 + bar;
+	     # DEBUG w => w_2
+
+	     If we deleted BB X first, propagating the value of w_2
+	     won't do us any good.  It's too late to recover their
+	     original definition of v_1: when it was deleted, it was
+	     only referenced in other DEFs, it couldn't possibly know
+	     it should have been retained, and propagating every
+	     single DEF just in case it might have to be propagated
+	     into a DEBUG STMT would probably be too wasteful.
+
+	     When dominator information is not readily available, we
+	     check for and accept some loss of debug information.  But
+	     if it is available, there's no excuse for us to remove
+	     blocks in the wrong order, so we don't even check for
+	     dead SSA NAMEs.  SSA verification shall catch any
+	     errors.  */
+	  if ((!gsi && !gimple_bb (def_stmt))
+	      || !walk_gimple_op (def_stmt, find_released_ssa_name,
+				  &wi))
+	    no_value = true;
+	}
 
-		  /* When removing blocks without following reverse
-		     dominance order, we may sometimes encounter SSA_NAMEs
-		     that have already been released, referenced in other
-		     SSA_DEFs that we're about to release.  Consider:
-
-		     <bb X>:
-		     v_1 = foo;
-
-		     <bb Y>:
-		     w_2 = v_1 + bar;
-		     # DEBUG w => w_2
-
-		     If we deleted BB X first, propagating the value of
-		     w_2 won't do us any good.  It's too late to recover
-		     their original definition of v_1: when it was
-		     deleted, it was only referenced in other DEFs, it
-		     couldn't possibly know it should have been retained,
-		     and propagating every single DEF just in case it
-		     might have to be propagated into a DEBUG STMT would
-		     probably be too wasteful.
-
-		     When dominator information is not readily
-		     available, we check for and accept some loss of
-		     debug information.  But if it is available,
-		     there's no excuse for us to remove blocks in the
-		     wrong order, so we don't even check for dead SSA
-		     NAMEs.  SSA verification shall catch any
-		     errors.  */
-		  if (!walk_gimple_op (def_stmt, find_released_ssa_name, &wi))
-		    no_value = true;
-		}
+      if (!no_value)
+	value = gimple_assign_rhs_to_tree (def_stmt);
+    }
+
+  if (value)
+    {
+      /* If there's a single use of VAR, and VAR is the entire debug
+	 expression (usecount would have been incremented again
+	 otherwise), and the definition involves only constants and
+	 SSA names, then we can propagate VALUE into this single use,
+	 avoiding the temp.
+
+	 We can also avoid using a temp if VALUE can be shared and
+	 propagated into all uses, without generating expressions that
+	 wouldn't be valid gimple RHSs.
+
+	 Other cases that would require unsharing or non-gimple RHSs
+	 are deferred to a debug temp, although we could avoid temps
+	 at the expense of duplication of expressions.  */
+
+      if (CONSTANT_CLASS_P (value)
+	  || (usecount == 1
+	      && (!gimple_assign_single_p (def_stmt)
+		  || is_gimple_min_invariant (value)))
+	  || is_gimple_reg (value))
+	value = unshare_expr (value);
+      else
+	{
+	  gimple def_temp;
+	  tree vexpr = make_node (DEBUG_EXPR_DECL);
+
+	  def_temp = gimple_build_debug_bind (vexpr,
+					      unshare_expr (value),
+					      def_stmt);
+
+	  DECL_ARTIFICIAL (vexpr) = 1;
+	  TREE_TYPE (vexpr) = TREE_TYPE (value);
+	  if (DECL_P (value))
+	    DECL_MODE (vexpr) = DECL_MODE (value);
+	  else
+	    DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (value));
 
-	      if (!no_value)
-		value = gimple_assign_rhs_to_tree (def_stmt);
+	  if (gsi)
+	    gsi_insert_before (gsi, def_temp, GSI_SAME_STMT);
+	  else
+	    {
+	      gimple_stmt_iterator ngsi = gsi_for_stmt (def_stmt);
+	      gsi_insert_before (&ngsi, def_temp, GSI_SAME_STMT);
 	    }
 
-	  if (!value)
-	    no_value = true;
+	  value = vexpr;
 	}
+    }
 
-      if (no_value)
-	gimple_debug_bind_reset_value (stmt);
-      else
+  FOR_EACH_IMM_USE_STMT (stmt, imm_iter, var)
+    {
+      if (!gimple_debug_bind_p (stmt))
+	continue;
+
+      if (value)
 	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (value));
+	  /* unshare_expr is not needed here.  vexpr 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.  */
+	  SET_USE (use_p, value);
+      else
+	gimple_debug_bind_reset_value (stmt);
 
       update_stmt (stmt);
     }
 }
 
 
-/* Given a STMT to be moved to the iterator position TOBSIP in the
-   TOBB basic block, verify whether we're moving it across any of the
-   debug statements that use it.  If TOBB is NULL, then the definition
-   is understood as being removed, and TOBSIP is unused.  */
+/* Insert a DEBUG BIND stmt before STMT for each DEF referenced by
+   other DEBUG stmts, and replace uses of the DEF with the
+   newly-created debug temp.  */
 
 void
-propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
-				 const gimple_stmt_iterator *togsip)
+insert_debug_temps_for_defs (gimple_stmt_iterator *gsi)
 {
+  gimple stmt;
   ssa_op_iter op_iter;
   def_operand_p def_p;
 
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  FOR_EACH_SSA_DEF_OPERAND (def_p, def, op_iter, SSA_OP_DEF)
+  stmt = gsi_stmt (*gsi);
+
+  FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, op_iter, SSA_OP_DEF)
     {
       tree var = DEF_FROM_PTR (def_p);
 
       if (TREE_CODE (var) != SSA_NAME)
 	continue;
 
-      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+      insert_debug_temp_for_var_def (gsi, var);
     }
 }
 
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.h	2009-10-12 02:19:11.000000000 -0300
@@ -2455,6 +2455,10 @@ struct function;
 /* Every ..._DECL node gets a unique number.  */
 #define DECL_UID(NODE) (DECL_MINIMAL_CHECK (NODE)->decl_minimal.uid)
 
+/* DEBUG_EXPR_DECLs get negative UID numbers, to catch erroneous
+   uses.  */
+#define DEBUG_TEMP_UID(NODE) (-DECL_UID (TREE_CHECK ((NODE), DEBUG_EXPR_DECL)))
+
 /* These two fields describe where in the source code the declaration
    was.  If the declaration appears in several places (as for a C
    function that is declared first and then defined later), this
Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree.c	2009-10-12 02:19:11.000000000 -0300
@@ -152,6 +152,9 @@ static const char * const tree_node_kind
 static GTY(()) int next_decl_uid;
 /* Unique id for next type created.  */
 static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created.  Use negative numbers,
+   to catch erroneous uses.  */
+static GTY(()) int next_debug_decl_uid;
 
 /* Since we cannot rehash a type after it is in the table, we have to
    keep the hash code.  */
@@ -872,7 +875,10 @@ make_node_stat (enum tree_code code MEM_
 	    DECL_ALIGN (t) = 1;
 	}
       DECL_SOURCE_LOCATION (t) = input_location;
-      DECL_UID (t) = next_decl_uid++;
+      if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if (TREE_CODE (t) == LABEL_DECL)
 	LABEL_DECL_UID (t) = -1;
 
@@ -948,7 +954,10 @@ copy_node_stat (tree node MEM_STAT_DECL)
 
   if (TREE_CODE_CLASS (code) == tcc_declaration)
     {
-      DECL_UID (t) = next_decl_uid++;
+      if (code == DEBUG_EXPR_DECL)
+	DECL_UID (t) = --next_debug_decl_uid;
+      else
+	DECL_UID (t) = next_decl_uid++;
       if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
 	  && DECL_HAS_VALUE_EXPR_P (node))
 	{
Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/cfgexpand.c	2009-10-12 02:19:11.000000000 -0300
@@ -2361,6 +2361,18 @@ expand_debug_expr (tree exp)
       op1 = wrap_constant (GET_MODE_INNER (mode), op1);
       return gen_rtx_CONCAT (mode, op0, op1);
 
+    case DEBUG_EXPR_DECL:
+      op0 = DECL_RTL_IF_SET (exp);
+
+      if (op0)
+	return op0;
+
+      op0 = gen_rtx_DEBUG_EXPR (mode);
+      XTREE (op0, 0) = exp;
+      SET_DECL_RTL (exp, op0);
+
+      return op0;
+
     case VAR_DECL:
     case PARM_DECL:
     case FUNCTION_DECL:
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/var-tracking.c	2009-10-12 02:19:11.000000000 -0300
@@ -732,6 +732,7 @@ dv_is_decl_p (decl_or_value dv)
     case (int)PARM_DECL:
     case (int)RESULT_DECL:
     case (int)FUNCTION_DECL:
+    case (int)DEBUG_EXPR_DECL:
     case (int)COMPONENT_REF:
       return true;
 
@@ -2222,7 +2223,7 @@ dataflow_set_union (dataflow_set *dst, d
 
 /* Whether the value is currently being expanded.  */
 #define VALUE_RECURSED_INTO(x) \
-  (RTL_FLAG_CHECK1 ("VALUE_RECURSED_INTO", (x), VALUE)->used)
+  (RTL_FLAG_CHECK2 ("VALUE_RECURSED_INTO", (x), VALUE, DEBUG_EXPR)->used)
 /* Whether the value is in changed_variables hash table.  */
 #define VALUE_CHANGED(x) \
   (RTL_FLAG_CHECK1 ("VALUE_CHANGED", (x), VALUE)->frame_related)
@@ -4112,6 +4113,9 @@ track_expr_p (tree expr, bool need_rtl)
   rtx decl_rtl;
   tree realdecl;
 
+  if (TREE_CODE (expr) == DEBUG_EXPR_DECL)
+    return DECL_RTL_SET_P (expr);
+
   /* If EXPR is not a parameter or a variable do not track it.  */
   if (TREE_CODE (expr) != VAR_DECL && TREE_CODE (expr) != PARM_DECL)
     return 0;
@@ -6271,11 +6275,12 @@ vt_expand_loc_callback (rtx x, bitmap re
   decl_or_value dv;
   variable var;
   location_chain loc;
-  rtx result;
+  rtx result, subreg, xret;
 
-  if (GET_CODE (x) == SUBREG)
+  switch (GET_CODE (x))
     {
-      rtx subreg = SUBREG_REG (x);
+    case SUBREG:
+      subreg = SUBREG_REG (x);
 
       if (GET_CODE (SUBREG_REG (x)) != VALUE)
 	return x;
@@ -6297,22 +6302,31 @@ vt_expand_loc_callback (rtx x, bitmap re
 	result = gen_rtx_raw_SUBREG (GET_MODE (x), subreg, SUBREG_BYTE (x));
 
       return result;
-    }
 
-  if (GET_CODE (x) != VALUE)
-    return x;
+    case DEBUG_EXPR:
+      dv = dv_from_decl (XTREE (x, 0));
+      xret = NULL;
+      break;
+
+    case VALUE:
+      dv = dv_from_value (x);
+      xret = x;
+      break;
+
+    default:
+      return x;
+    }
 
   if (VALUE_RECURSED_INTO (x))
-    return x;
+    return NULL;
 
-  dv = dv_from_value (x);
   var = (variable) htab_find_with_hash (vars, dv, dv_htab_hash (dv));
 
   if (!var)
-    return x;
+    return xret;
 
   if (var->n_var_parts == 0)
-    return x;
+    return xret;
 
   gcc_assert (var->n_var_parts == 1);
 
@@ -6332,7 +6346,7 @@ vt_expand_loc_callback (rtx x, bitmap re
   if (result)
     return result;
   else
-    return x;
+    return xret;
 }
 
 /* Expand VALUEs in LOC, using VARS as well as cselib's equivalence
@@ -6382,6 +6396,9 @@ emit_note_insn_var_location (void **varp
 
   decl = dv_as_decl (var->dv);
 
+  if (TREE_CODE (decl) == DEBUG_EXPR_DECL)
+    goto clear;
+
   gcc_assert (decl);
 
   complete = true;
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/cselib.c	2009-10-12 02:19:11.000000000 -0300
@@ -585,6 +585,7 @@ rtx_equal_for_cselib_p (rtx x, rtx y)
     {
     case CONST_DOUBLE:
     case CONST_FIXED:
+    case DEBUG_EXPR:
       return 0;
 
     case LABEL_REF:
@@ -703,6 +704,10 @@ cselib_hash_rtx (rtx x, int create)
 
       return e->value;
 
+    case DEBUG_EXPR:
+      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      return hash ? hash : (unsigned int) DEBUG_EXPR;
+
     case CONST_INT:
       hash += ((unsigned) CONST_INT << 7) + INTVAL (x);
       return hash ? hash : (unsigned int) CONST_INT;
@@ -1213,6 +1218,13 @@ cselib_expand_value_rtx_1 (rtx orig, str
 	result = expand_loc (CSELIB_VAL_PTR (orig)->locs, evd, max_depth);
 	return result;
       }
+
+    case DEBUG_EXPR:
+      if (evd->callback)
+	return evd->callback (orig, evd->regs_active, max_depth,
+			      evd->callback_arg);
+      return orig;
+
     default:
       break;
     }
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-10-12 02:19:12.000000000 -0300
@@ -894,6 +894,10 @@ get_expr_operands (gimple stmt, tree *ex
       add_stmt_operand (expr_p, stmt, flags);
       return;
 
+    case DEBUG_EXPR_DECL:
+      gcc_assert (gimple_debug_bind_p (stmt));
+      return;
+
     case MISALIGNED_INDIRECT_REF:
       get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags);
       /* fall through */
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/emit-rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -2393,6 +2393,8 @@ verify_rtx_sharing (rtx orig, rtx insn)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2593,6 +2595,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2712,6 +2716,8 @@ repeat:
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -2783,6 +2789,8 @@ set_used_flags (rtx x)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
Index: gcc/rtl.c
===================================================================
--- gcc/rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -232,6 +232,8 @@ copy_rtx (rtx orig)
   switch (code)
     {
     case REG:
+    case DEBUG_EXPR:
+    case VALUE:
     case CONST_INT:
     case CONST_DOUBLE:
     case CONST_FIXED:
@@ -381,6 +383,7 @@ rtx_equal_p_cb (const_rtx x, const_rtx y
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
@@ -496,6 +499,7 @@ rtx_equal_p (const_rtx x, const_rtx y)
     case SYMBOL_REF:
       return XSTR (x, 0) == XSTR (y, 0);
 
+    case DEBUG_EXPR:
     case VALUE:
     case SCRATCH:
     case CONST_DOUBLE:
Index: gcc/print-rtl.c
===================================================================
--- gcc/print-rtl.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/print-rtl.c	2009-10-12 02:19:12.000000000 -0300
@@ -318,6 +318,12 @@ print_rtx (const_rtx in_rtx)
 	    dump_addr (outfile, "/", (void*)val);
 #endif
 	  }
+	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
+	  {
+#ifndef GENERATOR_FILE
+	    fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
+#endif
+	  }
 	break;
 
       case 'e':
Index: gcc/sched-vis.c
===================================================================
--- gcc/sched-vis.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/sched-vis.c	2009-10-12 02:19:12.000000000 -0300
@@ -521,6 +521,10 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, t);
       cur = safe_concat (buf, cur, "]");
       break;
+    case DEBUG_EXPR:
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      cur = safe_concat (buf, cur, t);
+      break;
     default:
       print_exp (t, x, verbose);
       cur = safe_concat (buf, cur, t);
@@ -670,11 +674,18 @@ print_insn (char *buf, const_rtx x, int 
 	if (DECL_P (INSN_VAR_LOCATION_DECL (insn)))
 	  {
 	    tree id = DECL_NAME (INSN_VAR_LOCATION_DECL (insn));
+	    char idbuf[32];
 	    if (id)
 	      name = IDENTIFIER_POINTER (id);
+	    else if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn))
+		     == DEBUG_EXPR_DECL)
+	      {
+		sprintf (idbuf, "D#%i",
+			 DEBUG_TEMP_UID (INSN_VAR_LOCATION_DECL (insn)));
+		name = idbuf;
+	      }
 	    else
 	      {
-		char idbuf[32];
 		sprintf (idbuf, "D.%i",
 			 DECL_UID (INSN_VAR_LOCATION_DECL (insn)));
 		name = idbuf;
Index: gcc/tree-dump.c
===================================================================
--- gcc/tree-dump.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-dump.c	2009-10-12 02:19:12.000000000 -0300
@@ -511,6 +511,10 @@ dequeue_and_dump (dump_info_p di)
       dump_child ("cnst", DECL_INITIAL (t));
       break;
 
+    case DEBUG_EXPR_DECL:
+      dump_int (di, "-uid", DEBUG_TEMP_UID (t));
+      /* Fall through.  */
+
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
Index: gcc/tree-pretty-print.c
===================================================================
--- gcc/tree-pretty-print.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-pretty-print.c	2009-10-12 02:19:12.000000000 -0300
@@ -183,6 +183,8 @@ dump_decl_name (pretty_printer *buffer, 
     {
       if (TREE_CODE (node) == LABEL_DECL && LABEL_DECL_UID (node) != -1)
         pp_printf (buffer, "L.%d", (int) LABEL_DECL_UID (node));
+      else if (TREE_CODE (node) == DEBUG_EXPR_DECL)
+	pp_printf (buffer, "D#%i", DEBUG_TEMP_UID (node));
       else
 	{
 	  char c = TREE_CODE (node) == CONST_DECL ? 'C' : 'D';
@@ -1051,6 +1053,7 @@ dump_generic_node (pretty_printer *buffe
     case VAR_DECL:
     case PARM_DECL:
     case FIELD_DECL:
+    case DEBUG_EXPR_DECL:
     case NAMESPACE_DECL:
       dump_decl_name (buffer, node, flags);
       break;
Index: gcc/gimple-iterator.c
===================================================================
--- gcc/gimple-iterator.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/gimple-iterator.c	2009-10-12 02:19:12.000000000 -0300
@@ -358,7 +358,8 @@ gsi_split_seq_before (gimple_stmt_iterat
 
 /* Replace the statement pointed-to by GSI to STMT.  If UPDATE_EH_INFO
    is true, the exception handling information of the original
-   statement is moved to the new statement.  */
+   statement is moved to the new statement.  Assignments must only be
+   replaced with assignments to the same LHS.  */
 
 void
 gsi_replace (gimple_stmt_iterator *gsi, gimple stmt, bool update_eh_info)
@@ -368,6 +369,9 @@ gsi_replace (gimple_stmt_iterator *gsi, 
   if (stmt == orig_stmt)
     return;
 
+  gcc_assert (!gimple_has_lhs (orig_stmt)
+	      || gimple_get_lhs (orig_stmt) == gimple_get_lhs (stmt));
+
   gimple_set_location (stmt, gimple_location (orig_stmt));
   gimple_set_bb (stmt, gsi_bb (*gsi));
 
@@ -470,6 +474,8 @@ gsi_remove (gimple_stmt_iterator *i, boo
   gimple_seq_node cur, next, prev;
   gimple stmt = gsi_stmt (*i);
 
+  insert_debug_temps_for_defs (i);
+
   /* Free all the data flow information for STMT.  */
   gimple_set_bb (stmt, NULL);
   delink_stmt_imm_use (stmt);
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-10-12 02:19:12.000000000 -0300
@@ -764,6 +764,7 @@ rewrite_reciprocal (gimple_stmt_iterator
   gimple stmt, stmt1, stmt2;
   tree var, name, lhs, type;
   tree real_one;
+  gimple_stmt_iterator gsi;
 
   stmt = gsi_stmt (*bsi);
   lhs = gimple_assign_lhs (stmt);
@@ -798,8 +799,9 @@ rewrite_reciprocal (gimple_stmt_iterator
   /* Replace division stmt with reciprocal and multiply stmts.
      The multiply stmt is not invariant, so update iterator
      and avoid rescanning.  */
-  gsi_replace (bsi, stmt1, true);
-  gsi_insert_after (bsi, stmt2, GSI_NEW_STMT);
+  gsi = *bsi;
+  gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+  gsi_replace (&gsi, stmt2, true);
 
   /* Continue processing with invariant reciprocal statement.  */
   return stmt1;
@@ -858,6 +860,8 @@ rewrite_bittest (gimple_stmt_iterator *b
   if (outermost_invariant_loop (b, loop_containing_stmt (stmt1)) != NULL
       && outermost_invariant_loop (a, loop_containing_stmt (stmt1)) == NULL)
     {
+      gimple_stmt_iterator rsi;
+
       /* 1 << B */
       var = create_tmp_var (TREE_TYPE (a), "shifttmp");
       add_referenced_var (var);
@@ -878,9 +882,14 @@ rewrite_bittest (gimple_stmt_iterator *b
       SET_USE (use, name);
       gimple_cond_set_rhs (use_stmt, build_int_cst_type (TREE_TYPE (name), 0));
 
-      gsi_insert_before (bsi, stmt1, GSI_SAME_STMT);
-      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
-      gsi_replace (bsi, stmt2, true);
+      /* Don't use gsi_replace here, none of the new assignments sets
+	 the variable originally set in stmt.  Move bsi to stmt1, and
+	 then remove the original stmt, so that we get a chance to
+	 retain debug info for it.  */
+      rsi = *bsi;
+      gsi_insert_before (bsi, stmt1, GSI_NEW_STMT);
+      gsi_insert_before (&rsi, stmt2, GSI_SAME_STMT);
+      gsi_remove (&rsi, true);
 
       return stmt1;
     }
@@ -1060,7 +1069,6 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      propagate_defs_into_debug_stmts (gsi_stmt (bsi), NULL, NULL);
       gsi_remove (&bsi, false);
     }
 }
Index: gcc/tree-ssa-reassoc.c
===================================================================
--- gcc/tree-ssa-reassoc.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-10-12 02:19:12.000000000 -0300
@@ -1405,7 +1405,6 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1451,6 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  propagate_defs_into_debug_stmts (binrhs, gimple_bb (stmt), &gsinow);
   gsi_move_before (&gsirhs, &gsinow);
 
   gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs));
Index: gcc/tree-ssa-sink.c
===================================================================
--- gcc/tree-ssa-sink.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-10-12 02:19:12.000000000 -0300
@@ -385,9 +385,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_after_labels (commondom);
 
-      if (debug_stmts)
-	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
-
       return true;
     }
 
@@ -406,8 +403,6 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
       return true;
     }
 
@@ -441,8 +436,6 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
-
   return true;
 }
 
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-10-12 02:19:12.000000000 -0300
@@ -939,7 +939,6 @@ forward_propagate_addr_expr (tree name, 
   gimple use_stmt;
   bool all = true;
   bool single_use_p = has_single_use (name);
-  bool debug = false;
 
   FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
     {
@@ -950,9 +949,7 @@ forward_propagate_addr_expr (tree name, 
 	 there is nothing we can do.  */
       if (gimple_code (use_stmt) != GIMPLE_ASSIGN)
 	{
-	  if (is_gimple_debug (use_stmt))
-	    debug = true;
-	  else
+	  if (!is_gimple_debug (use_stmt))
 	    all = false;
 	  continue;
 	}
@@ -995,9 +992,6 @@ forward_propagate_addr_expr (tree name, 
 	}
     }
 
-  if (all && debug)
-    propagate_var_def_into_debug_stmts (name, NULL, NULL);
-
   return all;
 }
 
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssanames.c	2009-10-12 02:19:13.000000000 -0300
@@ -206,7 +206,7 @@ release_ssa_name (tree var)
       use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
 
       if (MAY_HAVE_DEBUG_STMTS)
-	propagate_var_def_into_debug_stmts (var, NULL, NULL);
+	insert_debug_temp_for_var_def (NULL, var);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-flow.h	2009-10-12 02:19:13.000000000 -0300
@@ -637,10 +637,8 @@ typedef bool (*walk_use_def_chains_fn) (
 
 extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
 
-void propagate_defs_into_debug_stmts (gimple, basic_block,
-				      const gimple_stmt_iterator *);
-void propagate_var_def_into_debug_stmts (tree, basic_block,
-					 const gimple_stmt_iterator *);
+void insert_debug_temps_for_defs (gimple_stmt_iterator *);
+void insert_debug_temp_for_var_def (gimple_stmt_iterator *, tree);
 void release_defs_bitset (bitmap toremove);
 
 /* In tree-into-ssa.c  */
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-10-12 02:03:57.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-10-12 02:19:13.000000000 -0300
@@ -325,7 +325,13 @@ mark_stmt_if_obviously_necessary (gimple
       break;
 
     case GIMPLE_DEBUG:
-      mark_stmt_necessary (stmt, false);
+      /* Debug temps without a value are not useful.  ??? If we could
+	 easily locate the debug temp bind stmt for a use thereof,
+	 would could refrain from marking all debug temps here, and
+	 mark them only if they're used.  */
+      if (gimple_debug_bind_has_value_p (stmt)
+	  || TREE_CODE (gimple_debug_bind_get_var (stmt)) != DEBUG_EXPR_DECL)
+	mark_stmt_necessary (stmt, false);
       return;
 
     case GIMPLE_GOTO:
@@ -1071,7 +1077,7 @@ eliminate_unnecessary_stmts (void)
 {
   bool something_changed = false;
   basic_block bb;
-  gimple_stmt_iterator gsi;
+  gimple_stmt_iterator gsi, psi;
   gimple stmt;
   tree call;
   VEC (basic_block, heap) *h;
@@ -1111,10 +1117,13 @@ eliminate_unnecessary_stmts (void)
       bb = VEC_pop (basic_block, h);
 
       /* Remove dead statements.  */
-      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi = psi)
 	{
 	  stmt = gsi_stmt (gsi);
 
+	  psi = gsi;
+	  gsi_prev (&psi);
+
 	  stats.total++;
 
 	  /* If GSI is not necessary then remove it.  */
@@ -1122,14 +1131,6 @@ eliminate_unnecessary_stmts (void)
 	    {
 	      remove_dead_stmt (&gsi, bb);
 	      something_changed = true;
-
-	      /* If stmt was the last stmt in the block, we want to
-		 move gsi to the stmt that became the last stmt, but
-		 gsi_prev would crash.  */
-	      if (gsi_end_p (gsi))
-		gsi = gsi_last_bb (bb);
-	      else
-		gsi_prev (&gsi);
 	    }
 	  else if (is_gimple_call (stmt))
 	    {
@@ -1159,10 +1160,7 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_prev (&gsi);
 	    }
-	  else
-	    gsi_prev (&gsi);
 	}
     }
 
Index: gcc/testsuite/gcc.dg/guality/pr41447-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/guality/pr41447-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,25 @@
+/* { dg-do run { xfail *-*-* } } */
+/* { dg-options "-g -O2" } */
+
+#include "guality.h"
+
+int a;
+
+int foo()
+{
+  int tmp = a;
+  int tmp2 = a;
+  int tmp3;
+  int res;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  a = 0;
+  tmp3 = tmp2;
+  GUALCHKVAL (a);
+  GUALCHKVAL (tmp);
+  GUALCHKVAL (tmp2);
+  GUALCHKVAL (tmp3);
+  res = tmp - tmp2 + 1;
+  return res;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41264-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41264-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+
+typedef unsigned int hashval_t;
+static hashval_t __attribute__((always_inline))
+iterative_hash_host_wide_int (long val, hashval_t val2)
+{
+  hashval_t a = (hashval_t) val;
+  int zero = 0;
+  hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 8 + zero));
+
+  a -= b; a -= val2; a ^= (val2>>13);
+  b -= val2; b -= a; b ^= (a<< 8);
+  val2 -= a; val2 -= b; val2 ^= ((b&0xffffffff)>>13);
+  a -= b; a -= val2; a ^= ((val2&0xffffffff)>>12);
+  b -= val2; b -= a; b = (b ^ (a<<16)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>> 5)) & 0xffffffff;
+  a -= b; a -= val2; a = (a ^ (val2>> 3)) & 0xffffffff;
+  b -= val2; b -= a; b = (b ^ (a<<10)) & 0xffffffff;
+  val2 -= a; val2 -= b; val2 = (val2 ^ (b>>15)) & 0xffffffff;
+  return val2;
+}
+
+hashval_t
+bla (int nunits, int mode)
+{
+  hashval_t hashcode = 0;
+
+
+  hashcode = iterative_hash_host_wide_int (14, hashcode);
+  hashcode = iterative_hash_host_wide_int (nunits, hashcode);
+  hashcode = iterative_hash_host_wide_int (mode, hashcode);
+  if (nunits)
+    return 0;
+  else
+    return hashcode;
+}
Index: gcc/testsuite/gcc.dg/debug/pr41343-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/debug/pr41343-1.c	2009-10-12 02:19:13.000000000 -0300
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#define X(new,old) int i ## new = i ## old + i ## old;
+#define Y(pfx) X(pfx ## 1, pfx) \
+  X(pfx ## 2, pfx ## 1) \
+  X(pfx ## 3, pfx ## 2) \
+  X(pfx ## 4, pfx ## 3) \
+  X(pfx ## 5, pfx ## 4) \
+  X(pfx ## 6, pfx ## 5) \
+  X(pfx ## 7, pfx ## 6) \
+  X(pfx ## 8, pfx ## 7) \
+  X(pfx ## 9, pfx ## 8)
+
+void foo (int i1)
+{
+  Y(1)
+  Y(11)
+  Y(111)
+  asm ("" : : "X" (i1));
+}

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-12 19:01                         ` Alexandre Oliva
@ 2009-10-13  6:02                           ` Eric Botcazou
  2009-10-13  6:41                             ` Jakub Jelinek
  2009-10-13 21:01                           ` Alexandre Oliva
  1 sibling, 1 reply; 25+ messages in thread
From: Eric Botcazou @ 2009-10-13  6:02 UTC (permalink / raw)
  To: Alexandre Oliva; +Cc: gcc-patches, Richard Guenther, jakub

> Thanks, here's what I'm installing.

This again broke bootstrap with RTL checking (on x86-64):

/red.a/gnatmail-x/build-red/obj/./gcc/xgcc -B/red.a/gnatmail-x/build-red/obj/./gcc/ -B/usr/gnat/x86_64-pc-linux-gnu/bin/ -B/usr/gnat/x86_64-pc-linux-gnu/lib/ -isystem /usr/gnat/x86_64-pc-linux-gnu/include -isystem /usr/gnat/x86_64-pc-linux-gnu/sys-include    -g -O2 -O2  -g -O2 -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include  -fPIC -g -DHAVE_GTHR_DEFAULT -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED   -I. -I. -I../.././gcc -I/red.a/gnatmail-x/build-red/src/libgcc -I/red.a/gnatmail-x/build-red/src/libgcc/. -I/red.a/gnatmail-x/build-red/src/libgcc/../gcc -I/red.a/gnatmail-x/build-red/src/libgcc/../include -I/red.a/gnatmail-x/build-red/src/libgcc/config/libbid -DENABLE_DECIMAL_BID_FORMAT -DHAVE_CC_TLS -DUSE_TLS -o 
_mulsc3.o -MT _mulsc3.o -MD -MP -MF 
_mulsc3.dep -DL_mulsc3 -c /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c 
\
  -fvisibility=hidden -DHIDE_EXPORTS
/red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c: In 
function '__mulsc3':
/red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c:1826:1: internal 
compiler error: RTL check: expected elt 0 type 't', have '0' (rtx debug_expr) 
in expand_debug_expr, at cfgexpand.c:2371
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:mailto:report@adacore.com> for instructions.
make[3]: *** [_mulsc3.o] Error 1

Please consider testing your patches with --enable-checking=yes,rtl.

-- 
Eric Botcazou

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-13  6:02                           ` Eric Botcazou
@ 2009-10-13  6:41                             ` Jakub Jelinek
  2009-10-13  9:38                               ` Richard Guenther
  0 siblings, 1 reply; 25+ messages in thread
From: Jakub Jelinek @ 2009-10-13  6:41 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: Alexandre Oliva, gcc-patches, Richard Guenther

On Tue, Oct 13, 2009 at 07:37:53AM +0200, Eric Botcazou wrote:
> > Thanks, here's what I'm installing.
> 
> This again broke bootstrap with RTL checking (on x86-64):
> 
> /red.a/gnatmail-x/build-red/obj/./gcc/xgcc -B/red.a/gnatmail-x/build-red/obj/./gcc/ -B/usr/gnat/x86_64-pc-linux-gnu/bin/ -B/usr/gnat/x86_64-pc-linux-gnu/lib/ -isystem /usr/gnat/x86_64-pc-linux-gnu/include -isystem /usr/gnat/x86_64-pc-linux-gnu/sys-include    -g -O2 -O2  -g -O2 -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include  -fPIC -g -DHAVE_GTHR_DEFAULT -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED   -I. -I. -I../.././gcc -I/red.a/gnatmail-x/build-red/src/libgcc -I/red.a/gnatmail-x/build-red/src/libgcc/. -I/red.a/gnatmail-x/build-red/src/libgcc/../gcc -I/red.a/gnatmail-x/build-red/src/libgcc/../include -I/red.a/gnatmail-x/build-red/src/libgcc/config/libbid -DENABLE_DECIMAL_BID_FORMAT -DHAVE_CC_TLS -DUSE_TLS -o 
> _mulsc3.o -MT _mulsc3.o -MD -MP -MF 
> _mulsc3.dep -DL_mulsc3 -c /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c 
> \
>   -fvisibility=hidden -DHIDE_EXPORTS
> /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c: In 
> function '__mulsc3':
> /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c:1826:1: internal 
> compiler error: RTL check: expected elt 0 type 't', have '0' (rtx debug_expr) 
> in expand_debug_expr, at cfgexpand.c:2371
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <URL:mailto:report@adacore.com> for instructions.
> make[3]: *** [_mulsc3.o] Error 1
> 
> Please consider testing your patches with --enable-checking=yes,rtl.

Here is a fix, so far completely untested.

We could either use X0TREE macros instead of XTREE, but I'd say it is an
implementation detail that DEBUG_EXPR uses 0, not t, so DEBUG_EXPR users
shouldn't know about it.  This patch instead introduces a new macro.

2009-10-13  Jakub Jelinek  <jakub@redhat.com>

	* rtl.h (DEBUG_EXPR_TREE_DECL): Define.
	* sched-vis.c (print_value): Use it.
	* cselib.c (cselib_hash_rtx): Likewise.
	* print-rtl.c (print_rtx): Likewise.
	* cfgexpand.c (expand_debug_rtx): Likewise.
	* var-tracking.c (vt_expand_loc_callback): Likewise.

--- gcc/rtl.h.jj	2009-10-05 21:47:26.000000000 +0200
+++ gcc/rtl.h	2009-10-13 08:07:46.000000000 +0200
@@ -930,6 +930,9 @@ extern const char * const reg_note_name[
 #define NOTE_DURING_CALL_P(RTX)				\
   (RTL_FLAG_CHECK1("NOTE_VAR_LOCATION_DURING_CALL_P", (RTX), NOTE)->call)
 
+/* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX.  */
+#define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR)
+
 /* Possible initialization status of a variable.   When requested
    by the user, this information is tracked and recorded in the DWARF
    debug information, along with the variable's location.  */
--- gcc/sched-vis.c.jj	2009-10-13 07:59:00.000000000 +0200
+++ gcc/sched-vis.c	2009-10-13 08:11:10.000000000 +0200
@@ -522,7 +522,7 @@ print_value (char *buf, const_rtx x, int
       cur = safe_concat (buf, cur, "]");
       break;
     case DEBUG_EXPR:
-      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
+      sprintf (t, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
       cur = safe_concat (buf, cur, t);
       break;
     default:
--- gcc/cselib.c.jj	2009-10-13 07:59:00.000000000 +0200
+++ gcc/cselib.c	2009-10-13 08:09:57.000000000 +0200
@@ -705,7 +705,8 @@ cselib_hash_rtx (rtx x, int create)
       return e->value;
 
     case DEBUG_EXPR:
-      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
+      hash += ((unsigned) DEBUG_EXPR << 7)
+	      + DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x));
       return hash ? hash : (unsigned int) DEBUG_EXPR;
 
     case CONST_INT:
--- gcc/print-rtl.c.jj	2009-10-13 07:59:00.000000000 +0200
+++ gcc/print-rtl.c	2009-10-13 08:10:44.000000000 +0200
@@ -321,7 +321,8 @@ print_rtx (const_rtx in_rtx)
 	else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
 	  {
 #ifndef GENERATOR_FILE
-	    fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
+	    fprintf (outfile, " D#%i",
+		     DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
 #endif
 	  }
 	break;
--- gcc/cfgexpand.c.jj	2009-10-13 07:59:00.000000000 +0200
+++ gcc/cfgexpand.c	2009-10-13 08:08:10.000000000 +0200
@@ -2368,7 +2368,7 @@ expand_debug_expr (tree exp)
 	return op0;
 
       op0 = gen_rtx_DEBUG_EXPR (mode);
-      XTREE (op0, 0) = exp;
+      DEBUG_EXPR_TREE_DECL (op0) = exp;
       SET_DECL_RTL (exp, op0);
 
       return op0;
--- gcc/var-tracking.c.jj	2009-10-13 07:59:00.000000000 +0200
+++ gcc/var-tracking.c	2009-10-13 08:09:03.000000000 +0200
@@ -6304,7 +6304,7 @@ vt_expand_loc_callback (rtx x, bitmap re
       return result;
 
     case DEBUG_EXPR:
-      dv = dv_from_decl (XTREE (x, 0));
+      dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
       xret = NULL;
       break;
 


	Jakub

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-13  6:41                             ` Jakub Jelinek
@ 2009-10-13  9:38                               ` Richard Guenther
  0 siblings, 0 replies; 25+ messages in thread
From: Richard Guenther @ 2009-10-13  9:38 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: Eric Botcazou, Alexandre Oliva, gcc-patches

On Tue, Oct 13, 2009 at 8:15 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Tue, Oct 13, 2009 at 07:37:53AM +0200, Eric Botcazou wrote:
>> > Thanks, here's what I'm installing.
>>
>> This again broke bootstrap with RTL checking (on x86-64):
>>
>> /red.a/gnatmail-x/build-red/obj/./gcc/xgcc -B/red.a/gnatmail-x/build-red/obj/./gcc/ -B/usr/gnat/x86_64-pc-linux-gnu/bin/ -B/usr/gnat/x86_64-pc-linux-gnu/lib/ -isystem /usr/gnat/x86_64-pc-linux-gnu/include -isystem /usr/gnat/x86_64-pc-linux-gnu/sys-include    -g -O2 -O2  -g -O2 -DIN_GCC   -W -Wall -Wwrite-strings -Wcast-qual -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition  -isystem ./include  -fPIC -g -DHAVE_GTHR_DEFAULT -DIN_LIBGCC2 -D__GCC_FLOAT_NOT_NEEDED   -I. -I. -I../.././gcc -I/red.a/gnatmail-x/build-red/src/libgcc -I/red.a/gnatmail-x/build-red/src/libgcc/. -I/red.a/gnatmail-x/build-red/src/libgcc/../gcc -I/red.a/gnatmail-x/build-red/src/libgcc/../include -I/red.a/gnatmail-x/build-red/src/libgcc/config/libbid -DENABLE_DECIMAL_BID_FORMAT -DHAVE_CC_TLS -DUSE_TLS -o
>> _mulsc3.o -MT _mulsc3.o -MD -MP -MF
>> _mulsc3.dep -DL_mulsc3 -c /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c
>> \
>>   -fvisibility=hidden -DHIDE_EXPORTS
>> /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c: In
>> function '__mulsc3':
>> /red.a/gnatmail-x/build-red/src/libgcc/../gcc/libgcc2.c:1826:1: internal
>> compiler error: RTL check: expected elt 0 type 't', have '0' (rtx debug_expr)
>> in expand_debug_expr, at cfgexpand.c:2371
>> Please submit a full bug report,
>> with preprocessed source if appropriate.
>> See <URL:mailto:report@adacore.com> for instructions.
>> make[3]: *** [_mulsc3.o] Error 1
>>
>> Please consider testing your patches with --enable-checking=yes,rtl.
>
> Here is a fix, so far completely untested.
>
> We could either use X0TREE macros instead of XTREE, but I'd say it is an
> implementation detail that DEBUG_EXPR uses 0, not t, so DEBUG_EXPR users
> shouldn't know about it.  This patch instead introduces a new macro.

Looks good to me.  Ok if it passes bootstrap & testing w/
RTL checking enabled.

Thanks,
Richard.

> 2009-10-13  Jakub Jelinek  <jakub@redhat.com>
>
>        * rtl.h (DEBUG_EXPR_TREE_DECL): Define.
>        * sched-vis.c (print_value): Use it.
>        * cselib.c (cselib_hash_rtx): Likewise.
>        * print-rtl.c (print_rtx): Likewise.
>        * cfgexpand.c (expand_debug_rtx): Likewise.
>        * var-tracking.c (vt_expand_loc_callback): Likewise.
>
> --- gcc/rtl.h.jj        2009-10-05 21:47:26.000000000 +0200
> +++ gcc/rtl.h   2009-10-13 08:07:46.000000000 +0200
> @@ -930,6 +930,9 @@ extern const char * const reg_note_name[
>  #define NOTE_DURING_CALL_P(RTX)                                \
>   (RTL_FLAG_CHECK1("NOTE_VAR_LOCATION_DURING_CALL_P", (RTX), NOTE)->call)
>
> +/* DEBUG_EXPR_DECL corresponding to a DEBUG_EXPR RTX.  */
> +#define DEBUG_EXPR_TREE_DECL(RTX) XCTREE (RTX, 0, DEBUG_EXPR)
> +
>  /* Possible initialization status of a variable.   When requested
>    by the user, this information is tracked and recorded in the DWARF
>    debug information, along with the variable's location.  */
> --- gcc/sched-vis.c.jj  2009-10-13 07:59:00.000000000 +0200
> +++ gcc/sched-vis.c     2009-10-13 08:11:10.000000000 +0200
> @@ -522,7 +522,7 @@ print_value (char *buf, const_rtx x, int
>       cur = safe_concat (buf, cur, "]");
>       break;
>     case DEBUG_EXPR:
> -      sprintf (t, "D#%i", DEBUG_TEMP_UID (XTREE (x, 0)));
> +      sprintf (t, "D#%i", DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x)));
>       cur = safe_concat (buf, cur, t);
>       break;
>     default:
> --- gcc/cselib.c.jj     2009-10-13 07:59:00.000000000 +0200
> +++ gcc/cselib.c        2009-10-13 08:09:57.000000000 +0200
> @@ -705,7 +705,8 @@ cselib_hash_rtx (rtx x, int create)
>       return e->value;
>
>     case DEBUG_EXPR:
> -      hash += ((unsigned) DEBUG_EXPR << 7) + DEBUG_TEMP_UID (XTREE (x, 0));
> +      hash += ((unsigned) DEBUG_EXPR << 7)
> +             + DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (x));
>       return hash ? hash : (unsigned int) DEBUG_EXPR;
>
>     case CONST_INT:
> --- gcc/print-rtl.c.jj  2009-10-13 07:59:00.000000000 +0200
> +++ gcc/print-rtl.c     2009-10-13 08:10:44.000000000 +0200
> @@ -321,7 +321,8 @@ print_rtx (const_rtx in_rtx)
>        else if (i == 0 && GET_CODE (in_rtx) == DEBUG_EXPR)
>          {
>  #ifndef GENERATOR_FILE
> -           fprintf (outfile, " D#%i", DEBUG_TEMP_UID (XTREE (in_rtx, 0)));
> +           fprintf (outfile, " D#%i",
> +                    DEBUG_TEMP_UID (DEBUG_EXPR_TREE_DECL (in_rtx)));
>  #endif
>          }
>        break;
> --- gcc/cfgexpand.c.jj  2009-10-13 07:59:00.000000000 +0200
> +++ gcc/cfgexpand.c     2009-10-13 08:08:10.000000000 +0200
> @@ -2368,7 +2368,7 @@ expand_debug_expr (tree exp)
>        return op0;
>
>       op0 = gen_rtx_DEBUG_EXPR (mode);
> -      XTREE (op0, 0) = exp;
> +      DEBUG_EXPR_TREE_DECL (op0) = exp;
>       SET_DECL_RTL (exp, op0);
>
>       return op0;
> --- gcc/var-tracking.c.jj       2009-10-13 07:59:00.000000000 +0200
> +++ gcc/var-tracking.c  2009-10-13 08:09:03.000000000 +0200
> @@ -6304,7 +6304,7 @@ vt_expand_loc_callback (rtx x, bitmap re
>       return result;
>
>     case DEBUG_EXPR:
> -      dv = dv_from_decl (XTREE (x, 0));
> +      dv = dv_from_decl (DEBUG_EXPR_TREE_DECL (x));
>       xret = NULL;
>       break;
>
>
>
>        Jakub
>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PR debug/41343] introduce debug expr temps
  2009-10-12 19:01                         ` Alexandre Oliva
  2009-10-13  6:02                           ` Eric Botcazou
@ 2009-10-13 21:01                           ` Alexandre Oliva
  1 sibling, 0 replies; 25+ messages in thread
From: Alexandre Oliva @ 2009-10-13 21:01 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, jakub

[-- Attachment #1: Type: text/plain, Size: 465 bytes --]

On Oct 12, 2009, Alexandre Oliva <aoliva@redhat.com> wrote:

> Thanks, here's what I'm installing.

And here's some low-hanging memory savings...  I failed to specify what
kind of decl struct DEBUG_EXPR_DECL was to use, so it's using the larger
non-common one.

This patch shrinks it to decl_with_rtl.  It shouldn't be too hard to get
it to use an even smaller struct, but I'm frying bigger fish right now.

I'll check it in as obvious tonight, if nobody objects.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: vta-temp-values-pr41343-size.patch --]
[-- Type: text/x-diff, Size: 1011 bytes --]

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

	PR debug/41343
	PR debug/41447
	PR debug/41264
	PR debug/41338
	* tree.c (tree_node_structure_for_code): DEBUG_EXPR_DECL uses
	decl with rtl.
	(tree_code_size): Likewise.

Index: gcc/tree.c
===================================================================
--- gcc/tree.c.orig	2009-10-13 04:50:58.000000000 -0300
+++ gcc/tree.c	2009-10-13 04:52:12.000000000 -0300
@@ -287,6 +287,8 @@ tree_node_structure_for_code (enum tree_
 	    return TS_LABEL_DECL;
 	  case RESULT_DECL:
 	    return TS_RESULT_DECL;
+	  case DEBUG_EXPR_DECL:
+	    return TS_DECL_WRTL;
 	  case CONST_DECL:
 	    return TS_CONST_DECL;
 	  case TYPE_DECL:
@@ -670,6 +672,8 @@ tree_code_size (enum tree_code code)
 	    return sizeof (struct tree_type_decl);
 	  case FUNCTION_DECL:
 	    return sizeof (struct tree_function_decl);
+	  case DEBUG_EXPR_DECL:
+	    return sizeof (struct tree_decl_with_rtl);
 	  default:
 	    return sizeof (struct tree_decl_non_common);
 	  }

[-- Attachment #3: Type: text/plain, Size: 257 bytes --]


-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2009-10-13 20:59 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-22 19:51 [PR debug/41343] introduce debug expr temps Alexandre Oliva
2009-09-23  8:42 ` Richard Guenther
2009-09-23 11:54   ` Richard Guenther
2009-09-23 12:02     ` Richard Guenther
2009-09-30  8:24       ` Alexandre Oliva
2009-09-30  9:54         ` Richard Guenther
2009-10-02  6:06           ` Alexandre Oliva
2009-10-02  7:10   ` Alexandre Oliva
2009-10-03 15:02     ` Richard Guenther
2009-10-06  6:43       ` Alexandre Oliva
2009-10-06 10:30         ` Richard Guenther
2009-10-07  8:35           ` Alexandre Oliva
2009-10-07 10:24             ` Richard Guenther
2009-10-08 19:48               ` Alexandre Oliva
2009-10-09  7:48             ` Alexandre Oliva
2009-10-09 11:29               ` Richard Guenther
2009-10-11 13:05                 ` Alexandre Oliva
2009-10-11 14:26                   ` Richard Guenther
2009-10-12  6:36                     ` Alexandre Oliva
2009-10-12  8:58                       ` Richard Guenther
2009-10-12 19:01                         ` Alexandre Oliva
2009-10-13  6:02                           ` Eric Botcazou
2009-10-13  6:41                             ` Jakub Jelinek
2009-10-13  9:38                               ` Richard Guenther
2009-10-13 21:01                           ` Alexandre Oliva

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).