This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[vta] assorted VTA changes


This patch implements (AFAICT) all of the changes you've
requested/suggested, as well as a few improvements I came up with on my
own.

There might be some testsuite regressions caused by it.  I can't look
into them right now, unfortunately.  I'll be on the road July 13-22,
with limited internet access and computer time.  I have noticed that a
mostly-trivial backport of this patch to the vta4.4 branch causes
bootstrap failures.  I started looking at them, but no obvious solution
came forth.

I hope that, during my absence, I will manage to implement the
var-tracking.c changes that I have in mind to reduce memory consumption
and improve tracking of variables.

The latter has to do with keeping track across basic blocks of gimple
reg variables that get assigned to stack slots.  This requires some
smarts to recognize MEMs of equivalent values as equivalent as well.

For the former, my plan is to implement chains of hash tables, to avoid
the excessive growth of variable hash tables that causes lots of memory
and compute time to be wasted propagating values that are not reused.

The thinking is that, where we currently have in and out hash tables per
block, and sharing of identical hash tables, we'd enable out hash tables
to partially override in hash tables, and in hash tables to partially
override an out set from another block.

Look up of decl_or_values (DVs) would work like this:

  look up in the first variable hash table in the chain
  if we found it, that's what we return

  look up in the first mask hash table
  if we found it, we know the DV was removed from the first hash table,
  so return ânot foundâ

  otherwise, proceed to the next pair of hash tables in the chain

Adding basic block identifiers and reference counting to the pairs of
hash tables, we can speed up merges at confluence points: there's no
need to mess with contents of common ancestor's hash tables, only with
the overriders.

I'm thinking of using sizes of incoming hash tables, mask tables and
back-edge information to decide whether or not to duplicate a hash table
for speed or chain an overrider to it for space savings.

Anyhow...  That's something I'm yet to implement.  What I have now, and
that I'm installing in the VTA branch, is this:

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

	* cfgexpand.c (expand_debug_expr): Enclose CONST_STRINGs in MEMs.
	(expand_debug_locations): Use NULL trees for no bind value.
	(expand_gimple_basic_block): Likewise.
	* gimple.h (GIMPLE_DEBUG_BIND): New.  Replaces all uses of
	VAR_DEBUG_VALUE tree code.
	(GIMPLE_DEBUG_BIND_NOVALUE): New.
	(gimple_debug_bind_reset_value): New.  Replace all assignments to
	VAR_DEBUG_VALUE_VALUE from VAR_DEBUG_VALUE_NOVALUE with it.
	(gimple_debug_bind_has_value_p): New.  Replace all compares of
	VAR_DEBUG_VALUE_VALUE and VAR_DEBUG_VALUE_NOVALUE with it.
	(gsi_next_nondebug, gsi_prev_nondebug): Embrace do/while body.
	* tree-if-conv.c (tree_if_convert_stmt): Adjust.
	* tree-inline.c: Adjust.
	(copy_debug_stmt, copy_debug_stmts): Add comments.
	(insert_init_debug_bind): Use the var returned by
	target_for_debug_bind, renamed from...
	* tree-into-ssa.c (var_debug_value_for_decl): ... this.
	(insert_phi_nodes_for, rewrite_stmt): Likewise.
	(check_and_update_debug_stmt_1): Removed.
	(check_and_update_debug_stmt): Removed.  Drop all callers.
	(maybe_replace_use_in_debug_insn): Renamed to...
	(maybe_replace_use_in_debug_stmt): ... this.  Adjust all callers.
	Don't keep non-current SSA names.  Don't assume default DEFs.
	(rewrite_update_stmt): Rearrange logic.
	(adjust_debug_stmts_for_var_def_move,
	adjust_debug_stmts_for_move): Moved to...
	* tree-ssa.c (propagate_var_def_into_debug_stmts,
	propagate_defs_into_debug_stmts): ... this.
	(target_for_debug_bind): Moved and renamed from
	var_debug_value_for_decl.  Support DECL_HAS_VALUE_EXPR_P rather
	than ABSTRACT_ORIGINs.
	(verify_ssa): Adjust.
	* tree-parloops.c: Adjust.
	(separate_decls_in_region): Add comments.  Drop unnecessary
	assertion check.
	* tree-ssa-dce.c (necessary_p): Remove.
	(eliminate_unnecessary_stmts): Iterate backwards.  Adjust.
	* tree-ssa-loop-ivopts.c: Adjust.
	* tree.h (VAR_DEBUG_VALUE_NOVALUE): Removed.
	(VAR_DEBUG_VALUE_SET_VAR): Removed.  Changed all callers to use
	gimple_debug_bind_set_var.
	(VAR_DEBUG_VALUE_VAR): Removed.  Changed all callers to use
	gimple_debug_bind_get_var.
	(VAR_DEBUG_VALUE_VALUE): Removed.  Changed all callers to use
	gimple_debug_bind_get_value, gimple_debug_bind_get_value_ptr,
	gimple_debug_bind_set_value, gimple_debug_bind_reset_value or
	gimple_debug_bind_has_value_p.
	(target_for_debug_bind): Declare.
	(var_debug_value_for_decl): Remove.
	* expr.c (expand_expr_real_1): Drop VAR_DEBUG_VALUE handling.
	* gimple-pretty-print.c (dump_gimple_debug): Adjust.
	* gimple.c (gimple_build_wtih_ops_stat): Take unsigned subcode.
	(gimple_build_assign_with_ops_stat): Type-cast subcode.
	(gimple_build_debug_bind_stat): Document stmt parameter.
	Use GIMPLE_DEBUG_BIND.
	* tree-flow.h: Rename and remove declarations.
	* tree-ssa-operands.c Adjust.
	(opf_debug_use): Removed.  Test is_gimple_debug instead.
	(get_indirect_ref_operands): Pass down opf_no_vops.
	(get_expr_operands): Drop VAR_DEBUG_VALUE handling.
	* tree.def: Drop VAR_DEBUG_VALUE.
	* var-tracking.c: Adjust.
	* tree-cfg.c: Adjust.
	(remove_bb): Walk stmts backwards.
	(remove_edge_and_dominated_blocks): Visit blocks backwards.
	* tree-ssa-dom.c (propagate_rhs_into_lhs): Simplify handling of
	debug stmts.
	* tree-ssa-forwprop.c, tree-ssa-loop-im.c: Adjust.
	* tree-ssa-reassoc.c, tree-ssa-sink.c, tree-ssanames.c: Adjust.

Index: gcc/cfgexpand.c
===================================================================
--- gcc/cfgexpand.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/cfgexpand.c	2009-07-12 02:03:01.000000000 -0300
@@ -2194,6 +2194,8 @@ expand_debug_expr (tree exp)
       if (!lookup_constant_def (exp))
 	{
 	  op0 = gen_rtx_CONST_STRING (Pmode, TREE_STRING_POINTER (exp));
+	  op0 = gen_rtx_MEM (BLKmode, op0);
+	  set_mem_attributes (op0, exp, 0);
 	  return op0;
 	}
       /* Fall through...  */
