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]

Re: VTA merge - rtl compare-debug


rtl-compare-debug (53K) - fix -fcompare-debug errors that showed up in the
presence of debug insns

Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c.orig	2009-06-05 04:56:43.000000000 -0300
+++ gcc/regrename.c	2009-06-05 05:03:03.000000000 -0300
@@ -265,6 +265,7 @@ regrename_optimize (void)
 	  n_uses = 0;
 	  for (last = this_du; last->next_use; last = last->next_use)
 	    {
+	      /* ??? Do we need to discount debug insns here?  */
 	      n_uses++;
 	      IOR_COMPL_HARD_REG_SET (this_unavailable,
 				      reg_class_contents[last->cl]);
@@ -819,7 +820,8 @@ build_def_use (basic_block bb)
 	      *recog_data.dup_loc[i] = cc0_rtx;
 	    }
 
-	  scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_all_read,
+	  scan_rtx (insn, &PATTERN (insn), NO_REGS,
+		    DEBUG_INSN_P (insn) ? mark_access : terminate_all_read,
 		    OP_IN, 0);
 
 	  for (i = 0; i < recog_data.n_dups; i++)
Index: gcc/ira-conflicts.c
===================================================================
--- gcc/ira-conflicts.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/ira-conflicts.c	2009-06-05 05:08:11.000000000 -0300
@@ -522,7 +522,7 @@ add_copies (ira_loop_tree_node_t loop_tr
   if (bb == NULL)
     return;
   FOR_BB_INSNS (bb, insn)
-    if (INSN_P (insn))
+    if (NONDEBUG_INSN_P (insn))
       add_insn_allocno_copies (insn);
 }
 
Index: gcc/regstat.c
===================================================================
--- gcc/regstat.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/regstat.c	2009-06-05 05:08:11.000000000 -0300
@@ -61,11 +61,27 @@ regstat_init_n_sets_and_refs (void)
 
   regstat_n_sets_and_refs = XNEWVEC (struct regstat_n_sets_and_refs_t, max_regno);
 
-  for (i = 0; i < max_regno; i++)
-    {
-      SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
-      SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
-    }
+  if (MAY_HAVE_DEBUG_INSNS)
+    for (i = 0; i < max_regno; i++)
+      {
+	int use_count;
+	df_ref use;
+
+	use_count = DF_REG_USE_COUNT (i);
+	for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
+	  if (DF_REF_INSN_INFO (use) && DEBUG_INSN_P (DF_REF_INSN (use)))
+	    use_count--;
+
+
+	SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+	SET_REG_N_REFS (i, use_count + REG_N_SETS (i));
+      }
+  else
+    for (i = 0; i < max_regno; i++)
+      {
+	SET_REG_N_SETS (i, DF_REG_DEF_COUNT (i));
+	SET_REG_N_REFS (i, DF_REG_USE_COUNT (i) + REG_N_SETS (i));
+      }
   timevar_pop (TV_REG_STATS);
 
 }
