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

	PR debug/53740
	PR debug/52983
	PR debug/48866
	* dce.c (word_dce_process_block): Check whether inserting debug
	temps are needed even for needed insns.
	(dce_process_block): Likewise.
	* df-problems.c (dead_debug_add): Add comment about multi-regs.
	(dead_debug_insert_temp): Likewise.  Don't subreg when we're
	setting fewer regs than a multi-reg requires.

Index: gcc/dce.c
===================================================================
--- gcc/dce.c.orig	2012-06-27 02:29:32.290377543 -0300
+++ gcc/dce.c	2012-06-27 02:30:56.072721259 -0300
@@ -864,9 +864,12 @@ word_dce_process_block (basic_block bb, 
 	   anything in local_live.  */
 	if (marked_insn_p (insn))
 	  df_word_lr_simulate_uses (insn, local_live);
+
 	/* Insert debug temps for dead REGs used in subsequent debug
-	   insns.  */
-	else if (debug.used && !bitmap_empty_p (debug.used))
+	   insns.  We may have to emit a debug temp even if the insn
+	   was marked, in case the debug use was after the point of
+	   death.  */
+	if (debug.used && !bitmap_empty_p (debug.used))
 	  {
 	    df_ref *def_rec;
 
@@ -963,9 +966,12 @@ dce_process_block (basic_block bb, bool 
 	   anything in local_live.  */
 	if (needed)
 	  df_simulate_uses (insn, local_live);
+
 	/* Insert debug temps for dead REGs used in subsequent debug
-	   insns.  */
-	else if (debug.used && !bitmap_empty_p (debug.used))
+	   insns.  We may have to emit a debug temp even if the insn
+	   was marked, in case the debug use was after the point of
+	   death.  */
+	if (debug.used && !bitmap_empty_p (debug.used))
 	  for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++)
 	    dead_debug_insert_temp (&debug, DF_REF_REGNO (*def_rec), insn,
 				    DEBUG_TEMP_BEFORE_WITH_VALUE);
Index: gcc/df-problems.c
===================================================================
--- gcc/df-problems.c.orig	2012-06-27 02:30:45.000000000 -0300
+++ gcc/df-problems.c	2012-06-27 02:30:56.073721179 -0300
@@ -3179,6 +3179,9 @@ dead_debug_add (struct dead_debug *debug
   if (!debug->used)
     debug->used = BITMAP_ALLOC (NULL);
 
+  /* ??? If we dealt with split multi-registers below, we should set
+     all registers for the used mode in case of hardware
+     registers.  */
   bitmap_set_bit (debug->used, uregno);
 }
 
@@ -3269,6 +3272,15 @@ dead_debug_insert_temp (struct dead_debu
 	  /* Hmm...  Something's fishy, we should be setting REG here.  */
 	  if (REGNO (dest) != REGNO (reg))
 	    breg = NULL;
+	  /* If we're not overwriting all the hardware registers that
+	     setting REG in its mode would, we won't know what to bind
+	     the debug temp to.  ??? We could bind the debug_expr to a
+	     CONCAT or PARALLEL with the split multi-registers, and
+	     replace them as we found the corresponding sets.  */
+	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
+		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
+		       != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
+	    breg = NULL;
 	  /* Ok, it's the same (hardware) REG, but with a different
 	     mode, so SUBREG it.  */
 	  else