@@ -2751,7 +2753,7 @@ expand_debug_locations (void)
 	rtx val;
 	enum machine_mode mode;
 
-	if (value == VAR_DEBUG_VALUE_NOVALUE)
+	if (value == NULL_TREE)
 	  val = NULL_RTX;
 	else
 	  {
@@ -2883,11 +2885,16 @@ expand_gimple_basic_block (basic_block b
 
 	  for (;;)
 	    {
-	      tree var = VAR_DEBUG_VALUE_VAR (stmt);
-	      tree value = VAR_DEBUG_VALUE_VALUE (stmt);
+	      tree var = gimple_debug_bind_get_var (stmt);
+	      tree value;
 	      rtx val;
 	      enum machine_mode mode;
 
+	      if (gimple_debug_bind_has_value_p (stmt))
+		value = gimple_debug_bind_get_value (stmt);
+	      else
+		value = NULL_TREE;
+
 	      last = get_last_insn ();
 
 	      set_curr_insn_source_location (gimple_location (stmt));
Index: gcc/gimple.h
===================================================================
--- gcc/gimple.h.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/gimple.h	2009-07-07 22:09:13.000000000 -0300
@@ -114,7 +114,9 @@ enum gf_mask {
     GF_OMP_RETURN_NOWAIT	= 1 << 0,
 
     GF_OMP_SECTION_LAST		= 1 << 0,
-    GF_PREDICT_TAKEN		= 1 << 15
+    GF_PREDICT_TAKEN		= 1 << 15,
+
+    GIMPLE_DEBUG_BIND		= 0
 };
 
 /* Masks for selecting a pass local flag (PLF) to work on.  These
@@ -3177,7 +3179,7 @@ static inline bool
 gimple_debug_bind_p (const_gimple s)
 {
   if (is_gimple_debug (s))
-    return s->gsbase.subcode == VAR_DEBUG_VALUE;
+    return s->gsbase.subcode == GIMPLE_DEBUG_BIND;
 
   return false;
 }
@@ -3235,6 +3237,34 @@ gimple_debug_bind_set_value (gimple dbg,
   gimple_set_op (dbg, 1, value);
 }
 
+/* The second operand of a GIMPLE_DEBUG_BIND, when the value was
+   optimized away.  */
+#define GIMPLE_DEBUG_BIND_NOVALUE NULL_TREE /* error_mark_node */
+
+/* Remove the value bound to the variable in a GIMPLE_DEBUG bind
+   statement.  */
+
+static inline void
+gimple_debug_bind_reset_value (gimple dbg)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_assert (gimple_debug_bind_p (dbg));
+  gimple_set_op (dbg, 1, GIMPLE_DEBUG_BIND_NOVALUE);
+}
+
+/* Return true if the GIMPLE_DEBUG bind statement is bound to a
+   value.  */
+
+static inline bool
+gimple_debug_bind_has_value_p (gimple dbg)
+{
+  GIMPLE_CHECK (dbg, GIMPLE_DEBUG);
+  gcc_assert (gimple_debug_bind_p (dbg));
+  return gimple_op (dbg, 1) != GIMPLE_DEBUG_BIND_NOVALUE;
+}
+
+#undef GIMPLE_DEBUG_BIND_NOVALUE
+
 /* Return the body for the OMP statement GS.  */
 
 static inline gimple_seq 
@@ -4390,7 +4420,9 @@ static inline void
 gsi_next_nondebug (gimple_stmt_iterator *i)
 {
   do
-    gsi_next (i);
+    {
+      gsi_next (i);
+    }
   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
 }
 
@@ -4400,7 +4432,9 @@ static inline void
 gsi_prev_nondebug (gimple_stmt_iterator *i)
 {
   do
-    gsi_prev (i);
+    {
+      gsi_prev (i);
+    }
   while (!gsi_end_p (*i) && is_gimple_debug (gsi_stmt (*i)));
 }
 
Index: gcc/tree-if-conv.c
===================================================================
--- gcc/tree-if-conv.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-if-conv.c	2009-07-07 20:05:22.000000000 -0300
@@ -240,10 +240,10 @@ tree_if_convert_stmt (struct loop *  loo
       break;
 
     case GIMPLE_DEBUG:
-      /* ??? Should there be conditional VAR_DEBUG_VALUEs?  */
+      /* ??? Should there be conditional GIMPLE_DEBUG_BINDs?  */
       if (gimple_debug_bind_p (gsi_stmt (*gsi)))
 	{
-	  VAR_DEBUG_VALUE_VALUE (gsi_stmt (*gsi)) = VAR_DEBUG_VALUE_NOVALUE;
+	  gimple_debug_bind_reset_value (gsi_stmt (*gsi));
 	  update_stmt (gsi_stmt (*gsi));
 	}
       break;
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-inline.c	2009-07-07 20:05:22.000000000 -0300
@@ -159,7 +159,7 @@ insert_debug_decl_map (copy_body_data *i
   if (!MAY_HAVE_DEBUG_STMTS)
     return;
 
-  if (!var_debug_value_for_decl (key))
+  if (!target_for_debug_bind (key))
     return;
 
   gcc_assert (TREE_CODE (key) == PARM_DECL);
@@ -1323,8 +1323,8 @@ remap_gimple_stmt (gimple stmt, copy_bod
 
       if (gimple_debug_bind_p (stmt))
 	{
-	  copy = gimple_build_debug_bind (VAR_DEBUG_VALUE_VAR (stmt),
-					  VAR_DEBUG_VALUE_VALUE (stmt),
+	  copy = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt),
+					  gimple_debug_bind_get_value (stmt),
 					  stmt);
 	  VARRAY_PUSH_GENERIC_PTR (id->debug_stmts, copy);
 	  return copy;
@@ -2052,6 +2052,12 @@ copy_cfg_body (copy_body_data * id, gcov
   return new_fndecl;
 }
 
+/* Copy the debug STMT using ID.  We deal with these statements in a
+   special way: if any variable in their VALUE expression wasn't
+   remapped yet, we won't remap it, because that would get decl uids
+   out of sync, causing codegen differences between -g and -g0.  If
+   this arises, we drop the VALUE expression altogether.  */
+
 static void
 copy_debug_stmt (gimple stmt, copy_body_data *id)
 {
@@ -2074,7 +2080,7 @@ copy_debug_stmt (gimple stmt, copy_body_
 
   processing_debug_stmt = 1;
 
-  t = VAR_DEBUG_VALUE_VAR (stmt);
+  t = gimple_debug_bind_get_var (stmt);
 
   if (TREE_CODE (t) == PARM_DECL && id->debug_map
       && (n = (tree *) pointer_map_contains (id->debug_map, t)))
@@ -2085,14 +2091,15 @@ copy_debug_stmt (gimple stmt, copy_body_
   else
     walk_tree (&t, remap_gimple_op_r, &wi, NULL);
 
-  VAR_DEBUG_VALUE_SET_VAR (stmt, t);
+  gimple_debug_bind_set_var (stmt, t);
 
-  if (VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
-    walk_tree (&VAR_DEBUG_VALUE_VALUE (stmt), remap_gimple_op_r, &wi, NULL);
+  if (gimple_debug_bind_has_value_p (stmt))
+    walk_tree (gimple_debug_bind_get_value_ptr (stmt),
+	       remap_gimple_op_r, &wi, NULL);
 
   /* Punt if any decl couldn't be remapped.  */
   if (processing_debug_stmt < 0)
-    VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
+    gimple_debug_bind_reset_value (stmt);
 
   processing_debug_stmt = 0;
 
@@ -2101,6 +2108,10 @@ copy_debug_stmt (gimple stmt, copy_body_
     mark_symbols_for_renaming (stmt);
 }
 
+/* Process deferred debug stmts.  In order to give values better odds
+   of being successfully remapped, we delay the processing of debug
+   stmts.  */
+
 static void
 copy_debug_stmts (copy_body_data *id)
 {
@@ -2174,6 +2185,7 @@ insert_init_debug_bind (copy_body_data *
 {
   gimple note;
   gimple_stmt_iterator gsi;
+  tree tracked_var;
 
   if (!gimple_in_ssa_p (id->src_cfun))
     return NULL;
@@ -2181,7 +2193,8 @@ insert_init_debug_bind (copy_body_data *
   if (!MAY_HAVE_DEBUG_STMTS)
     return NULL;
 
-  if (!var_debug_value_for_decl (var))
+  tracked_var = target_for_debug_bind (var);
+  if (!tracked_var)
     return NULL;
 
   if (bb)
@@ -2191,7 +2204,7 @@ insert_init_debug_bind (copy_body_data *
 	base_stmt = gsi_stmt (gsi);
     }
 
-  note = gimple_build_debug_bind (var, value, base_stmt);
+  note = gimple_build_debug_bind (tracked_var, value, base_stmt);
 
   if (bb)
     {
Index: gcc/tree-into-ssa.c
===================================================================
--- gcc/tree-into-ssa.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-into-ssa.c	2009-07-12 03:16:10.000000000 -0300
@@ -1054,244 +1054,6 @@ mark_phi_for_rewrite (basic_block bb, gi
   VEC_replace (gimple_vec, phis_to_rewrite, idx, phis);
 }
 
-/* Decide whether to emit a VAR_DEBUG_VALUE annotation for VAR.  */
-
-bool
-var_debug_value_for_decl (tree var)
-{
-  if (TREE_CODE (var) != VAR_DECL
-      && TREE_CODE (var) != PARM_DECL)
-    return false;
-
-  if (DECL_IGNORED_P (var))
-    return false;
-
-  if (!DECL_NAME (var))
-    {
-      tree origin = DECL_ABSTRACT_ORIGIN (var);
-
-      if (!origin)
-	return false;
-
-      if (!DECL_P (origin))
-	return false;
-
-      if (!DECL_NAME (origin))
-	return false;
-    }
-
-  if (!MAY_HAVE_DEBUG_STMTS)
-    return false;
-
-  if (!is_gimple_reg (var))
-    return false;
-
-  return true;
-}
-
-/* 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.  */
-void
-adjust_debug_stmts_for_var_def_move (tree var,
-				     basic_block tobb,
-				     const gimple_stmt_iterator *togsip)
-{
-  imm_use_iterator imm_iter;
-  gimple stmt;
-  use_operand_p use_p;
-  tree value = NULL;
-  bool no_value = false;
-
-  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)
-	    {
-	      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;
-	    }
-	}
-
-      if (!value && !no_value)
-	{
-	  if (SSA_NAME_VALUE (var))
-	    value = SSA_NAME_VALUE (var);
-	  else
-	    {
-	      gimple def_stmt = SSA_NAME_DEF_STMT (var);
-
-	      if (gimple_code (def_stmt) == GIMPLE_ASSIGN
-		  && TREE_TYPE (gimple_assign_rhs1 (def_stmt))
-		  && gimple_assign_rhs2 (def_stmt)
-		  && TREE_TYPE (gimple_assign_rhs2 (def_stmt)))
-		value = gimple_assign_rhs_to_tree (def_stmt);
-	    }
-
-	  if (!value)
-	    no_value = true;
-	}
-
-      if (no_value)
-	VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
-      else
-	FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter)
-	  SET_USE (use_p, unshare_expr (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.  */
-
-void
-adjust_debug_stmts_for_move (gimple def, basic_block tobb,
-			     const gimple_stmt_iterator *togsip)
-{
-  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_ALL_DEFS)
-    {
-      tree var = DEF_FROM_PTR (def_p);
-
-      if (TREE_CODE (var) != SSA_NAME)
-	continue;
-
-      adjust_debug_stmts_for_var_def_move (var, tobb, togsip);
-    }
-}
-
-/* Wrapper struct for the function predicate passed to
-   check_and_update_debug_stmt_1 ().  */
-
-struct check_debug_predicate
-{
-  bool (*available_p)(tree);
-  gimple stmt;
-};
-
-/* Look for an SSA_NAME in the expression *TP whose definition was
-   removed, or is about to be removed, per the available_p predicate
-   given by the check_debug_predicate *DATA.  */
-
-static tree
-check_and_update_debug_stmt_1 (tree *tp, int *walk_subtrees,
-			       void *data)
-{
-  tree t = *tp;
-
-  if (EXPR_P (t))
-    return NULL_TREE;
-
-  *walk_subtrees = 0;
-
-  if (TREE_CODE (t) == SSA_NAME)
-    {
-      struct check_debug_predicate *p = (struct check_debug_predicate *)data;
-
-      if (SSA_NAME_IN_FREE_LIST (t))
-	return t;
-
-      if (!SSA_NAME_DEF_STMT (t))
-	{
-	  /* Default definitions are never removed.  */
-	  if (SSA_NAME_IS_DEFAULT_DEF (t))
-	    return NULL_TREE;
-	  else
-	    return t;
-	}
-
-      if (gimple_nop_p (SSA_NAME_DEF_STMT (t)))
-	{
-	  if (SSA_NAME_IS_DEFAULT_DEF (t))
-	    return NULL_TREE;
-	  else
-	    return t;
-	}
-
-      if (p->available_p && !p->available_p (t))
-	return t;
-
-      if (dom_info_available_p (CDI_DOMINATORS))
-	{
-	  basic_block bbuse = gimple_bb (p->stmt);
-	  basic_block bbdef = gimple_bb (SSA_NAME_DEF_STMT (t));
-
-	  if (bbuse != bbdef
-	      && !dominated_by_p (CDI_DOMINATORS, bbuse, bbdef))
-	    return t;
-	}
-    }
-
-  return NULL_TREE;
-}
-
-/* Look for any SSA_NAMEs in the VALUE of a VAR_DEBUG_VALUE statement
-   T that have become or are about to become unavailable.
-   AVAILABLE_P, if non-NULL, is used to determine whether the variable
-   is about to become unavailable.  */
-
-void
-check_and_update_debug_stmt (gimple t, bool (*available_p)(tree))
-{
-  struct check_debug_predicate p;
-
-  gcc_assert (is_gimple_debug (t));
-
-  if (VAR_DEBUG_VALUE_VALUE (t) == VAR_DEBUG_VALUE_NOVALUE)
-    return;
-
-  p.available_p = available_p;
-  p.stmt = t;
-  if (walk_tree (&VAR_DEBUG_VALUE_VALUE (t), check_and_update_debug_stmt_1,
-		 &p, NULL))
-    {
-      /* ??? Can we do better?  */
-      VAR_DEBUG_VALUE_VALUE (t) = VAR_DEBUG_VALUE_NOVALUE;
-      update_stmt (t);
-    }
-}
-
 /* Insert PHI nodes for variable VAR using the iterated dominance
    frontier given in PHI_INSERTION_POINTS.  If UPDATE_P is true, this
    function assumes that the caller is incrementally updating the
@@ -1358,11 +1120,13 @@ insert_phi_nodes_for (tree var, bitmap p
 	}
       else
 	{
+	  tree tracked_var;
 	  gcc_assert (DECL_P (var));
 	  phi = create_phi_node (var, bb);
-	  if (!update_p && var_debug_value_for_decl (var))
+	  if (!update_p && (tracked_var = target_for_debug_bind (var)))
 	    {
-	      gimple note = gimple_build_debug_bind (var, PHI_RESULT (phi),
+	      gimple note = gimple_build_debug_bind (tracked_var,
+						     PHI_RESULT (phi),
 						     phi);
 	      gimple_stmt_iterator si = gsi_after_labels (bb);
 	      gsi_insert_before (&si, note, GSI_SAME_STMT);
@@ -1540,15 +1304,19 @@ rewrite_stmt (gimple_stmt_iterator si)
   if (register_defs_p (stmt))
     FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
       {
-	tree var = DEF_FROM_PTR (def_p), name;
+	tree var = DEF_FROM_PTR (def_p);
+	tree name = make_ssa_name (var, stmt);
+	tree tracked_var;
 	gcc_assert (DECL_P (var));
-	SET_DEF (def_p, name = make_ssa_name (var, stmt));
-	if (var_debug_value_for_decl (var))
+	SET_DEF (def_p, name);
+	register_new_def (DEF_FROM_PTR (def_p), var);
+
+	tracked_var = target_for_debug_bind (var);
+	if (tracked_var)
 	  {
-	    gimple note = gimple_build_debug_bind (var, name, stmt);
+	    gimple note = gimple_build_debug_bind (tracked_var, name, stmt);
 	    gsi_insert_after (&si, note, GSI_SAME_STMT);
 	  }
-	register_new_def (DEF_FROM_PTR (def_p), var);
       }
 }
 
@@ -2013,7 +1781,7 @@ maybe_replace_use (use_operand_p use_p)
    returning false to indicate a need to do so.  */
 
 static inline bool
-maybe_replace_use_in_debug_insn (use_operand_p use_p)
+maybe_replace_use_in_debug_stmt (use_operand_p use_p)
 {
   tree rdef = NULL_TREE;
   tree use = USE_FROM_PTR (use_p);
@@ -2024,11 +1792,15 @@ maybe_replace_use_in_debug_insn (use_ope
   else if (is_old_name (use))
     {
       rdef = get_current_def (use);
-      if (!rdef && SSA_NAME_DEF_STMT (use))
-	return true;
+      /* We can't assume that, if there's no current definition, the
+	 default one should be used.  It could be the case that we've
+	 rearranged blocks so that the earlier definition no longer
+	 dominates the use.  */
+      if (!rdef && SSA_NAME_IS_DEFAULT_DEF (use))
+	rdef = use;
     }
   else
-    return true;
+    rdef = use;
 
   if (rdef && rdef != use)
     SET_USE (use_p, rdef);
@@ -2102,37 +1874,41 @@ rewrite_update_stmt (gimple stmt)
 
   /* Rewrite USES included in OLD_SSA_NAMES and USES whose underlying
      symbol is marked for renaming.  */
-  if (rewrite_uses_p (stmt) && !is_gimple_debug (stmt))
-    FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
-      maybe_replace_use (use_p);
-
-  else if (rewrite_uses_p (stmt) && is_gimple_debug (stmt))
+  if (rewrite_uses_p (stmt))
     {
-      bool failed = false;
+      if (is_gimple_debug (stmt))
+	{
+	  bool failed = false;
 
-      FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
-	if (!maybe_replace_use_in_debug_insn (use_p))
-	  {
-	    failed = true;
-	    break;
-	  }
+	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+	    if (!maybe_replace_use_in_debug_stmt (use_p))
+	      {
+		failed = true;
+		break;
+	      }
 
-      if (failed)
+	  if (failed)
+	    {
+	      /* DOM sometimes threads jumps in such a way that a
+		 debug stmt ends up referencing a SSA variable that no
+		 longer dominates the debug stmt, but such that all
+		 incoming definitions refer to the same definition in
+		 an earlier dominator.  We could try to recover that
+		 definition somehow, but this will have to do for now.
+
+		 Introducing a default definition, which is what
+		 maybe_replace_use() would do in such cases, may
+		 modify code generation, for the otherwise-unused
+		 default definition would never go away, modifying SSA
+		 version numbers all over.  */
+	      gimple_debug_bind_reset_value (stmt);
+	      update_stmt (stmt);
+	    }
+	}
+      else
 	{
-	  /* DOM sometimes threads jumps in such a way that a debug
-	     stmt ends up referencing a SSA variable that no longer
-	     dominates the debug stmt, but such that all incoming
-	     definitions refer to the same definition in an earlier
-	     dominator.  We could try to recover that definition
-	     somehow, but this will have to do for now.
-
-	     Introducing a default definition, which is what
-	     maybe_replace_use() would do in such cases, may modify
-	     code generation, for the otherwise-unused default
-	     definition would never go away, modifying SSA version
-	     numbers all over.  */
-	  VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
-	  update_stmt (stmt);
+	  FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
+	    maybe_replace_use (use_p);
 	}
     }
 
Index: gcc/tree-parloops.c
===================================================================
--- gcc/tree-parloops.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-parloops.c	2009-07-07 20:05:22.000000000 -0300
@@ -883,7 +883,7 @@ separate_decls_in_region_debug_bind (gim
     slot = htab_find_slot_with_hash (name_copies, &elt, elt.version, NO_INSERT);
     if (!slot)
       {
-	gimple_debug_bind_set_value (stmt, VAR_DEBUG_VALUE_NOVALUE);
+	gimple_debug_bind_reset_value (stmt);
 	update_stmt (stmt);
 	break;
       }
@@ -1253,6 +1253,12 @@ separate_decls_in_region (edge entry, ed
 	}
     }
 
+  /* Now process debug bind stmts.  We must not create decls while
+     processing debug stmts, so we defer their processing so as to
+     make sure we will have debug info for as many variables as
+     possible (all of those that were dealt with in the loop above),
+     and discard those for which we know there's nothing we can
+     do.  */
   if (has_debug_stmt)
     for (i = 0; VEC_iterate (basic_block, body, i, bb); i++)
       if (bb != entry_bb && bb != exit_bb)
@@ -1271,8 +1277,6 @@ separate_decls_in_region (edge entry, ed
 		      continue;
 		    }
 		}
-	      else
-		gcc_assert (!is_gimple_debug (stmt));
 
 	      gsi_next (&gsi);
 	    }
Index: gcc/tree-ssa-dce.c
===================================================================
--- gcc/tree-ssa-dce.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-ssa-dce.c	2009-07-10 16:01:13.000000000 -0300
@@ -1,5 +1,5 @@
 /* Dead code elimination pass for the GNU compiler.
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Ben Elliston <bje@redhat.com>
    and Andrew MacLeod <amacleod@redhat.com>
@@ -1062,16 +1062,6 @@ remove_dead_stmt (gimple_stmt_iterator *
   release_defs (stmt); 
 }
 
-/* Predicate used by check_and_update_debug_stmt.  Return TRUE if the
-   T's definition is not about to be removed.  T is assumed to be an
-   SSA_NAME.  */
-
-static bool
-necessary_p (tree t)
-{
-  return gimple_plf (SSA_NAME_DEF_STMT (t), STMT_NECESSARY);
-}
-
 /* Eliminate unnecessary statements. Any instruction not marked as necessary
    contributes nothing to the program, and can be deleted.  */
 
@@ -1089,10 +1079,32 @@ eliminate_unnecessary_stmts (void)
 
   clear_special_calls ();
 
-  FOR_EACH_BB (bb)
+  /* Walking basic blocks and statements in reverse order avoids
+     releasing SSA names before any other DEFs that refer to them are
+     released.  This helps avoid loss of debug information, as we get
+     a chance to propagate all RHSs of removed SSAs into debug uses,
+     rather than only the latest ones.  E.g., consider:
+
+     x_3 = y_1 + z_2;
+     a_5 = x_3 - b_4;
+     # DEBUG a => a_5
+
+     If we were to release x_3 before a_5, when we reached a_5 and
+     tried to substitute it into the debug stmt, we'd see x_3 there,
+     but x_3's DEF, type, etc would have already been disconnected.
+     By going backwards, the debug stmt first changes to:
+
+     # DEBUG a => x_3 - b_4
+
+     and then to:
+
+     # DEBUG a => y_1 + z_2 - b_4
+
+     as desired.  */
+  FOR_EACH_BB_REVERSE (bb)
     {
       /* Remove dead statements.  */
-      for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
+      for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
 	{
 	  stmt = gsi_stmt (gsi);
 
@@ -1103,6 +1115,14 @@ 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))
 	    {
@@ -1132,19 +1152,10 @@ eliminate_unnecessary_stmts (void)
 		    }
 		  notice_special_calls (stmt);
 		}
-	      gsi_next (&gsi);
+	      gsi_prev (&gsi);
 	    }
 	  else
-	    {
-	      if (gimple_debug_bind_p (stmt))
-		{
-		  if (something_changed
-		      && (VAR_DEBUG_VALUE_VALUE (stmt)
-			  != VAR_DEBUG_VALUE_NOVALUE))
-		    check_and_update_debug_stmt (stmt, necessary_p);
-		}
-	      gsi_next (&gsi);
-	    }
+	    gsi_prev (&gsi);
 	}
     }
   /* Since we don't track liveness of virtual PHI nodes, it is possible that we
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-ssa-loop-ivopts.c	2009-07-07 20:05:22.000000000 -0300
@@ -5426,7 +5426,7 @@ remove_unused_ivs (struct ivopts_data *d
 		    continue;
 
 		  /* ??? We can probably do better than this.  */
-		  VAR_DEBUG_VALUE_VALUE (stmt) = VAR_DEBUG_VALUE_NOVALUE;
+		  gimple_debug_bind_reset_value (stmt);
 		  update_stmt (stmt);
 		}
 	    }
Index: gcc/tree-ssa.c
===================================================================
--- gcc/tree-ssa.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-ssa.c	2009-07-10 23:51:25.000000000 -0300
@@ -239,6 +239,148 @@ flush_pending_stmts (edge e)
   redirect_edge_var_map_clear (e);
 }
 
+/* Given a tree for an expression for which we might want to emit
+   locations or values in debug information (generally a variable, but
+   we might deal with other kinds of trees in the future), return the
+   tree that should be used as the variable of a DEBUG_BIND STMT or
+   VAR_LOCATION INSN or NOTE.  Return NULL if VAR is not to be tracked.  */
+
+tree
+target_for_debug_bind (tree var)
+{
+  if (!MAY_HAVE_DEBUG_STMTS)
+    return NULL_TREE;
+
+  if (TREE_CODE (var) != VAR_DECL
+      && TREE_CODE (var) != PARM_DECL)
+    return NULL_TREE;
+
+  if (DECL_HAS_VALUE_EXPR_P (var))
+    return target_for_debug_bind (DECL_VALUE_EXPR (var));
+
+#if 0
+  /* Should we deal with DECL_DEBUG_EXPR_IS_FROM as well?  */
+  if (DECL_DEBUG_EXPR_IS_FROM (var))
+    return target_for_debug_bind (DECL_DEBUG_EXPR (var));
+#endif
+
+  if (DECL_IGNORED_P (var))
+    return NULL_TREE;
+
+  if (!is_gimple_reg (var))
+    return NULL_TREE;
+
+  return var;
+}
+
+/* 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.  */
+void
+propagate_var_def_into_debug_stmts (tree var,
+				    basic_block tobb,
+				    const gimple_stmt_iterator *togsip)
+{
+  imm_use_iterator imm_iter;
+  gimple stmt;
+  use_operand_p use_p;
+  tree value = NULL;
+  bool no_value = false;
+
+  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 (is_gimple_assign (def_stmt))
+	    value = gimple_assign_rhs_to_tree (def_stmt);
+
+	  if (!value)
+	    no_value = true;
+	}
+
+      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));
+
+      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.  */
+
+void
+propagate_defs_into_debug_stmts (gimple def, basic_block tobb,
+				 const gimple_stmt_iterator *togsip)
+{
+  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_ALL_DEFS)
+    {
+      tree var = DEF_FROM_PTR (def_p);
+
+      if (TREE_CODE (var) != SSA_NAME)
+	continue;
+
+      propagate_var_def_into_debug_stmts (var, tobb, togsip);
+    }
+}
+
 /* Return true if SSA_NAME is malformed and mark it visited.
 
    IS_VIRTUAL is true if this SSA_NAME was found inside a virtual
@@ -633,7 +775,7 @@ verify_ssa (bool check_modified_stmt)
 		}
 	    }
 	  else if (gimple_debug_bind_p (stmt)
-		   && VAR_DEBUG_VALUE_VALUE (stmt) == VAR_DEBUG_VALUE_NOVALUE)
+		   && !gimple_debug_bind_has_value_p (stmt))
 	    continue;
 
 	  /* Verify the single virtual operand and its constraints.  */
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree.h	2009-07-07 20:52:58.000000000 -0300
@@ -1534,13 +1534,6 @@ struct GTY(()) tree_constructor {
 /* Nonzero if is_gimple_debug() may possibly hold.  */
 #define MAY_HAVE_DEBUG_STMTS    (flag_var_tracking_assignments)
 
-/* The second operand of a VAR_DEBUG_VALUE when the value was
-   optimized away.  */
-#define VAR_DEBUG_VALUE_NOVALUE NULL_TREE /* error_mark_node */
-#define VAR_DEBUG_VALUE_SET_VAR(T, V) (gimple_debug_bind_set_var ((T), (V)))
-#define VAR_DEBUG_VALUE_VAR(T) (gimple_debug_bind_get_var (T))
-#define VAR_DEBUG_VALUE_VALUE(T) (*gimple_debug_bind_get_value_ptr (T))
-
 /* In a LOOP_EXPR node.  */
 #define LOOP_EXPR_BODY(NODE) TREE_OPERAND_CHECK_CODE (NODE, LOOP_EXPR, 0)
 
@@ -5173,6 +5166,10 @@ struct GTY(()) tree_priority_map {
 #define tree_priority_map_hash tree_map_base_hash
 #define tree_priority_map_marked_p tree_map_base_marked_p
 
+/* In tree-ssa.c */
+
+tree target_for_debug_bind (tree);
+
 /* In tree-ssa-ccp.c */
 extern tree maybe_fold_offset_to_reference (location_t, tree, tree, tree);
 extern tree maybe_fold_offset_to_address (location_t, tree, tree, tree);
@@ -5313,8 +5310,4 @@ more_const_call_expr_args_p (const const
   for ((arg) = first_const_call_expr_arg ((call), &(iter)); (arg);	\
        (arg) = next_const_call_expr_arg (&(iter)))
 
-/* Determines whether the given TREE is subject to debug tracking.  */
-
-bool var_debug_value_for_decl (tree);
-
 #endif  /* GCC_TREE_H  */
Index: gcc/expr.c
===================================================================
--- gcc/expr.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/expr.c	2009-07-07 20:05:22.000000000 -0300
@@ -9261,10 +9261,6 @@ expand_expr_real_1 (tree exp, rtx target
 	return const0_rtx;
       }
 
-    case VAR_DEBUG_VALUE:
-      /* Expanded by expand_gimple_basic_block only.  */
-      gcc_unreachable ();
-
     case RETURN_EXPR:
       if (!TREE_OPERAND (exp, 0))
 	expand_null_return ();
Index: gcc/gimple-pretty-print.c
===================================================================
--- gcc/gimple-pretty-print.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/gimple-pretty-print.c	2009-07-07 20:14:18.000000000 -0300
@@ -789,7 +789,7 @@ dump_gimple_debug (pretty_printer *buffe
 {
   switch (gs->gsbase.subcode)
     {
-    case VAR_DEBUG_VALUE:
+    case GIMPLE_DEBUG_BIND:
       if (flags & TDF_RAW)
 	dump_gimple_fmt (buffer, spc, flags, "%G BIND <%T, %T>", gs,
 			 gimple_debug_bind_get_var (gs),
Index: gcc/gimple.c
===================================================================
--- gcc/gimple.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/gimple.c	2009-07-07 20:55:52.000000000 -0300
@@ -254,7 +254,7 @@ gimple_set_subcode (gimple g, unsigned s
   gimple_build_with_ops_stat (c, s, n MEM_STAT_INFO)
 
 static gimple
-gimple_build_with_ops_stat (enum gimple_code code, enum tree_code subcode,
+gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode,
 		            unsigned num_ops MEM_STAT_DECL)
 {
   gimple s = gimple_alloc_stat (code, num_ops PASS_MEM_STAT);
@@ -427,7 +427,7 @@ gimple_build_assign_with_ops_stat (enum 
      code).  */
   num_ops = get_gimple_rhs_num_ops (subcode) + 1;
   
-  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, subcode, num_ops
+  p = gimple_build_with_ops_stat (GIMPLE_ASSIGN, (unsigned)subcode, num_ops
   			          PASS_MEM_STAT);
   gimple_assign_set_lhs (p, lhs);
   gimple_assign_set_rhs1 (p, op1);
@@ -832,12 +832,13 @@ gimple_build_switch_vec (tree index, tre
 
 /* Build a new GIMPLE_DEBUG_BIND statement.
 
-   VAR is bound to VALUE.  */
+   VAR is bound to VALUE; block and location are taken from STMT.  */
 
 gimple
 gimple_build_debug_bind_stat (tree var, tree value, gimple stmt MEM_STAT_DECL)
 {
-  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG, VAR_DEBUG_VALUE, 2
+  gimple p = gimple_build_with_ops_stat (GIMPLE_DEBUG,
+					 (unsigned)GIMPLE_DEBUG_BIND, 2
 					 PASS_MEM_STAT);
 
   gimple_debug_bind_set_var (p, var);
Index: gcc/tree-flow.h
===================================================================
--- gcc/tree-flow.h.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-flow.h	2009-07-10 23:51:34.000000000 -0300
@@ -629,6 +629,10 @@ 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 *);
 
 /* In tree-into-ssa.c  */
 void update_ssa (unsigned);
@@ -645,11 +649,6 @@ void mark_sym_for_renaming (tree);
 void mark_set_for_renaming (bitmap);
 tree get_current_def (tree);
 void set_current_def (tree, tree);
-void adjust_debug_stmts_for_move (gimple, basic_block,
-				  const gimple_stmt_iterator *);
-void adjust_debug_stmts_for_var_def_move (tree, basic_block,
-					  const gimple_stmt_iterator *);
-void check_and_update_debug_stmt (gimple, bool (*)(tree));
 
 /* In tree-ssanames.c  */
 extern void init_ssanames (struct function *, int);
Index: gcc/tree-ssa-operands.c
===================================================================
--- gcc/tree-ssa-operands.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree-ssa-operands.c	2009-07-07 22:22:29.000000000 -0300
@@ -126,9 +126,6 @@ static struct 
    clobbering sites like function calls or ASM_EXPRs.  */
 #define opf_implicit	(1 << 2)
 
-/* Operand is a use only for purposes of debug information.  */
-#define opf_debug_use   (1 << 3)
-
 /* Array for building all the def operands.  */
 static VEC(tree,heap) *build_defs;
 
@@ -638,7 +635,7 @@ add_virtual_operand (gimple stmt ATTRIBU
   if (flags & opf_no_vops)
     return;
 
-  gcc_assert ((flags & opf_debug_use) == 0);
+  gcc_assert (!is_gimple_debug (stmt));
 
   if (flags & opf_def)
     append_vdef (gimple_vop (cfun));
@@ -727,7 +724,8 @@ get_indirect_ref_operands (gimple stmt, 
 
   /* If requested, add a USE operand for the base pointer.  */
   if (recurse_on_base)
-    get_expr_operands (stmt, pptr, opf_use);
+    get_expr_operands (stmt, pptr,
+		       opf_use | (flags & opf_no_vops));
 }
 
 
@@ -856,8 +854,8 @@ get_expr_operands (gimple stmt, tree *ex
   if (expr == NULL)
     return;
 
-  if ((flags & opf_debug_use) != 0)
-    uflags |= (flags & (opf_debug_use | opf_no_vops));
+  if (is_gimple_debug (stmt))
+    uflags |= (flags & opf_no_vops);
 
   code = TREE_CODE (expr);
   codeclass = TREE_CODE_CLASS (code);
@@ -869,7 +867,7 @@ get_expr_operands (gimple stmt, tree *ex
 	 reference to it, but the fact that the statement takes its
 	 address will be of interest to some passes (e.g. alias
 	 resolution).  */
-      if (!(flags & opf_debug_use))
+      if (!is_gimple_debug (stmt))
 	mark_address_taken (TREE_OPERAND (expr, 0));
 
       /* If the address is invariant, there may be no interesting
@@ -950,12 +948,6 @@ get_expr_operands (gimple stmt, tree *ex
       get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags);
       return;
 
-    case VAR_DEBUG_VALUE:
-      if (VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
-	get_expr_operands (stmt, &VAR_DEBUG_VALUE_VALUE (stmt),
-			   opf_use | opf_debug_use | opf_no_vops);
-      return;
-
     case CONSTRUCTOR:
       {
 	/* General aggregate CONSTRUCTORs have been decomposed, but they
@@ -1045,9 +1037,9 @@ parse_ssa_operands (gimple stmt)
   else if (is_gimple_debug (stmt))
     {
       if (gimple_debug_bind_p (stmt)
-	  && VAR_DEBUG_VALUE_VALUE (stmt) != VAR_DEBUG_VALUE_NOVALUE)
-	get_expr_operands (stmt, &VAR_DEBUG_VALUE_VALUE (stmt),
-			   opf_use | opf_debug_use | opf_no_vops);
+	  && gimple_debug_bind_has_value_p (stmt))
+	get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt),
+			   opf_use | opf_no_vops);
     }
   else
     {
Index: gcc/tree.def
===================================================================
--- gcc/tree.def.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/tree.def	2009-07-07 20:05:22.000000000 -0300
@@ -948,11 +948,6 @@ DEFTREECODE (STATEMENT_LIST, "statement_
    The type of the expression is the same as Y.  */
 DEFTREECODE (ASSERT_EXPR, "assert_expr", tcc_expression, 2)
 
-/* Debug bind operation.  Operand 0 is a tree that represents a user
-   variable; 1 is an expression that evaluates to the value of the
-   variable.  */
-DEFTREECODE (VAR_DEBUG_VALUE, "var_debug_value", tcc_statement, 2)
-
 /* Base class information. Holds information about a class as a
    baseclass of itself or another class.  */
 DEFTREECODE (TREE_BINFO, "tree_binfo", tcc_exceptional, 0)
Index: gcc/var-tracking.c
===================================================================
--- gcc/var-tracking.c.orig	2009-07-07 20:05:05.000000000 -0300
+++ gcc/var-tracking.c	2009-07-07 21:18:39.000000000 -0300
@@ -779,7 +779,7 @@ dv_onepart_p (decl_or_value dv)
   if (!decl)
     return true;
 
-  return var_debug_value_for_decl (decl);
+  return (target_for_debug_bind (decl) != NULL_TREE);
 }
 
 /* Return the variable pool to be used for dv, depending on whether it
@@ -4490,7 +4490,7 @@ use_type (rtx *loc, struct count_use_inf
 
       if (!expr)
 	return MO_USE_NO_VAR;
-      else if (var_debug_value_for_decl (var_debug_decl (expr)))
+      else if (target_for_debug_bind (var_debug_decl (expr)))
 	return MO_CLOBBER;
       else if (track_loc_p (*loc, expr, REG_OFFSET (*loc),
 			    false, modep, NULL))
@@ -4504,7 +4504,7 @@ use_type (rtx *loc, struct count_use_inf
 
       if (!expr)
 	return MO_CLOBBER;
-      else if (var_debug_value_for_decl (var_debug_decl (expr)))
+      else if (target_for_debug_bind (var_debug_decl (expr)))
 	return MO_CLOBBER;
       else if (track_loc_p (*loc, expr, INT_MEM_OFFSET (*loc),
 			    false, modep, NULL))
@@ -7124,7 +7124,7 @@ vt_add_function_parameters (void)
 
       dv = dv_from_decl (parm);
 
-      if (var_debug_value_for_decl (parm)
+      if (target_for_debug_bind (parm)
 	  /* We can't deal with these right now, because this kind of
 	     variable is single-part.  ??? We could handle parallels
 	     that describe multiple locations for the same single
Index: gcc/tree-cfg.c
===================================================================
--- gcc/tree-cfg.c.orig	2009-07-07 15:09:03.000000000 -0300
+++ gcc/tree-cfg.c	2009-07-10 23:51:06.000000000 -0300
@@ -2258,7 +2258,11 @@ remove_bb (basic_block bb)
   /* Remove all the instructions in the block.  */
   if (bb_seq (bb) != NULL)
     {
-      for (i = gsi_start_bb (bb); !gsi_end_p (i);)
+      /* Walk backwards so as to get a chance to substitute all
+	 released DEFs into debug stmts.  See
+	 eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+	 details.  */
+      for (i = gsi_last_bb (bb); !gsi_end_p (i);)
 	{
 	  gimple stmt = gsi_stmt (i);
 	  if (gimple_code (stmt) == GIMPLE_LABEL
@@ -2294,6 +2298,11 @@ remove_bb (basic_block bb)
 	      gsi_remove (&i, true);
 	    }
 
+	  if (gsi_end_p (i))
+	    i = gsi_last_bb (bb);
+	  else
+	    gsi_prev (&i);
+
 	  /* Don't warn for removed gotos.  Gotos are often removed due to
 	     jump threading, thus resulting in bogus warnings.  Not great,
 	     since this way we lose warnings for gotos in the original
@@ -4292,10 +4301,7 @@ verify_stmt (gimple_stmt_iterator *gsi)
     }
 
   if (is_gimple_debug (stmt))
-    {
-      check_and_update_debug_stmt (stmt, NULL);
-      return false;
-    }
+    return false;
 
   memset (&wi, 0, sizeof (wi));
   addr = walk_gimple_op (gsi_stmt (*gsi), verify_expr, &wi);
@@ -6950,8 +6956,12 @@ remove_edge_and_dominated_blocks (edge e
     remove_edge (e);
   else
     {
-      for (i = 0; VEC_iterate (basic_block, bbs_to_remove, i, bb); i++)
-	delete_basic_block (bb);
+      /* Walk backwards so as to get a chance to substitute all
+	 released DEFs into debug stmts.  See
+	 eliminate_unnecessary_stmts() in tree-ssa-dce.c for more
+	 details.  */
+      for (i = VEC_length (basic_block, bbs_to_remove); i-- > 0; )
+	delete_basic_block (VEC_index (basic_block, bbs_to_remove, i));
     }
 
   /* Update the dominance information.  The immediate dominator may change only
Index: gcc/tree-ssa-dom.c
===================================================================
--- gcc/tree-ssa-dom.c.orig	2009-07-05 04:19:48.000000000 -0300
+++ gcc/tree-ssa-dom.c	2009-07-12 03:53:33.000000000 -0300
@@ -1,5 +1,5 @@
 /* SSA Dominator optimizations for trees
-   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
@@ -2523,6 +2523,11 @@ propagate_rhs_into_lhs (gimple stmt, tre
 	 be successful would be if the use occurs in an ASM_EXPR.  */
       FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs)
 	{
+	  /* Leave debug stmts alone.  If we succeed in propagating
+	     all non-debug uses, we'll drop the DEF, and propagation
+	     into debug stmts will occur then.  */
+	  if (gimple_debug_bind_p (use_stmt))
+	    continue;
 	
 	  /* It's not always safe to propagate into an ASM_EXPR.  */
 	  if (gimple_code (use_stmt) == GIMPLE_ASM
@@ -2575,8 +2580,6 @@ propagate_rhs_into_lhs (gimple stmt, tre
 
 	      continue;
 	    }
-	  else if (gimple_debug_bind_p (use_stmt))
-	    check_and_update_debug_stmt (use_stmt, NULL);
 
 	  /* From this point onward we are propagating into a 
 	     real statement.  Folding may (or may not) be possible,
Index: gcc/tree-ssa-forwprop.c
===================================================================
--- gcc/tree-ssa-forwprop.c.orig	2009-06-17 06:17:15.000000000 -0300
+++ gcc/tree-ssa-forwprop.c	2009-07-10 16:28:57.000000000 -0300
@@ -984,7 +984,7 @@ forward_propagate_addr_expr (tree name, 
     }
 
   if (all && debug)
-    adjust_debug_stmts_for_var_def_move (name, NULL, NULL);
+    propagate_var_def_into_debug_stmts (name, NULL, NULL);
 
   return all;
 }
Index: gcc/tree-ssa-loop-im.c
===================================================================
--- gcc/tree-ssa-loop-im.c.orig	2009-07-05 04:16:54.000000000 -0300
+++ gcc/tree-ssa-loop-im.c	2009-07-10 16:28:23.000000000 -0300
@@ -879,7 +879,7 @@ 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);
-      adjust_debug_stmts_for_move (gsi_stmt (*bsi), NULL, NULL);
+      propagate_defs_into_debug_stmts (gsi_stmt (*bsi), NULL, NULL);
       gsi_replace (bsi, stmt2, true);
 
       return stmt1;
@@ -1060,7 +1060,7 @@ move_computations_stmt (struct dom_walk_
 
       mark_virtual_ops_for_renaming (stmt);
       gsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      adjust_debug_stmts_for_move (gsi_stmt (bsi), NULL, NULL);
+      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-05-12 03:48:10.000000000 -0300
+++ gcc/tree-ssa-reassoc.c	2009-07-10 16:28:23.000000000 -0300
@@ -1405,7 +1405,7 @@ rewrite_expr_tree (gimple stmt, unsigned
 	    {
 	      stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt1));
 	      gsirhs1 = gsi_for_stmt (stmt2);
-	      adjust_debug_stmts_for_move (stmt2, gimple_bb (stmt), &gsinow);
+	      propagate_defs_into_debug_stmts (stmt2, gimple_bb (stmt), &gsinow);
 	      gsi_move_before (&gsirhs1, &gsinow);
 	      gsi_prev (&gsinow);
 	      stmt1 = stmt2;
@@ -1452,7 +1452,7 @@ linearize_expr (gimple stmt)
 
   gsinow = gsi_for_stmt (stmt);
   gsirhs = gsi_for_stmt (binrhs);
-  adjust_debug_stmts_for_move (binrhs, gimple_bb (stmt), &gsinow);
+  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-07-05 04:19:54.000000000 -0300
+++ gcc/tree-ssa-sink.c	2009-07-10 16:28:23.000000000 -0300
@@ -388,7 +388,7 @@ statement_sink_location (gimple stmt, ba
       *togsi = gsi_after_labels (commondom);
 
       if (debug_stmts)
-	adjust_debug_stmts_for_move (stmt, commondom, togsi);
+	propagate_defs_into_debug_stmts (stmt, commondom, togsi);
 
       return true;
     }
@@ -408,7 +408,7 @@ statement_sink_location (gimple stmt, ba
 
       *togsi = gsi_for_stmt (use);
 
-      adjust_debug_stmts_for_move (stmt, sinkbb, togsi);
+      propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
 
       return true;
     }
@@ -443,7 +443,7 @@ statement_sink_location (gimple stmt, ba
 
   *togsi = gsi_after_labels (sinkbb);
 
-  adjust_debug_stmts_for_move (stmt, sinkbb, togsi);
+  propagate_defs_into_debug_stmts (stmt, sinkbb, togsi);
 
   return true;
 }
Index: gcc/tree-ssanames.c
===================================================================
--- gcc/tree-ssanames.c.orig	2009-05-12 03:54:34.000000000 -0300
+++ gcc/tree-ssanames.c	2009-07-10 16:28:57.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)
-	adjust_debug_stmts_for_var_def_move (var, NULL, NULL);
+	propagate_var_def_into_debug_stmts (var, NULL, NULL);
 
 #ifdef ENABLE_CHECKING
       verify_imm_links (stderr, var);
-- 
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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]