@@ -149,7 +165,7 @@ regstat_bb_compute_ri (unsigned int bb_i
       struct df_mw_hardreg **mws_rec;
       rtx link;
  
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;
 
       /* Increment the live_length for all of the registers that
Index: gcc/reload.c
===================================================================
--- gcc/reload.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/reload.c	2009-06-05 05:07:56.000000000 -0300
@@ -6727,6 +6727,8 @@ find_equiv_reg (rtx goal, rtx insn, enum
   while (1)
     {
       p = PREV_INSN (p);
+      if (p && DEBUG_INSN_P (p))
+	continue;
       num++;
       if (p == 0 || LABEL_P (p)
 	  || num > PARAM_VALUE (PARAM_MAX_RELOAD_SEARCH_INSNS))
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/rtlanal.c	2009-06-05 05:08:11.000000000 -0300
@@ -741,7 +741,7 @@ reg_used_between_p (const_rtx reg, const
     return 0;
 
   for (insn = NEXT_INSN (from_insn); insn != to_insn; insn = NEXT_INSN (insn))
-    if (INSN_P (insn)
+    if (NONDEBUG_INSN_P (insn)
 	&& (reg_overlap_mentioned_p (reg, PATTERN (insn))
 	   || (CALL_P (insn) && find_reg_fusage (insn, USE, reg))))
       return 1;
@@ -2148,6 +2148,7 @@ side_effects_p (const_rtx x)
     case SCRATCH:
     case ADDR_VEC:
     case ADDR_DIFF_VEC:
+    case VAR_LOCATION:
       return 0;
 
     case CLOBBER:
@@ -4727,7 +4728,11 @@ canonicalize_condition (rtx insn, rtx co
 	 stop if it isn't a single set or if it has a REG_INC note because
 	 we don't want to bother dealing with it.  */
 
-      if ((prev = prev_nonnote_insn (prev)) == 0
+      do
+	prev = prev_nonnote_insn (prev);
+      while (prev && DEBUG_INSN_P (prev));
+
+      if (prev == 0
 	  || !NONJUMP_INSN_P (prev)
 	  || FIND_REG_INC_NOTE (prev, NULL_RTX)
 	  /* In cfglayout mode, there do not have to be labels at the
Index: gcc/final.c
===================================================================
--- gcc/final.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/final.c	2009-06-05 05:07:56.000000000 -0300
@@ -409,7 +409,8 @@ get_attr_length_1 (rtx insn ATTRIBUTE_UN
 
       case INSN:
 	body = PATTERN (insn);
-	if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER)
+	if (GET_CODE (body) == USE || GET_CODE (body) == CLOBBER
+	    || DEBUG_INSN_P (insn))
 	  return 0;
 
 	else if (GET_CODE (body) == ASM_INPUT || asm_noperands (body) >= 0)
Index: gcc/cfgloopanal.c
===================================================================
--- gcc/cfgloopanal.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/cfgloopanal.c	2009-06-05 05:08:11.000000000 -0300
@@ -174,8 +174,8 @@ num_loop_insns (const struct loop *loop)
     {
       bb = bbs[i];
       ninsns++;
-      for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
-	if (INSN_P (insn))
+      FOR_BB_INSNS (bb, insn)
+	if (NONDEBUG_INSN_P (insn))
 	  ninsns++;
     }
   free(bbs);
@@ -197,9 +197,9 @@ average_num_loop_insns (const struct loo
     {
       bb = bbs[i];
 
-      binsns = 1;
-      for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = NEXT_INSN (insn))
-	if (INSN_P (insn))
+      binsns = 0;
+      FOR_BB_INSNS (bb, insn)
+	if (NONDEBUG_INSN_P (insn))
 	  binsns++;
 
       ratio = loop->header->frequency == 0
Index: gcc/auto-inc-dec.c
===================================================================
--- gcc/auto-inc-dec.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/auto-inc-dec.c	2009-06-05 05:08:11.000000000 -0300
@@ -1341,7 +1341,7 @@ merge_in_block (int max_reg, basic_block
       unsigned int uid = INSN_UID (insn);
       bool insn_is_add_or_inc = true;
 
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;	
 
       /* This continue is deliberate.  We do not want the uses of the
@@ -1414,7 +1414,7 @@ merge_in_block (int max_reg, basic_block
       
       /* If the inc insn was merged with a mem, the inc insn is gone
 	 and there is noting to update.  */
-      if (DF_INSN_UID_GET(uid))
+      if (DF_INSN_UID_GET (uid))
 	{
 	  df_ref *def_rec;
 	  df_ref *use_rec;
Index: gcc/df-scan.c
===================================================================
--- gcc/df-scan.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/df-scan.c	2009-06-05 05:07:56.000000000 -0300
@@ -1361,6 +1361,62 @@ df_insn_rescan (rtx insn)
   return true;
 }
 
+/* Same as df_insn_rescan, but don't mark the basic block as
+   dirty.  */
+
+bool
+df_insn_rescan_debug_internal (rtx insn)
+{
+  unsigned int uid = INSN_UID (insn);
+  struct df_insn_info *insn_info;
+
+  gcc_assert (DEBUG_INSN_P (insn));
+  gcc_assert (VAR_LOC_UNKNOWN_P (INSN_VAR_LOCATION_LOC (insn)));
+
+  if (!df)
+    return false;
+
+  insn_info = DF_INSN_UID_SAFE_GET (INSN_UID (insn));
+  if (!insn_info)
+    return false;
+
+  if (dump_file)
+    fprintf (dump_file, "deleting debug_insn with uid = %d.\n", uid);
+
+  bitmap_clear_bit (df->insns_to_delete, uid);
+  bitmap_clear_bit (df->insns_to_rescan, uid);
+  bitmap_clear_bit (df->insns_to_notes_rescan, uid);
+
+  if (!insn_info->defs)
+    return false;
+
+  if (insn_info->defs == df_null_ref_rec
+      && insn_info->uses == df_null_ref_rec
+      && insn_info->eq_uses == df_null_ref_rec
+      && insn_info->mw_hardregs == df_null_mw_rec)
+    return false;
+
+  df_mw_hardreg_chain_delete (insn_info->mw_hardregs);
+
+  if (df_chain)
+    {
+      df_ref_chain_delete_du_chain (insn_info->defs);
+      df_ref_chain_delete_du_chain (insn_info->uses);
+      df_ref_chain_delete_du_chain (insn_info->eq_uses);
+    }
+
+  df_ref_chain_delete (insn_info->defs);
+  df_ref_chain_delete (insn_info->uses);
+  df_ref_chain_delete (insn_info->eq_uses);
+
+  insn_info->defs = df_null_ref_rec;
+  insn_info->uses = df_null_ref_rec;
+  insn_info->eq_uses = df_null_ref_rec;
+  insn_info->mw_hardregs = df_null_mw_rec;
+
+  return true;
+}
+
 
 /* Rescan all of the insns in the function.  Note that the artificial
    uses and defs are not touched.  This function will destroy def-se
@@ -3306,12 +3362,20 @@ df_uses_record (enum df_ref_class cl, st
 	break;
       }
 
+    case VAR_LOCATION:
+      df_uses_record (cl, collection_rec,
+		      &PAT_VAR_LOCATION_LOC (x),
+		      DF_REF_REG_USE, bb, insn_info,
+		      flags, width, offset, mode);
+      return;
+
     case PRE_DEC:
     case POST_DEC:
     case PRE_INC:
     case POST_INC:
     case PRE_MODIFY:
     case POST_MODIFY:
+      gcc_assert (!DEBUG_INSN_P (insn_info->insn));
       /* Catch the def of the register being modified.  */
       df_ref_record (cl, collection_rec, XEXP (x, 0), &XEXP (x, 0),
 		     bb, insn_info, 
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/ifcvt.c	2009-06-05 05:08:11.000000000 -0300
@@ -194,7 +194,7 @@ first_active_insn (basic_block bb)
       insn = NEXT_INSN (insn);
     }
 
-  while (NOTE_P (insn))
+  while (NOTE_P (insn) || DEBUG_INSN_P (insn))
     {
       if (insn == BB_END (bb))
 	return NULL_RTX;
@@ -217,6 +217,7 @@ last_active_insn (basic_block bb, int sk
 
   while (NOTE_P (insn)
 	 || JUMP_P (insn)
+	 || DEBUG_INSN_P (insn)
 	 || (skip_use_p
 	     && NONJUMP_INSN_P (insn)
 	     && GET_CODE (PATTERN (insn)) == USE))
@@ -269,7 +270,7 @@ cond_exec_process_insns (ce_if_block_t *
 
   for (insn = start; ; insn = NEXT_INSN (insn))
     {
-      if (NOTE_P (insn))
+      if (NOTE_P (insn) || DEBUG_INSN_P (insn))
 	goto insn_done;
 
       gcc_assert(NONJUMP_INSN_P (insn) || CALL_P (insn));
@@ -2256,6 +2257,8 @@ noce_process_if_block (struct noce_if_in
   else
     {
       insn_b = prev_nonnote_insn (if_info->cond_earliest);
+      while (insn_b && DEBUG_INSN_P (insn_b))
+	insn_b = prev_nonnote_insn (insn_b);
       /* We're going to be moving the evaluation of B down from above
 	 COND_EARLIEST to JUMP.  Make sure the relevant data is still
 	 intact.  */
@@ -2266,14 +2269,13 @@ noce_process_if_block (struct noce_if_in
 	  || ! rtx_equal_p (x, SET_DEST (set_b))
 	  || ! noce_operand_ok (SET_SRC (set_b))
 	  || reg_overlap_mentioned_p (x, SET_SRC (set_b))
-	  || modified_between_p (SET_SRC (set_b),
-				 PREV_INSN (if_info->cond_earliest), jump)
+	  || modified_between_p (SET_SRC (set_b), insn_b, jump)
 	  /* Likewise with X.  In particular this can happen when
 	     noce_get_condition looks farther back in the instruction
 	     stream than one might expect.  */
 	  || reg_overlap_mentioned_p (x, cond)
 	  || reg_overlap_mentioned_p (x, a)
-	  || modified_between_p (x, PREV_INSN (if_info->cond_earliest), jump))
+	  || modified_between_p (x, insn_b, jump))
 	insn_b = set_b = NULL_RTX;
     }
 
@@ -2474,6 +2476,8 @@ check_cond_move_block (basic_block bb, r
    /* We can only handle simple jumps at the end of the basic block.
       It is almost impossible to update the CFG otherwise.  */
   insn = BB_END (bb);
+  while (DEBUG_INSN_P (insn))
+    insn = PREV_INSN (insn);
   if (JUMP_P (insn) && !onlyjump_p (insn))
     return FALSE;
 
@@ -2481,7 +2485,7 @@ check_cond_move_block (basic_block bb, r
     {
       rtx set, dest, src;
 
-      if (!INSN_P (insn) || JUMP_P (insn))
+      if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
 	continue;
       set = single_set (insn);
       if (!set)
@@ -2559,7 +2563,8 @@ cond_move_convert_if_block (struct noce_
       rtx set, target, dest, t, e;
       unsigned int regno;
 
-      if (!INSN_P (insn) || JUMP_P (insn))
+      /* ??? Maybe emit conditional debug insn?  */
+      if (!NONDEBUG_INSN_P (insn) || JUMP_P (insn))
 	continue;
       set = single_set (insn);
       gcc_assert (set && REG_P (SET_DEST (set)));
@@ -3120,6 +3125,7 @@ block_jumps_and_fallthru_p (basic_block 
 
       if (INSN_P (insn)
 	  && !JUMP_P (insn)
+	  && !DEBUG_INSN_P (insn)
 	  && GET_CODE (PATTERN (insn)) != USE
 	  && GET_CODE (PATTERN (insn)) != CLOBBER)
 	n_insns++;
@@ -3787,6 +3793,9 @@ dead_or_predicable (basic_block test_bb,
   head = BB_HEAD (merge_bb);
   end = BB_END (merge_bb);
 
+  while (DEBUG_INSN_P (end) && end != head)
+    end = PREV_INSN (end);
+
   /* If merge_bb ends with a tablejump, predicating/moving insn's
      into test_bb and then deleting merge_bb will result in the jumptable
      that follows merge_bb being removed along with merge_bb and then we
@@ -3796,6 +3805,8 @@ dead_or_predicable (basic_block test_bb,
 
   if (LABEL_P (head))
     head = NEXT_INSN (head);
+  while (DEBUG_INSN_P (head) && head != end)
+    head = NEXT_INSN (head);
   if (NOTE_P (head))
     {
       if (head == end)
@@ -3804,6 +3815,8 @@ dead_or_predicable (basic_block test_bb,
 	  goto no_body;
 	}
       head = NEXT_INSN (head);
+      while (DEBUG_INSN_P (head) && head != end)
+	head = NEXT_INSN (head);
     }
 
   if (JUMP_P (end))
@@ -3814,6 +3827,8 @@ dead_or_predicable (basic_block test_bb,
 	  goto no_body;
 	}
       end = PREV_INSN (end);
+      while (DEBUG_INSN_P (end) && end != head)
+	end = PREV_INSN (end);
     }
 
   /* Disable handling dead code by conditional execution if the machine needs
@@ -3871,7 +3886,7 @@ dead_or_predicable (basic_block test_bb,
 	{
 	  if (CALL_P (insn))
 	    return FALSE;
-	  if (INSN_P (insn))
+	  if (NONDEBUG_INSN_P (insn))
 	    {
 	      if (may_trap_p (PATTERN (insn)))
 		return FALSE;
@@ -3917,7 +3932,7 @@ dead_or_predicable (basic_block test_bb,
 
       FOR_BB_INSNS (merge_bb, insn)
 	{
-	  if (INSN_P (insn))
+	  if (NONDEBUG_INSN_P (insn))
 	    {
 	      unsigned int uid = INSN_UID (insn);
 	      df_ref *def_rec;
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-lives.c	2009-06-05 05:08:11.000000000 -0300
@@ -894,7 +894,7 @@ process_bb_node_lives (ira_loop_tree_nod
 	  df_ref *def_rec, *use_rec;
 	  bool call_p;
 	  
-	  if (! INSN_P (insn))
+	  if (!NONDEBUG_INSN_P (insn))
 	    continue;
 	  
 	  if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
Index: gcc/regmove.c
===================================================================
--- gcc/regmove.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/regmove.c	2009-06-05 05:07:56.000000000 -0300
@@ -321,9 +321,12 @@ optimize_reg_copy_1 (rtx insn, rtx dest,
 	      /* For SREGNO, count the total number of insns scanned.
 		 For DREGNO, count the total number of insns scanned after
 		 passing the death note for DREGNO.  */
-	      s_length++;
-	      if (dest_death)
-		d_length++;
+	      if (!DEBUG_INSN_P (p))
+		{
+		  s_length++;
+		  if (dest_death)
+		    d_length++;
+		}
 
 	      /* If the insn in which SRC dies is a CALL_INSN, don't count it
 		 as a call that has been crossed.  Otherwise, count it.  */
@@ -767,7 +770,7 @@ fixup_match_2 (rtx insn, rtx dst, rtx sr
 
       if (find_regno_note (p, REG_DEAD, REGNO (dst)))
 	dst_death = p;
-      if (! dst_death)
+      if (! dst_death && !DEBUG_INSN_P (p))
 	length++;
 
       pset = single_set (p);
@@ -1095,7 +1098,8 @@ regmove_backward_pass (void)
 		  if (BLOCK_FOR_INSN (p) != bb)
 		    break;
 
-		  length++;
+		  if (!DEBUG_INSN_P (p))
+		    length++;
 
 		  /* ??? See if all of SRC is set in P.  This test is much
 		     more conservative than it needs to be.  */
@@ -1105,22 +1109,9 @@ regmove_backward_pass (void)
 		      /* We use validate_replace_rtx, in case there
 			 are multiple identical source operands.  All of
 			 them have to be changed at the same time.  */
+		      validate_change (p, &SET_DEST (pset), dst, 1);
 		      if (validate_replace_rtx (src, dst, insn))
-			{
-			  if (validate_change (p, &SET_DEST (pset),
-					       dst, 0))
-			    success = 1;
-			  else
-			    {
-			      /* Change all source operands back.
-				 This modifies the dst as a side-effect.  */
-			      validate_replace_rtx (dst, src, insn);
-			      /* Now make sure the dst is right.  */
-			      validate_change (insn,
-					       recog_data.operand_loc[match_no],
-					       dst, 0);
-			    }
-			}
+			success = 1;
 		      break;
 		    }
 
@@ -1129,9 +1120,21 @@ regmove_backward_pass (void)
 		     eliminate SRC. We can't make this change 
 		     if DST is mentioned at all in P,
 		     since we are going to change its value.  */
-		  if (reg_overlap_mentioned_p (src, PATTERN (p))
-		      || reg_mentioned_p (dst, PATTERN (p)))
-		    break;
+		  if (reg_overlap_mentioned_p (src, PATTERN (p)))
+		    {
+		      if (DEBUG_INSN_P (p))
+			validate_replace_rtx_group (dst, src, insn);
+		      else
+			break;
+		    }
+		  if (reg_mentioned_p (dst, PATTERN (p)))
+		    {
+		      if (DEBUG_INSN_P (p))
+			validate_change (p, &INSN_VAR_LOCATION_LOC (p),
+					 gen_rtx_UNKNOWN_VAR_LOC (), 1);
+		      else
+			break;
+		    }
 
 		  /* If we have passed a call instruction, and the
 		     pseudo-reg DST is not already live across a call,
@@ -1193,6 +1196,8 @@ regmove_backward_pass (void)
 
 		  break;
 		}
+	      else if (num_changes_pending () > 0)
+		cancel_changes (0);
 	    }
 
 	  /* If we weren't able to replace any of the alternatives, try an
Index: gcc/function.c
===================================================================
--- gcc/function.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/function.c	2009-06-05 05:07:56.000000000 -0300
@@ -1774,8 +1774,11 @@ instantiate_virtual_regs (void)
 	    || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
 	    || GET_CODE (PATTERN (insn)) == ASM_INPUT)
 	  continue;
-
-	instantiate_virtual_regs_in_insn (insn);
+	else if (DEBUG_INSN_P (insn))
+	  for_each_rtx (&INSN_VAR_LOCATION (insn),
+			instantiate_virtual_regs_in_rtx, NULL);
+	else
+	  instantiate_virtual_regs_in_insn (insn);
 
 	if (INSN_DELETED_P (insn))
 	  continue;
Index: gcc/df.h
===================================================================
--- gcc/df.h.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/df.h	2009-06-05 05:07:56.000000000 -0300
@@ -980,6 +980,7 @@ extern struct df_insn_info * df_insn_cre
 extern void df_insn_delete (basic_block, unsigned int);
 extern void df_bb_refs_record (int, bool);
 extern bool df_insn_rescan (rtx);
+extern bool df_insn_rescan_debug_internal (rtx);
 extern void df_insn_rescan_all (void);
 extern void df_process_deferred_rescans (void);
 extern void df_recompute_luids (basic_block);
Index: gcc/gcse.c
===================================================================
--- gcc/gcse.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/gcse.c	2009-06-05 05:08:11.000000000 -0300
@@ -2610,6 +2610,9 @@ cprop_insn (rtx insn)
 	}
     }
 
+  if (changed && DEBUG_INSN_P (insn))
+    return 0;
+
   return changed;
 }
 
@@ -3137,7 +3140,9 @@ bypass_conditional_jumps (void)
 	{
 	  setcc = NULL_RTX;
 	  FOR_BB_INSNS (bb, insn)
-	    if (NONJUMP_INSN_P (insn))
+	    if (DEBUG_INSN_P (insn))
+	      continue;
+	    else if (NONJUMP_INSN_P (insn))
 	      {
 		if (setcc)
 		  break;
@@ -4752,7 +4757,7 @@ compute_ld_motion_mems (void)
     {
       FOR_BB_INSNS (bb, insn)
 	{
-	  if (INSN_P (insn))
+	  if (NONDEBUG_INSN_P (insn))
 	    {
 	      if (GET_CODE (PATTERN (insn)) == SET)
 		{
Index: gcc/init-regs.c
===================================================================
--- gcc/init-regs.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/init-regs.c	2009-06-05 05:08:11.000000000 -0300
@@ -70,7 +70,7 @@ initialize_uninitialized_regs (void)
 	{
 	  unsigned int uid = INSN_UID (insn);
 	  df_ref *use_rec;
-	  if (!INSN_P (insn))
+	  if (!NONDEBUG_INSN_P (insn))
 	    continue;
 
 	  for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
Index: gcc/ira-build.c
===================================================================
--- gcc/ira-build.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-build.c	2009-06-05 05:08:11.000000000 -0300
@@ -1491,7 +1491,7 @@ create_bb_allocnos (ira_loop_tree_node_t
   curr_bb = bb = bb_node->bb;
   ira_assert (bb != NULL);
   FOR_BB_INSNS_REVERSE (bb, insn)
-    if (INSN_P (insn))
+    if (NONDEBUG_INSN_P (insn))
       create_insn_allocnos (PATTERN (insn), false);
   /* It might be a allocno living through from one subloop to
      another.  */
Index: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/cfgcleanup.c	2009-06-05 05:08:11.000000000 -0300
@@ -1086,10 +1086,10 @@ flow_find_cross_jump (int mode ATTRIBUTE
   while (true)
     {
       /* Ignore notes.  */
-      while (!INSN_P (i1) && i1 != BB_HEAD (bb1))
+      while (!NONDEBUG_INSN_P (i1) && i1 != BB_HEAD (bb1))
 	i1 = PREV_INSN (i1);
 
-      while (!INSN_P (i2) && i2 != BB_HEAD (bb2))
+      while (!NONDEBUG_INSN_P (i2) && i2 != BB_HEAD (bb2))
 	i2 = PREV_INSN (i2);
 
       if (i1 == BB_HEAD (bb1) || i2 == BB_HEAD (bb2))
@@ -1140,13 +1140,13 @@ flow_find_cross_jump (int mode ATTRIBUTE
      Two, it keeps line number notes as matched as may be.  */
   if (ninsns)
     {
-      while (last1 != BB_HEAD (bb1) && !INSN_P (PREV_INSN (last1)))
+      while (last1 != BB_HEAD (bb1) && !NONDEBUG_INSN_P (PREV_INSN (last1)))
 	last1 = PREV_INSN (last1);
 
       if (last1 != BB_HEAD (bb1) && LABEL_P (PREV_INSN (last1)))
 	last1 = PREV_INSN (last1);
 
-      while (last2 != BB_HEAD (bb2) && !INSN_P (PREV_INSN (last2)))
+      while (last2 != BB_HEAD (bb2) && !NONDEBUG_INSN_P (PREV_INSN (last2)))
 	last2 = PREV_INSN (last2);
 
       if (last2 != BB_HEAD (bb2) && LABEL_P (PREV_INSN (last2)))
@@ -1586,8 +1586,12 @@ try_crossjump_to_edge (int mode, edge e1
 	  /* Skip possible basic block header.  */
 	  if (LABEL_P (newpos2))
 	    newpos2 = NEXT_INSN (newpos2);
+	  while (DEBUG_INSN_P (newpos2))
+	    newpos2 = NEXT_INSN (newpos2);
 	  if (NOTE_P (newpos2))
 	    newpos2 = NEXT_INSN (newpos2);
+	  while (DEBUG_INSN_P (newpos2))
+	    newpos2 = NEXT_INSN (newpos2);
 	}
 
       if (dump_file)
@@ -1672,9 +1676,16 @@ try_crossjump_to_edge (int mode, edge e1
   /* Skip possible basic block header.  */
   if (LABEL_P (newpos1))
     newpos1 = NEXT_INSN (newpos1);
+
+  while (DEBUG_INSN_P (newpos1))
+    newpos1 = NEXT_INSN (newpos1);
+
   if (NOTE_INSN_BASIC_BLOCK_P (newpos1))
     newpos1 = NEXT_INSN (newpos1);
 
+  while (DEBUG_INSN_P (newpos1))
+    newpos1 = NEXT_INSN (newpos1);
+
   redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
   to_remove = single_succ (redirect_from);
 
Index: gcc/simplify-rtx.c
===================================================================
--- gcc/simplify-rtx.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/simplify-rtx.c	2009-06-05 05:07:56.000000000 -0300
@@ -202,6 +202,106 @@ avoid_constant_pool_reference (rtx x)
   return x;
 }
 
+/* Simplify a MEM based on its attributes.  This is the default
+   delegitimize_address target hook, and it's recommended that every
+   overrider call it.  */
+
+rtx
+delegitimize_mem_from_attrs (rtx x)
+{
+  if (MEM_P (x)
+      && MEM_EXPR (x)
+      && (!MEM_OFFSET (x)
+	  || GET_CODE (MEM_OFFSET (x)) == CONST_INT))
+    {
+      tree decl = MEM_EXPR (x);
+      enum machine_mode mode = GET_MODE (x);
+      HOST_WIDE_INT offset = 0;
+
+      switch (TREE_CODE (decl))
+	{
+	default:
+	  decl = NULL;
+	  break;
+
+	case VAR_DECL:
+	  break;
+
+	case ARRAY_REF:
+	case ARRAY_RANGE_REF:
+	case COMPONENT_REF:
+	case BIT_FIELD_REF:
+	case REALPART_EXPR:
+	case IMAGPART_EXPR:
+	case VIEW_CONVERT_EXPR:
+	  {
+	    HOST_WIDE_INT bitsize, bitpos;
+	    tree toffset;
+	    int unsignedp = 0, volatilep = 0;
+
+	    decl = get_inner_reference (decl, &bitsize, &bitpos, &toffset,
+					&mode, &unsignedp, &volatilep, false);
+	    if (bitsize != GET_MODE_BITSIZE (mode)
+		|| (bitpos % BITS_PER_UNIT)
+		|| (toffset && !host_integerp (toffset, 0)))
+	      decl = NULL;
+	    else
+	      {
+		offset += bitpos / BITS_PER_UNIT;
+		if (toffset)
+		  offset += TREE_INT_CST_LOW (toffset);
+	      }
+	    break;
+	  }
+	}
+
+      if (decl
+	  && mode == GET_MODE (x)
+	  && TREE_CODE (decl) == VAR_DECL
+	  && (TREE_STATIC (decl)
+	      || DECL_THREAD_LOCAL_P (decl))
+	  && DECL_RTL_SET_P (decl)
+	  && MEM_P (DECL_RTL (decl)))
+	{
+	  rtx newx;
+
+	  if (MEM_OFFSET (x))
+	    offset += INTVAL (MEM_OFFSET (x));
+
+	  newx = DECL_RTL (decl);
+
+	  if (MEM_P (newx))
+	    {
+	      rtx n = XEXP (newx, 0), o = XEXP (x, 0);
+
+	      /* Avoid creating a new MEM needlessly if we already had
+		 the same address.  We do if there's no OFFSET and the
+		 old address X is identical to NEWX, or if X is of the
+		 form (plus NEWX OFFSET), or the NEWX is of the form
+		 (plus Y (const_int Z)) and X is that with the offset
+		 added: (plus Y (const_int Z+OFFSET)).  */
+	      if (!((offset == 0
+		     || (GET_CODE (o) == PLUS
+			 && GET_CODE (XEXP (o, 1)) == CONST_INT
+			 && (offset == INTVAL (XEXP (o, 1))
+			     || (GET_CODE (n) == PLUS
+				 && GET_CODE (XEXP (n, 1)) == CONST_INT
+				 && (INTVAL (XEXP (n, 1)) + offset
+				     == INTVAL (XEXP (o, 1)))
+				 && (n = XEXP (n, 0))))
+			 && (o = XEXP (o, 0))))
+		    && rtx_equal_p (o, n)))
+		x = adjust_address_nv (newx, mode, offset);
+	    }
+	  else if (GET_MODE (x) == GET_MODE (newx)
+		   && offset == 0)
+	    x = newx;
+	}
+    }
+
+  return x;
+}
+
 /* Make a unary operation by first seeing if it folds and otherwise making
    the specified operation.  */
 
Index: gcc/loop-invariant.c
===================================================================
--- gcc/loop-invariant.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/loop-invariant.c	2009-06-05 05:08:11.000000000 -0300
@@ -912,7 +912,7 @@ find_invariants_bb (basic_block bb, bool
 
   FOR_BB_INSNS (bb, insn)
     {
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;
 
       find_invariants_insn (insn, always_reached, always_executed);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira.c	2009-06-05 05:08:11.000000000 -0300
@@ -2201,7 +2201,7 @@ memref_used_between_p (rtx memref, rtx s
   for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
        insn = NEXT_INSN (insn))
     {
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;
       
       if (memref_referenced_p (memref, PATTERN (insn)))
@@ -2645,7 +2645,7 @@ update_equiv_regs (void)
 		    }
 		  /* Move the initialization of the register to just before
 		     INSN.  Update the flow information.  */
-		  else if (PREV_INSN (insn) != equiv_insn)
+		  else if (prev_nondebug_insn (insn) != equiv_insn)
 		    {
 		      rtx new_insn;
 
Index: gcc/target-def.h
===================================================================
--- gcc/target-def.h.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/target-def.h	2009-06-05 05:07:56.000000000 -0300
@@ -488,7 +488,7 @@
 #define TARGET_CANNOT_COPY_INSN_P NULL
 #define TARGET_COMMUTATIVE_P hook_bool_const_rtx_commutative_p
 #define TARGET_LEGITIMIZE_ADDRESS default_legitimize_address
-#define TARGET_DELEGITIMIZE_ADDRESS hook_rtx_rtx_identity
+#define TARGET_DELEGITIMIZE_ADDRESS delegitimize_mem_from_attrs
 #define TARGET_LEGITIMATE_ADDRESS_P default_legitimate_address_p
 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P hook_bool_mode_const_rtx_false
 #define TARGET_MIN_ANCHOR_OFFSET 0
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/ira-costs.c	2009-06-05 05:08:11.000000000 -0300
@@ -995,7 +995,7 @@ scan_one_insn (rtx insn)
   rtx set, note;
   int i, k;
 
-  if (!INSN_P (insn))
+  if (!NONDEBUG_INSN_P (insn))
     return insn;
 
   pat_code = GET_CODE (PATTERN (insn));
@@ -1384,7 +1384,7 @@ process_bb_node_for_hard_reg_moves (ira_
     freq = 1;
   FOR_BB_INSNS (bb, insn)
     {
-      if (! INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;
       set = single_set (insn);
       if (set == NULL_RTX)
Index: gcc/combine.c
===================================================================
--- gcc/combine.c.orig	2009-06-05 05:07:48.000000000 -0300
+++ gcc/combine.c	2009-06-05 05:08:11.000000000 -0300
@@ -921,7 +921,7 @@ create_log_links (void)
     {
       FOR_BB_INSNS_REVERSE (bb, insn)
         {
-          if (!INSN_P (insn))
+          if (!NONDEBUG_INSN_P (insn))
             continue;
 
 	  /* Log links are created only once.  */
@@ -1129,7 +1129,7 @@ combine_instructions (rtx f, unsigned in
 	   insn = next ? next : NEXT_INSN (insn))
 	{
 	  next = 0;
-	  if (INSN_P (insn))
+	  if (NONDEBUG_INSN_P (insn))
 	    {
 	      /* See if we know about function return values before this
 		 insn based upon SUBREG flags.  */
@@ -2163,6 +2163,188 @@ reg_subword_p (rtx x, rtx reg)
 	 && GET_MODE_CLASS (GET_MODE (x)) == MODE_INT;
 }
 
+#ifdef AUTO_INC_DEC
+/* Replace auto-increment addressing modes with explicit operations to
+   access the same addresses without modifying the corresponding
+   registers.  If AFTER holds, SRC is meant to be reused after the
+   side effect, otherwise it is to be reused before that.  */
+
+static rtx
+cleanup_auto_inc_dec (rtx src, bool after, enum machine_mode mem_mode)
+{
+  rtx x = src, n, o;
+  const RTX_CODE code = GET_CODE (x);
+  int i;
+  const char *fmt;
+
+  switch (code)
+    {
+    case MEM:
+      mem_mode = GET_MODE (x);
+      break;
+
+    case PRE_INC:
+    case PRE_DEC:
+    case POST_INC:
+    case POST_DEC:
+      gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
+      if (after == (code == PRE_INC || code == PRE_DEC))
+	x = XEXP (x, 0);
+      else
+	x = gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+			  GEN_INT ((code == PRE_INC || code == POST_INC)
+				   ? GET_MODE_SIZE (mem_mode)
+				   : -GET_MODE_SIZE (mem_mode)));
+      return cleanup_auto_inc_dec (x, after, mem_mode);
+
+    case PRE_MODIFY:
+    case POST_MODIFY:
+      if (after == (code == PRE_MODIFY))
+	x = XEXP (x, 0);
+      else
+	x = XEXP (x, 1);
+      return cleanup_auto_inc_dec (x, after, mem_mode);
+
+    default:
+      break;
+    }
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    if (fmt[i] == 'e')
+      {
+	o = XEXP (x, i);
+	n = cleanup_auto_inc_dec (o, after, mem_mode);
+	if (o != n)
+	  {
+	    if (x == src)
+	      x = shallow_copy_rtx (x);
+	    XEXP (x, i) = n;
+	  }
+      }
+    else if (fmt[i] == 'E')
+      {
+	int j;
+	for (j = 0; j < XVECLEN (x, i); j++)
+	  {
+	    o = XVECEXP (x, i, j);
+	    n = cleanup_auto_inc_dec (o, after, mem_mode);
+	    if (o != n)
+	      {
+		if (x == src)
+		  x = shallow_copy_rtx (x);
+		XVECEXP (x, i, j) = n;
+	      }
+	  }
+      }
+
+  return x;
+}
+#endif
+
+/* Auxiliary data structure for propagate_for_debug_stmt.  */
+
+struct rtx_subst_pair
+{
+  rtx from, to;
+  bool changed;
+#ifdef AUTO_INC_DEC
+  bool adjusted;
+  bool after;
+#endif
+};
+
+/* Clean up any auto-updates in PAIR->to the first time it is called
+   for a PAIR.  PAIR->adjusted is used to tell whether we've cleaned
+   up before.  */
+
+static void
+auto_adjust_pair (struct rtx_subst_pair *pair ATTRIBUTE_UNUSED)
+{
+#ifdef AUTO_INC_DEC
+  if (!pair->adjusted)
+    {
+      pair->adjusted = true;
+      pair->to = cleanup_auto_inc_dec (pair->to, pair->after, VOIDmode);
+    }
+#endif
+}
+
+/* If *LOC is the same as FROM in the struct rtx_subst_pair passed as
+   DATA, replace it with a copy of TO.  Handle SUBREGs of *LOC as
+   well.  */
+
+static int
+propagate_for_debug_subst (rtx *loc, void *data)
+{
+  struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
+  rtx from = pair->from, to = pair->to;
+  rtx x = *loc, s = x;
+
+  if (rtx_equal_p (x, from)
+      || (GET_CODE (x) == SUBREG && rtx_equal_p ((s = SUBREG_REG (x)), from)))
+    {
+      auto_adjust_pair (pair);
+      if (pair->to != to)
+	to = pair->to;
+      else
+	to = copy_rtx (to);
+      if (s != x)
+	{
+	  gcc_assert (GET_CODE (x) == SUBREG && SUBREG_REG (x) == s);
+	  to = simplify_gen_subreg (GET_MODE (x), to,
+				    GET_MODE (from), SUBREG_BYTE (x));
+	}
+      *loc = to;
+      pair->changed = true;
+      return -1;
+    }
+
+  return 0;
+}
+
+/* Replace occurrences of DEST with SRC in DEBUG_INSNs between INSN
+   and LAST.  If MOVE holds, debug insns must also be moved past
+   LAST.  */
+
+static void
+propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src, bool move)
+{
+  struct rtx_subst_pair p;
+  rtx next, move_pos = move ? last : NULL_RTX;
+
+  p.from = dest;
+  p.to = src;
+  p.changed = false;
+
+#ifdef AUTO_INC_DEC
+  p.adjusted = false;
+  p.after = move;
+#endif
+
+  next = NEXT_INSN (insn);
+  while (next != last)
+    {
+      insn = next;
+      next = NEXT_INSN (insn);
+      if (DEBUG_INSN_P (insn))
+	{
+	  for_each_rtx (&INSN_VAR_LOCATION_LOC (insn),
+			propagate_for_debug_subst, &p);
+	  if (!p.changed)
+	    continue;
+	  p.changed = false;
+	  if (move_pos)
+	    {
+	      remove_insn (insn);
+	      PREV_INSN (insn) = NEXT_INSN (insn) = NULL_RTX;
+	      move_pos = emit_debug_insn_after (insn, move_pos);
+	    }
+	  else
+	    df_insn_rescan (insn);
+	}
+    }
+}
 
 /* Delete the conditional jump INSN and adjust the CFG correspondingly.
    Note that the INSN should be deleted *after* removing dead edges, so
@@ -2219,7 +2401,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
      I2 and not in I3, a REG_DEAD note must be made.  */
   rtx i3dest_killed = 0;
   /* SET_DEST and SET_SRC of I2 and I1.  */
-  rtx i2dest, i2src, i1dest = 0, i1src = 0;
+  rtx i2dest = 0, i2src = 0, i1dest = 0, i1src = 0;
   /* PATTERN (I1) and PATTERN (I2), or a copy of it in certain cases.  */
   rtx i1pat = 0, i2pat = 0;
   /* Indicates if I2DEST or I1DEST is in I2SRC or I1_SRC.  */
@@ -2293,7 +2475,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
       && GET_CODE (SET_DEST (PATTERN (i3))) != STRICT_LOW_PART
       && ! reg_overlap_mentioned_p (SET_SRC (PATTERN (i3)),
 				    SET_DEST (PATTERN (i3)))
-      && next_real_insn (i2) == i3)
+      && next_active_insn (i2) == i3)
     {
       rtx p2 = PATTERN (i2);
 
@@ -2326,6 +2508,7 @@ try_combine (rtx i3, rtx i2, rtx i1, int
 	      subst_low_luid = DF_INSN_LUID (i2);
 
 	      added_sets_2 = added_sets_1 = 0;
+	      i2src = SET_DEST (PATTERN (i3));
 	      i2dest = SET_SRC (PATTERN (i3));
 	      i2dest_killed = dead_or_set_p (i2, i2dest);
 
@@ -3588,12 +3771,18 @@ try_combine (rtx i3, rtx i2, rtx i1, int
 	PATTERN (i2) = newi2pat;
       }
     else
-      SET_INSN_DELETED (i2);
+      {
+	if (MAY_HAVE_DEBUG_INSNS && i2src)
+	  propagate_for_debug (i2, i3, i2dest, i2src, i3_subst_into_i2);
+	SET_INSN_DELETED (i2);
+      }
 
     if (i1)
       {
 	LOG_LINKS (i1) = 0;
 	REG_NOTES (i1) = 0;
+	if (MAY_HAVE_DEBUG_INSNS)
+	  propagate_for_debug (i1, i3, i1dest, i1src, false);
 	SET_INSN_DELETED (i1);
       }
 
@@ -12314,6 +12503,29 @@ reg_bitfield_target_p (rtx x, rtx body)
 
   return 0;
 }
+
+/* Return the next insn after INSN that is neither a NOTE nor a
+   DEBUG_INSN.  This routine does not look inside SEQUENCEs.  */
+
+static rtx
+next_nonnote_nondebug_insn (rtx insn)
+{
+  while (insn)
+    {
+      insn = NEXT_INSN (insn);
+      if (insn == 0)
+	break;
+      if (NOTE_P (insn))
+	continue;
+      if (DEBUG_INSN_P (insn))
+	continue;
+      break;
+    }
+
+  return insn;
+}
+
+
 
 /* Given a chain of REG_NOTES originally from FROM_INSN, try to place them
    as appropriate.  I3 and I2 are the insns resulting from the combination
@@ -12567,7 +12779,7 @@ distribute_notes (rtx notes, rtx from_in
 		place = from_insn;
 	      else if (reg_referenced_p (XEXP (note, 0), PATTERN (i3)))
 		place = i3;
-	      else if (i2 != 0 && next_nonnote_insn (i2) == i3
+	      else if (i2 != 0 && next_nonnote_nondebug_insn (i2) == i3
 		       && reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
 		place = i2;
 	      else if ((rtx_equal_p (XEXP (note, 0), elim_i2)
@@ -12585,7 +12797,7 @@ distribute_notes (rtx notes, rtx from_in
 
 	      for (tem = PREV_INSN (tem); place == 0; tem = PREV_INSN (tem))
 		{
-		  if (! INSN_P (tem))
+		  if (!NONDEBUG_INSN_P (tem))
 		    {
 		      if (tem == BB_HEAD (bb))
 			break;
@@ -12786,7 +12998,7 @@ distribute_notes (rtx notes, rtx from_in
 			    for (tem = PREV_INSN (place); ;
 				 tem = PREV_INSN (tem))
 			      {
-				if (! INSN_P (tem))
+				if (!NONDEBUG_INSN_P (tem))
 				  {
 				    if (tem == BB_HEAD (bb))
 			 	      break;
@@ -12876,7 +13088,9 @@ distribute_links (rtx links)
 	   (insn && (this_basic_block->next_bb == EXIT_BLOCK_PTR
 		     || BB_HEAD (this_basic_block->next_bb) != insn));
 	   insn = NEXT_INSN (insn))
-	if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
+	if (DEBUG_INSN_P (insn))
+	  continue;
+	else if (INSN_P (insn) && reg_overlap_mentioned_p (reg, PATTERN (insn)))
 	  {
 	    if (reg_referenced_p (reg, PATTERN (insn)))
 	      place = insn;
Index: gcc/resource.c
===================================================================
--- gcc/resource.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/resource.c	2009-06-05 05:07:56.000000000 -0300
@@ -975,6 +975,9 @@ mark_target_live_regs (rtx insns, rtx ta
 	  rtx real_insn = insn;
 	  enum rtx_code code = GET_CODE (insn);
 
+	  if (DEBUG_INSN_P (insn))
+	    continue;
+
 	  /* If this insn is from the target of a branch, it isn't going to
 	     be used in the sequel.  If it is used in both cases, this
 	     test will not be true.  */
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/df-problems.c	2009-06-05 05:08:11.000000000 -0300
@@ -877,7 +877,7 @@ df_lr_bb_local_compute (unsigned int bb_
     {
       unsigned int uid = INSN_UID (insn);
 
-      if (!INSN_P (insn))
+      if (!NONDEBUG_INSN_P (insn))
 	continue;	
 
       for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++)
@@ -3201,6 +3201,8 @@ df_set_note (enum reg_note note_type, rt
   rtx curr = old;
   rtx prev = NULL;
 
+  gcc_assert (!DEBUG_INSN_P (insn));
+
   while (curr)
     if (XEXP (curr, 0) == reg)
       {
@@ -3333,9 +3335,12 @@ df_whole_mw_reg_dead_p (struct df_mw_har
 static rtx
 df_set_dead_notes_for_mw (rtx insn, rtx old, struct df_mw_hardreg *mws,
 			  bitmap live, bitmap do_not_gen,
-			  bitmap artificial_uses)
+			  bitmap artificial_uses, bool *added_notes_p)
 {
   unsigned int r;
+  bool is_debug = *added_notes_p;
+
+  *added_notes_p = false;
   
 #ifdef REG_DEAD_DEBUGGING
   if (dump_file)
@@ -3353,6 +3358,11 @@ df_set_dead_notes_for_mw (rtx insn, rtx 
   if (df_whole_mw_reg_dead_p (mws, live, artificial_uses, do_not_gen))
     {
       /* Add a dead note for the entire multi word register.  */
+      if (is_debug)
+	{
+	  *added_notes_p = true;
+	  return old;
+	}
       old = df_set_note (REG_DEAD, insn, old, mws->mw_reg);
 #ifdef REG_DEAD_DEBUGGING
       df_print_note ("adding 1: ", insn, REG_NOTES (insn));
@@ -3365,6 +3375,11 @@ df_set_dead_notes_for_mw (rtx insn, rtx 
 	    && !bitmap_bit_p (artificial_uses, r)
 	    && !bitmap_bit_p (do_not_gen, r))
 	  {
+	    if (is_debug)
+	      {
+		*added_notes_p = true;
+		return old;
+	      }
 	    old = df_set_note (REG_DEAD, insn, old, regno_reg_rtx[r]);
 #ifdef REG_DEAD_DEBUGGING
 	    df_print_note ("adding 2: ", insn, REG_NOTES (insn));
@@ -3475,10 +3490,13 @@ df_note_bb_compute (unsigned int bb_inde
       struct df_mw_hardreg **mws_rec;
       rtx old_dead_notes;
       rtx old_unused_notes;
+      int debug_insn;
  
       if (!INSN_P (insn))
 	continue;
 
+      debug_insn = DEBUG_INSN_P (insn);
+
       bitmap_clear (do_not_gen);
       df_kill_notes (insn, &old_dead_notes, &old_unused_notes);
 
@@ -3563,10 +3581,18 @@ df_note_bb_compute (unsigned int bb_inde
 	  struct df_mw_hardreg *mws = *mws_rec; 
 	  if ((DF_MWS_REG_DEF_P (mws))  
 	      && !df_ignore_stack_reg (mws->start_regno))
-	    old_dead_notes
-	      = df_set_dead_notes_for_mw (insn, old_dead_notes, 
-					  mws, live, do_not_gen,
-					  artificial_uses);
+	    {
+	      bool really_add_notes = debug_insn != 0;
+
+	      old_dead_notes
+		= df_set_dead_notes_for_mw (insn, old_dead_notes,
+					    mws, live, do_not_gen,
+					    artificial_uses,
+					    &really_add_notes);
+
+	      if (really_add_notes)
+		debug_insn = -1;
+	    }
 	  mws_rec++;
 	}
 
@@ -3576,7 +3602,7 @@ df_note_bb_compute (unsigned int bb_inde
 	  unsigned int uregno = DF_REF_REGNO (use);
 
 #ifdef REG_DEAD_DEBUGGING
-	  if (dump_file)
+	  if (dump_file && !debug_insn)
 	    {
 	      fprintf (dump_file, "  regular looking at use ");
 	      df_ref_debug (use, dump_file);
@@ -3584,6 +3610,12 @@ df_note_bb_compute (unsigned int bb_inde
 #endif
 	  if (!bitmap_bit_p (live, uregno))
 	    {
+	      if (debug_insn)
+		{
+		  debug_insn = -1;
+		  break;
+		}
+
 	      if ( (!(DF_REF_FLAGS (use) & DF_REF_MW_HARDREG))
 		   && (!bitmap_bit_p (do_not_gen, uregno))
 		   && (!bitmap_bit_p (artificial_uses, uregno))
@@ -3615,6 +3647,14 @@ df_note_bb_compute (unsigned int bb_inde
 	  free_EXPR_LIST_node (old_dead_notes);
 	  old_dead_notes = next;
 	}
+
+      if (debug_insn == -1)
+	{
+	  /* ??? We could probably do better here, replacing dead
+	     registers with their definitions.  */
+	  INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+	  df_insn_rescan_debug_internal (insn);
+	}
     }
 }
 
@@ -3760,6 +3800,9 @@ df_simulate_uses (rtx insn, bitmap live)
   df_ref *use_rec;
   unsigned int uid = INSN_UID (insn);
 
+  if (DEBUG_INSN_P (insn))
+    return;
+
   for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++)
     {
       df_ref use = *use_rec;
@@ -3826,7 +3869,7 @@ df_simulate_initialize_backwards (basic_
 void 
 df_simulate_one_insn_backwards (basic_block bb, rtx insn, bitmap live)
 {
-  if (! INSN_P (insn))
+  if (!NONDEBUG_INSN_P (insn))
     return;	
   
   df_simulate_defs (insn, live);
Index: gcc/reg-stack.c
===================================================================
--- gcc/reg-stack.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/reg-stack.c	2009-06-05 05:07:56.000000000 -0300
@@ -1327,6 +1327,30 @@ compare_for_stack_reg (rtx insn, stack r
     }
 }
 
+/* Substitute new registers in LOC, which is part of a debug insn.
+   REGSTACK is the current register layout.  */
+
+static int
+subst_stack_regs_in_debug_insn (rtx *loc, void *data)
+{
+  rtx *tloc = get_true_reg (loc);
+  stack regstack = (stack)data;
+  int hard_regno;
+
+  if (!STACK_REG_P (*tloc))
+    return 0;
+
+  if (tloc != loc)
+    return 0;
+
+  hard_regno = get_hard_regnum (regstack, *loc);
+  gcc_assert (hard_regno >= FIRST_STACK_REG);
+
+  replace_reg (loc, hard_regno);
+
+  return -1;
+}
+
 /* Substitute new registers in PAT, which is part of INSN.  REGSTACK
    is the current register layout.  Return whether a control flow insn
    was deleted in the process.  */
@@ -1360,6 +1384,9 @@ subst_stack_regs_pat (rtx insn, stack re
 	 since the REG_DEAD notes are not issued.)  */
       break;
 
+    case VAR_LOCATION:
+      gcc_unreachable ();
+
     case CLOBBER:
       {
 	rtx note;
@@ -2871,6 +2898,7 @@ convert_regs_1 (basic_block block)
   int reg;
   rtx insn, next;
   bool control_flow_insn_deleted = false;
+  int debug_insns_with_starting_stack = 0;
 
   any_malformed_asm = false;
 
@@ -2923,8 +2951,25 @@ convert_regs_1 (basic_block block)
 
       /* Don't bother processing unless there is a stack reg
 	 mentioned or if it's a CALL_INSN.  */
-      if (stack_regs_mentioned (insn)
-	  || CALL_P (insn))
+      if (DEBUG_INSN_P (insn))
+	{
+	  if (starting_stack_p)
+	    debug_insns_with_starting_stack++;
+	  else
+	    {
+	      for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+			    &regstack);
+
+	      /* Nothing must ever die at a debug insn.  If something
+		 is referenced in it that becomes dead, it should have
+		 died before and the reference in the debug insn
+		 should have been removed so as to avoid changing code
+		 generation.  */
+	      gcc_assert (!REG_NOTES (insn));
+	    }
+	}
+      else if (stack_regs_mentioned (insn)
+	       || CALL_P (insn))
 	{
 	  if (dump_file)
 	    {
@@ -2938,6 +2983,24 @@ convert_regs_1 (basic_block block)
     }
   while (next);
 
+  if (debug_insns_with_starting_stack)
+    {
+      /* Since it's the first non-debug instruction that determines
+	 the stack requirements of the current basic block, we refrain
+	 from updating debug insns before it in the loop above, and
+	 fix them up here.  */
+      for (insn = BB_HEAD (block); debug_insns_with_starting_stack;
+	   insn = NEXT_INSN (insn))
+	{
+	  if (!DEBUG_INSN_P (insn))
+	    continue;
+
+	  debug_insns_with_starting_stack--;
+	  for_each_rtx (&PATTERN (insn), subst_stack_regs_in_debug_insn,
+			&bi->stack_in);
+	}
+    }
+
   if (dump_file)
     {
       fprintf (dump_file, "Expected live registers [");
Index: gcc/cfgrtl.c
===================================================================
--- gcc/cfgrtl.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/cfgrtl.c	2009-06-05 05:07:56.000000000 -0300
@@ -568,11 +568,15 @@ rtl_merge_blocks (basic_block a, basic_b
 {
   rtx b_head = BB_HEAD (b), b_end = BB_END (b), a_end = BB_END (a);
   rtx del_first = NULL_RTX, del_last = NULL_RTX;
+  rtx b_debug_start = b_end, b_debug_end = b_end;
   int b_empty = 0;
 
   if (dump_file)
     fprintf (dump_file, "merging block %d into block %d\n", b->index, a->index);
 
+  while (DEBUG_INSN_P (b_end))
+    b_end = PREV_INSN (b_debug_start = b_end);
+
   /* If there was a CODE_LABEL beginning B, delete it.  */
   if (LABEL_P (b_head))
     {
@@ -638,9 +642,21 @@ rtl_merge_blocks (basic_block a, basic_b
   /* Reassociate the insns of B with A.  */
   if (!b_empty)
     {
-      update_bb_for_insn_chain (a_end, b_end, a);
+      update_bb_for_insn_chain (a_end, b_debug_end, a);
 
-      a_end = b_end;
+      a_end = b_debug_end;
+    }
+  else if (b_end != b_debug_end)
+    {
+      /* Move any deleted labels and other notes between the end of A
+	 and the debug insns that make up B after the debug insns,
+	 bringing the debug insns into A while keeping the notes after
+	 the end of A.  */
+      if (NEXT_INSN (a_end) != b_debug_start)
+	reorder_insns_nobb (NEXT_INSN (a_end), PREV_INSN (b_debug_start),
+			    b_debug_end);
+      update_bb_for_insn_chain (b_debug_start, b_debug_end, a);
+      a_end = b_debug_end;
     }
 
   df_bb_delete (b->index);
@@ -2164,6 +2180,11 @@ purge_dead_edges (basic_block bb)
   bool found;
   edge_iterator ei;
 
+  if (DEBUG_INSN_P (insn) && insn != BB_HEAD (bb))
+    do
+      insn = PREV_INSN (insn);
+    while ((DEBUG_INSN_P (insn) || NOTE_P (insn)) && insn != BB_HEAD (bb));
+
   /* If this instruction cannot trap, remove REG_EH_REGION notes.  */
   if (NONJUMP_INSN_P (insn)
       && (note = find_reg_note (insn, REG_EH_REGION, NULL)))
@@ -2184,10 +2205,10 @@ purge_dead_edges (basic_block bb)
 	 latter can appear when nonlocal gotos are used.  */
       if (e->flags & EDGE_EH)
 	{
-	  if (can_throw_internal (BB_END (bb))
+	  if (can_throw_internal (insn)
 	      /* If this is a call edge, verify that this is a call insn.  */
 	      && (! (e->flags & EDGE_ABNORMAL_CALL)
-		  || CALL_P (BB_END (bb))))
+		  || CALL_P (insn)))
 	    {
 	      ei_next (&ei);
 	      continue;
@@ -2195,7 +2216,7 @@ purge_dead_edges (basic_block bb)
 	}
       else if (e->flags & EDGE_ABNORMAL_CALL)
 	{
-	  if (CALL_P (BB_END (bb))
+	  if (CALL_P (insn)
 	      && (! (note = find_reg_note (insn, REG_EH_REGION, NULL))
 		  || INTVAL (XEXP (note, 0)) >= 0))
 	    {
@@ -2773,7 +2794,8 @@ rtl_block_ends_with_call_p (basic_block 
   while (!CALL_P (insn)
 	 && insn != BB_HEAD (bb)
 	 && (keep_with_call_p (insn)
-	     || NOTE_P (insn)))
+	     || NOTE_P (insn)
+	     || DEBUG_INSN_P (insn)))
     insn = PREV_INSN (insn);
   return (CALL_P (insn));
 }
Index: gcc/dce.c
===================================================================
--- gcc/dce.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/dce.c	2009-06-05 05:07:56.000000000 -0300
@@ -124,6 +124,7 @@ deletable_insn_p (rtx insn, bool fast, b
   switch (GET_CODE (body))
     {
     case USE:
+    case VAR_LOCATION:
       return false;
 
     case CLOBBER:
@@ -643,6 +644,9 @@ mark_reg_dependencies (rtx insn)
   struct df_link *defs;
   df_ref *use_rec;
 
+  if (DEBUG_INSN_P (insn))
+    return;
+
   for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++)
     {
       df_ref use = *use_rec;
Index: gcc/regcprop.c
===================================================================
--- gcc/regcprop.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/regcprop.c	2009-06-05 05:08:11.000000000 -0300
@@ -450,7 +450,10 @@ replace_oldest_value_reg (rtx *loc, enum
 	fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
 		 INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
 
-      validate_change (insn, loc, new_rtx, 1);
+      if (DEBUG_INSN_P (insn))
+	*loc = new_rtx;
+      else
+	validate_change (insn, loc, new_rtx, 1);
       return true;
     }
   return false;
@@ -474,6 +477,9 @@ replace_oldest_value_addr (rtx *loc, enu
   switch (code)
     {
     case PLUS:
+      if (DEBUG_INSN_P (insn))
+	break;
+
       {
 	rtx orig_op0 = XEXP (x, 0);
 	rtx orig_op1 = XEXP (x, 1);
@@ -608,9 +614,14 @@ replace_oldest_value_addr (rtx *loc, enu
 static bool
 replace_oldest_value_mem (rtx x, rtx insn, struct value_data *vd)
 {
-  return replace_oldest_value_addr (&XEXP (x, 0),
-				    base_reg_class (GET_MODE (x), MEM,
-						    SCRATCH),
+  enum reg_class cl;
+
+  if (DEBUG_INSN_P (insn))
+    cl = ALL_REGS;
+  else
+    cl = base_reg_class (GET_MODE (x), MEM, SCRATCH);
+
+  return replace_oldest_value_addr (&XEXP (x, 0), cl,
 				    GET_MODE (x), insn, vd);
 }
 
@@ -619,7 +630,7 @@ replace_oldest_value_mem (rtx x, rtx ins
 static bool
 copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
 {
-  bool changed = false;
+  bool anything_changed = false;
   rtx insn;
 
   for (insn = BB_HEAD (bb); ; insn = NEXT_INSN (insn))
@@ -628,8 +639,22 @@ copyprop_hardreg_forward_1 (basic_block 
       bool is_asm, any_replacements;
       rtx set;
       bool replaced[MAX_RECOG_OPERANDS];
+      bool changed = false;
 
-      if (! INSN_P (insn))
+      if (DEBUG_INSN_P (insn))
+	{
+	  rtx loc = INSN_VAR_LOCATION_LOC (insn);
+	  if (!VAR_LOC_UNKNOWN_P (loc)
+	      && replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
+					    ALL_REGS, GET_MODE (loc),
+					    insn, vd))
+	    {
+	      df_insn_rescan (insn);
+	      anything_changed = true;
+	    }
+	}
+
+      if (!NONDEBUG_INSN_P (insn))
 	{
 	  if (insn == BB_END (bb))
 	    break;
@@ -817,6 +842,12 @@ copyprop_hardreg_forward_1 (basic_block 
 	}
 
     did_replacement:
+      if (changed)
+	{
+	  df_insn_rescan (insn);
+	  anything_changed = true;
+	}
+
       /* Clobber call-clobbered registers.  */
       if (CALL_P (insn))
 	for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
@@ -834,7 +865,7 @@ copyprop_hardreg_forward_1 (basic_block 
 	break;
     }
 
-  return changed;
+  return anything_changed;
 }
 
 /* Main entry point for the forward copy propagation optimization.  */
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c.orig	2009-06-05 05:07:49.000000000 -0300
+++ gcc/reload1.c	2009-06-05 05:08:11.000000000 -0300
@@ -800,7 +800,7 @@ reload (rtx first, int global)
 	  && GET_MODE (insn) != VOIDmode)
 	PUT_MODE (insn, VOIDmode);
 
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
 	scan_paradoxical_subregs (PATTERN (insn));
 
       if (set != 0 && REG_P (SET_DEST (set)))
@@ -1233,6 +1233,36 @@ reload (rtx first, int global)
 	  else if (reg_equiv_mem[i])
 	    XEXP (reg_equiv_mem[i], 0) = addr;
 	}
+
+      /* We don't want complex addressing modes in debug insns
+	 if simpler ones will do, so delegitimize equivalences
+	 in debug insns.  */
+      if (MAY_HAVE_DEBUG_INSNS && reg_renumber[i] < 0)
+	{
+	  rtx reg = regno_reg_rtx[i];
+	  rtx equiv = 0;
+	  df_ref use;
+
+	  if (reg_equiv_constant[i])
+	    equiv = reg_equiv_constant[i];
+	  else if (reg_equiv_invariant[i])
+	    equiv = reg_equiv_invariant[i];
+	  else if (reg && MEM_P (reg))
+	    {
+	      equiv = targetm.delegitimize_address (reg);
+	      if (equiv == reg)
+		equiv = 0;
+	    }
+	  else if (reg && REG_P (reg) && (int)REGNO (reg) != i)
+	    equiv = reg;
+
+	  if (equiv)
+	    for (use = DF_REG_USE_CHAIN (i); use;
+		 use = DF_REF_NEXT_REG (use))
+	      if (DEBUG_INSN_P (DF_REF_INSN (use))
+		  && *DF_REF_LOC (use) == reg)
+		*DF_REF_LOC (use) = copy_rtx (equiv);
+	}
     }
 
   /* We must set reload_completed now since the cleanup_subreg_operands call
@@ -3150,7 +3180,8 @@ eliminate_regs_in_insn (rtx insn, int re
 		  || GET_CODE (PATTERN (insn)) == CLOBBER
 		  || GET_CODE (PATTERN (insn)) == ADDR_VEC
 		  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-		  || GET_CODE (PATTERN (insn)) == ASM_INPUT);
+		  || GET_CODE (PATTERN (insn)) == ASM_INPUT
+		  || DEBUG_INSN_P (insn));
       return 0;
     }
 
@@ -6940,7 +6971,7 @@ emit_input_reload_insns (struct insn_cha
 				rl->when_needed, old, rl->out, j, 0))
     {
       rtx temp = PREV_INSN (insn);
-      while (temp && NOTE_P (temp))
+      while (temp && (NOTE_P (temp) || DEBUG_INSN_P (temp)))
 	temp = PREV_INSN (temp);
       if (temp
 	  && NONJUMP_INSN_P (temp)
@@ -6983,6 +7014,13 @@ emit_input_reload_insns (struct insn_cha
 		  alter_reg (REGNO (old), -1, false);
 		}
 	      special = 1;
+
+	      /* Adjust any debug insns between temp and insn.  */
+	      while ((temp = NEXT_INSN (temp)) != insn)
+		if (DEBUG_INSN_P (temp))
+		  replace_rtx (PATTERN (temp), old, reloadreg);
+		else
+		  gcc_assert (NOTE_P (temp));
 	    }
 	  else
 	    {
-- 
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]