1 /* Infrastructure for tracking user variable locations and values
2    throughout compilation.
3    Copyright (C) 2010-2013 Free Software Foundation, Inc.
4    Contributed by Alexandre Oliva <aoliva@redhat.com>.
5 
6 This file is part of GCC.
7 
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
12 
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3.  If not see
20 <http://www.gnu.org/licenses/>.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "valtrack.h"
28 #include "function.h"
29 #include "regs.h"
30 #include "emit-rtl.h"
31 
32 /* gen_lowpart_no_emit hook implementation for DEBUG_INSNs.  In DEBUG_INSNs,
33    all lowpart SUBREGs are valid, despite what the machine requires for
34    instructions.  */
35 
36 static rtx
gen_lowpart_for_debug(enum machine_mode mode,rtx x)37 gen_lowpart_for_debug (enum machine_mode mode, rtx x)
38 {
39   rtx result = gen_lowpart_if_possible (mode, x);
40   if (result)
41     return result;
42 
43   if (GET_MODE (x) != VOIDmode)
44     return gen_rtx_raw_SUBREG (mode, x,
45 			       subreg_lowpart_offset (mode, GET_MODE (x)));
46 
47   return NULL_RTX;
48 }
49 
50 /* Replace auto-increment addressing modes with explicit operations to access
51    the same addresses without modifying the corresponding registers.  */
52 
53 static rtx
cleanup_auto_inc_dec(rtx src,enum machine_mode mem_mode ATTRIBUTE_UNUSED)54 cleanup_auto_inc_dec (rtx src, enum machine_mode mem_mode ATTRIBUTE_UNUSED)
55 {
56   rtx x = src;
57 #ifdef AUTO_INC_DEC
58   const RTX_CODE code = GET_CODE (x);
59   int i;
60   const char *fmt;
61 
62   switch (code)
63     {
64     case REG:
65     CASE_CONST_ANY:
66     case SYMBOL_REF:
67     case CODE_LABEL:
68     case PC:
69     case CC0:
70     case SCRATCH:
71       /* SCRATCH must be shared because they represent distinct values.  */
72       return x;
73     case CLOBBER:
74       /* Share clobbers of hard registers (like cc0), but do not share pseudo reg
75          clobbers or clobbers of hard registers that originated as pseudos.
76          This is needed to allow safe register renaming.  */
77       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
78 	  && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0)))
79 	return x;
80       break;
81 
82     case CONST:
83       if (shared_const_p (x))
84 	return x;
85       break;
86 
87     case MEM:
88       mem_mode = GET_MODE (x);
89       break;
90 
91     case PRE_INC:
92     case PRE_DEC:
93       gcc_assert (mem_mode != VOIDmode && mem_mode != BLKmode);
94       return gen_rtx_PLUS (GET_MODE (x),
95 			   cleanup_auto_inc_dec (XEXP (x, 0), mem_mode),
96 			   GEN_INT (code == PRE_INC
97 				    ? GET_MODE_SIZE (mem_mode)
98 				    : -GET_MODE_SIZE (mem_mode)));
99 
100     case POST_INC:
101     case POST_DEC:
102     case PRE_MODIFY:
103     case POST_MODIFY:
104       return cleanup_auto_inc_dec (code == PRE_MODIFY
105 				   ? XEXP (x, 1) : XEXP (x, 0),
106 				   mem_mode);
107 
108     default:
109       break;
110     }
111 
112   /* Copy the various flags, fields, and other information.  We assume
113      that all fields need copying, and then clear the fields that should
114      not be copied.  That is the sensible default behavior, and forces
115      us to explicitly document why we are *not* copying a flag.  */
116   x = shallow_copy_rtx (x);
117 
118   /* We do not copy the USED flag, which is used as a mark bit during
119      walks over the RTL.  */
120   RTX_FLAG (x, used) = 0;
121 
122   /* We do not copy FRAME_RELATED for INSNs.  */
123   if (INSN_P (x))
124     RTX_FLAG (x, frame_related) = 0;
125 
126   fmt = GET_RTX_FORMAT (code);
127   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
128     if (fmt[i] == 'e')
129       XEXP (x, i) = cleanup_auto_inc_dec (XEXP (x, i), mem_mode);
130     else if (fmt[i] == 'E' || fmt[i] == 'V')
131       {
132 	int j;
133 	XVEC (x, i) = rtvec_alloc (XVECLEN (x, i));
134 	for (j = 0; j < XVECLEN (x, i); j++)
135 	  XVECEXP (x, i, j)
136 	    = cleanup_auto_inc_dec (XVECEXP (src, i, j), mem_mode);
137       }
138 
139 #else /* !AUTO_INC_DEC */
140   x = copy_rtx (x);
141 #endif /* !AUTO_INC_DEC */
142 
143   return x;
144 }
145 
146 /* Auxiliary data structure for propagate_for_debug_stmt.  */
147 
148 struct rtx_subst_pair
149 {
150   rtx to;
151   bool adjusted;
152 };
153 
154 /* DATA points to an rtx_subst_pair.  Return the value that should be
155    substituted.  */
156 
157 static rtx
propagate_for_debug_subst(rtx from,const_rtx old_rtx,void * data)158 propagate_for_debug_subst (rtx from, const_rtx old_rtx, void *data)
159 {
160   struct rtx_subst_pair *pair = (struct rtx_subst_pair *)data;
161 
162   if (!rtx_equal_p (from, old_rtx))
163     return NULL_RTX;
164   if (!pair->adjusted)
165     {
166       pair->adjusted = true;
167       pair->to = cleanup_auto_inc_dec (pair->to, VOIDmode);
168       pair->to = make_compound_operation (pair->to, SET);
169       return pair->to;
170     }
171   return copy_rtx (pair->to);
172 }
173 
174 /* Replace all the occurrences of DEST with SRC in DEBUG_INSNs between INSN
175    and LAST, not including INSN, but including LAST.  Also stop at the end
176    of THIS_BASIC_BLOCK.  */
177 
178 void
propagate_for_debug(rtx insn,rtx last,rtx dest,rtx src,basic_block this_basic_block)179 propagate_for_debug (rtx insn, rtx last, rtx dest, rtx src,
180 		     basic_block this_basic_block)
181 {
182   rtx next, loc, end = NEXT_INSN (BB_END (this_basic_block));
183   rtx (*saved_rtl_hook_no_emit) (enum machine_mode, rtx);
184 
185   struct rtx_subst_pair p;
186   p.to = src;
187   p.adjusted = false;
188 
189   next = NEXT_INSN (insn);
190   last = NEXT_INSN (last);
191   saved_rtl_hook_no_emit = rtl_hooks.gen_lowpart_no_emit;
192   rtl_hooks.gen_lowpart_no_emit = gen_lowpart_for_debug;
193   while (next != last && next != end)
194     {
195       insn = next;
196       next = NEXT_INSN (insn);
197       if (DEBUG_INSN_P (insn))
198 	{
199 	  loc = simplify_replace_fn_rtx (INSN_VAR_LOCATION_LOC (insn),
200 					 dest, propagate_for_debug_subst, &p);
201 	  if (loc == INSN_VAR_LOCATION_LOC (insn))
202 	    continue;
203 	  INSN_VAR_LOCATION_LOC (insn) = loc;
204 	  df_insn_rescan (insn);
205 	}
206     }
207   rtl_hooks.gen_lowpart_no_emit = saved_rtl_hook_no_emit;
208 }
209 
210 /* Initialize DEBUG to an empty list, and clear USED, if given.  */
211 
212 void
dead_debug_global_init(struct dead_debug_global * debug,bitmap used)213 dead_debug_global_init (struct dead_debug_global *debug, bitmap used)
214 {
215   debug->used = used;
216   if (used)
217     bitmap_clear (used);
218 }
219 
220 /* Initialize DEBUG to an empty list, and clear USED, if given.  Link
221    back to GLOBAL, if given, and bring in used bits from it.  */
222 
223 void
dead_debug_local_init(struct dead_debug_local * debug,bitmap used,struct dead_debug_global * global)224 dead_debug_local_init (struct dead_debug_local *debug, bitmap used,
225 		       struct dead_debug_global *global)
226 {
227   if (!used && global && global->used)
228     used = BITMAP_ALLOC (NULL);
229 
230   debug->head = NULL;
231   debug->global = global;
232   debug->used = used;
233   debug->to_rescan = NULL;
234 
235   if (used)
236     {
237       if (global && global->used)
238 	bitmap_copy (used, global->used);
239       else
240 	bitmap_clear (used);
241     }
242 }
243 
244 /* Locate the entry for REG in GLOBAL->htab.  */
245 
246 static dead_debug_global_entry *
dead_debug_global_find(struct dead_debug_global * global,rtx reg)247 dead_debug_global_find (struct dead_debug_global *global, rtx reg)
248 {
249   dead_debug_global_entry temp_entry;
250   temp_entry.reg = reg;
251 
252   dead_debug_global_entry *entry = global->htab.find (&temp_entry);
253   gcc_checking_assert (entry && entry->reg == temp_entry.reg);
254 
255   return entry;
256 }
257 
258 /* Insert an entry mapping REG to DTEMP in GLOBAL->htab.  */
259 
260 static dead_debug_global_entry *
dead_debug_global_insert(struct dead_debug_global * global,rtx reg,rtx dtemp)261 dead_debug_global_insert (struct dead_debug_global *global, rtx reg, rtx dtemp)
262 {
263   dead_debug_global_entry temp_entry;
264   temp_entry.reg = reg;
265   temp_entry.dtemp = dtemp;
266 
267   if (!global->htab.is_created ())
268     global->htab.create (31);
269 
270   dead_debug_global_entry **slot = global->htab.find_slot (&temp_entry, INSERT);
271   gcc_checking_assert (!*slot);
272   *slot = XNEW (dead_debug_global_entry);
273   **slot = temp_entry;
274   return *slot;
275 }
276 
277 /* If UREGNO, referenced by USE, is a pseudo marked as used in GLOBAL,
278    replace it with with a USE of the debug temp recorded for it, and
279    return TRUE.  Otherwise, just return FALSE.
280 
281    If PTO_RESCAN is given, instead of rescanning modified INSNs right
282    away, add their UIDs to the bitmap, allocating one of *PTO_RESCAN
283    is NULL.  */
284 
285 static bool
dead_debug_global_replace_temp(struct dead_debug_global * global,df_ref use,unsigned int uregno,bitmap * pto_rescan)286 dead_debug_global_replace_temp (struct dead_debug_global *global,
287 				df_ref use, unsigned int uregno,
288 				bitmap *pto_rescan)
289 {
290   if (!global || uregno < FIRST_PSEUDO_REGISTER
291       || !global->used
292       || !REG_P (*DF_REF_REAL_LOC (use))
293       || REGNO (*DF_REF_REAL_LOC (use)) != uregno
294       || !bitmap_bit_p (global->used, uregno))
295     return false;
296 
297   dead_debug_global_entry *entry
298     = dead_debug_global_find (global, *DF_REF_REAL_LOC (use));
299   gcc_checking_assert (GET_CODE (entry->reg) == REG
300 		       && REGNO (entry->reg) == uregno);
301 
302   if (!entry->dtemp)
303     return true;
304 
305   *DF_REF_REAL_LOC (use) = entry->dtemp;
306   if (!pto_rescan)
307     df_insn_rescan (DF_REF_INSN (use));
308   else
309     {
310       if (!*pto_rescan)
311 	*pto_rescan = BITMAP_ALLOC (NULL);
312       bitmap_set_bit (*pto_rescan, INSN_UID (DF_REF_INSN (use)));
313     }
314 
315   return true;
316 }
317 
318 /* Reset all debug uses in HEAD, and clear DEBUG->to_rescan bits of
319    each reset insn.  DEBUG is not otherwise modified.  If HEAD is
320    DEBUG->head, DEBUG->head will be set to NULL at the end.
321    Otherwise, entries from DEBUG->head that pertain to reset insns
322    will be removed, and only then rescanned.  */
323 
324 static void
dead_debug_reset_uses(struct dead_debug_local * debug,struct dead_debug_use * head)325 dead_debug_reset_uses (struct dead_debug_local *debug,
326 		       struct dead_debug_use *head)
327 {
328   bool got_head = (debug->head == head);
329   bitmap rescan;
330   struct dead_debug_use **tailp = &debug->head;
331   struct dead_debug_use *cur;
332   bitmap_iterator bi;
333   unsigned int uid;
334 
335   if (got_head)
336     rescan = NULL;
337   else
338     rescan = BITMAP_ALLOC (NULL);
339 
340   while (head)
341     {
342       struct dead_debug_use *next = head->next;
343       rtx insn;
344 
345       insn = DF_REF_INSN (head->use);
346       if (!next || DF_REF_INSN (next->use) != insn)
347 	{
348 	  INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
349 	  if (got_head)
350 	    df_insn_rescan_debug_internal (insn);
351 	  else
352 	    bitmap_set_bit (rescan, INSN_UID (insn));
353 	  if (debug->to_rescan)
354 	    bitmap_clear_bit (debug->to_rescan, INSN_UID (insn));
355 	}
356       XDELETE (head);
357       head = next;
358     }
359 
360   if (got_head)
361     {
362       debug->head = NULL;
363       return;
364     }
365 
366   while ((cur = *tailp))
367     if (bitmap_bit_p (rescan, INSN_UID (DF_REF_INSN (cur->use))))
368       {
369 	*tailp = cur->next;
370 	XDELETE (cur);
371       }
372     else
373       tailp = &cur->next;
374 
375   EXECUTE_IF_SET_IN_BITMAP (rescan, 0, uid, bi)
376     {
377       struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
378       if (insn_info)
379 	df_insn_rescan_debug_internal (insn_info->insn);
380     }
381 
382   BITMAP_FREE (rescan);
383 }
384 
385 /* Promote pending local uses of pseudos in DEBUG to global
386    substitutions.  Uses of non-pseudos are left alone for
387    resetting.  */
388 
389 static void
dead_debug_promote_uses(struct dead_debug_local * debug)390 dead_debug_promote_uses (struct dead_debug_local *debug)
391 {
392   for (struct dead_debug_use *head = debug->head, **headp = &debug->head;
393        head; head = *headp)
394     {
395       rtx reg = *DF_REF_REAL_LOC (head->use);
396       df_ref ref;
397       dead_debug_global_entry *entry;
398 
399       if (GET_CODE (reg) != REG
400 	  || REGNO (reg) < FIRST_PSEUDO_REGISTER)
401 	{
402 	  headp = &head->next;
403 	  continue;
404 	}
405 
406       if (!debug->global->used)
407 	debug->global->used = BITMAP_ALLOC (NULL);
408 
409       bool added = bitmap_set_bit (debug->global->used, REGNO (reg));
410       gcc_checking_assert (added);
411 
412       entry = dead_debug_global_insert (debug->global, reg,
413 					make_debug_expr_from_rtl (reg));
414 
415       gcc_checking_assert (entry->dtemp);
416 
417       /* Tentatively remove the USE from the list.  */
418       *headp = head->next;
419 
420       if (!debug->to_rescan)
421 	debug->to_rescan = BITMAP_ALLOC (NULL);
422 
423       for (ref = DF_REG_USE_CHAIN (REGNO (reg)); ref;
424 	   ref = DF_REF_NEXT_REG (ref))
425 	if (DEBUG_INSN_P (DF_REF_INSN (ref)))
426 	  {
427 	    if (!dead_debug_global_replace_temp (debug->global, ref,
428 						 REGNO (reg),
429 						 &debug->to_rescan))
430 	      {
431 		rtx insn = DF_REF_INSN (ref);
432 		INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
433 		bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
434 	      }
435 	  }
436 
437       for (ref = DF_REG_DEF_CHAIN (REGNO (reg)); ref;
438 	   ref = DF_REF_NEXT_REG (ref))
439 	if (!dead_debug_insert_temp (debug, REGNO (reg), DF_REF_INSN (ref),
440 				     DEBUG_TEMP_BEFORE_WITH_VALUE))
441 	  {
442 	    rtx bind;
443 	    bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
444 					 DEBUG_EXPR_TREE_DECL (entry->dtemp),
445 					 gen_rtx_UNKNOWN_VAR_LOC (),
446 					 VAR_INIT_STATUS_INITIALIZED);
447 	    rtx insn = emit_debug_insn_before (bind, DF_REF_INSN (ref));
448 	    bitmap_set_bit (debug->to_rescan, INSN_UID (insn));
449 	  }
450 
451       entry->dtemp = NULL;
452       XDELETE (head);
453     }
454 }
455 
456 /* Reset all debug insns with pending uses.  Release the bitmap in it,
457    unless it is USED.  USED must be the same bitmap passed to
458    dead_debug_local_init.  */
459 
460 void
dead_debug_local_finish(struct dead_debug_local * debug,bitmap used)461 dead_debug_local_finish (struct dead_debug_local *debug, bitmap used)
462 {
463   if (debug->global)
464     dead_debug_promote_uses (debug);
465 
466   if (debug->used != used)
467     BITMAP_FREE (debug->used);
468 
469   dead_debug_reset_uses (debug, debug->head);
470 
471   if (debug->to_rescan)
472     {
473       bitmap_iterator bi;
474       unsigned int uid;
475 
476       EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi)
477 	{
478 	  struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
479 	  if (insn_info)
480 	    df_insn_rescan (insn_info->insn);
481 	}
482       BITMAP_FREE (debug->to_rescan);
483     }
484 }
485 
486 /* Release GLOBAL->used unless it is the same as USED.  Release the
487    mapping hash table if it was initialized.  */
488 
489 void
dead_debug_global_finish(struct dead_debug_global * global,bitmap used)490 dead_debug_global_finish (struct dead_debug_global *global, bitmap used)
491 {
492   if (global->used != used)
493     BITMAP_FREE (global->used);
494 
495   if (global->htab.is_created ())
496     global->htab.dispose ();
497 }
498 
499 /* Add USE to DEBUG, or substitute it right away if it's a pseudo in
500    the global substitution list.  USE must be a dead reference to
501    UREGNO in a debug insn.  Create a bitmap for DEBUG as needed.  */
502 
503 void
dead_debug_add(struct dead_debug_local * debug,df_ref use,unsigned int uregno)504 dead_debug_add (struct dead_debug_local *debug, df_ref use, unsigned int uregno)
505 {
506   if (dead_debug_global_replace_temp (debug->global, use, uregno,
507 				      &debug->to_rescan))
508     return;
509 
510   struct dead_debug_use *newddu = XNEW (struct dead_debug_use);
511 
512   newddu->use = use;
513   newddu->next = debug->head;
514   debug->head = newddu;
515 
516   if (!debug->used)
517     debug->used = BITMAP_ALLOC (NULL);
518 
519   /* ??? If we dealt with split multi-registers below, we should set
520      all registers for the used mode in case of hardware
521      registers.  */
522   bitmap_set_bit (debug->used, uregno);
523 }
524 
525 /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
526    before or after INSN (depending on WHERE), that binds a (possibly
527    global) debug temp to the widest-mode use of UREGNO, if WHERE is
528    *_WITH_REG, or the value stored in UREGNO by INSN otherwise, and
529    replace all uses of UREGNO in DEBUG with uses of the debug temp.
530    INSN must be where UREGNO dies, if WHERE is *_BEFORE_*, or where it
531    is set otherwise.  Return the number of debug insns emitted.  */
532 
533 int
dead_debug_insert_temp(struct dead_debug_local * debug,unsigned int uregno,rtx insn,enum debug_temp_where where)534 dead_debug_insert_temp (struct dead_debug_local *debug, unsigned int uregno,
535 			rtx insn, enum debug_temp_where where)
536 {
537   struct dead_debug_use **tailp = &debug->head;
538   struct dead_debug_use *cur;
539   struct dead_debug_use *uses = NULL;
540   struct dead_debug_use **usesp = &uses;
541   rtx reg = NULL_RTX;
542   rtx breg;
543   rtx dval = NULL_RTX;
544   rtx bind;
545   bool global;
546 
547   if (!debug->used)
548     return 0;
549 
550   global = (debug->global && debug->global->used
551 	    && bitmap_bit_p (debug->global->used, uregno));
552 
553   if (!global && !bitmap_clear_bit (debug->used, uregno))
554     return 0;
555 
556   /* Move all uses of uregno from debug->head to uses, setting mode to
557      the widest referenced mode.  */
558   while ((cur = *tailp))
559     {
560       if (DF_REF_REGNO (cur->use) == uregno)
561 	{
562 	  /* If this loc has been changed e.g. to debug_expr already
563 	     as part of a multi-register use, just drop it.  */
564 	  if (!REG_P (*DF_REF_REAL_LOC (cur->use)))
565 	    {
566 	      *tailp = cur->next;
567 	      XDELETE (cur);
568 	      continue;
569 	    }
570 	  *usesp = cur;
571 	  usesp = &cur->next;
572 	  *tailp = cur->next;
573 	  cur->next = NULL;
574 	  if (!reg
575 	      || (GET_MODE_BITSIZE (GET_MODE (reg))
576 		  < GET_MODE_BITSIZE (GET_MODE (*DF_REF_REAL_LOC (cur->use)))))
577 	    reg = *DF_REF_REAL_LOC (cur->use);
578 	}
579       else
580 	tailp = &(*tailp)->next;
581     }
582 
583   /* We may have dangling bits in debug->used for registers that were part
584      of a multi-register use, one component of which has been reset.  */
585   if (reg == NULL)
586     {
587       gcc_checking_assert (!uses);
588       if (!global)
589 	return 0;
590     }
591 
592   if (global)
593     {
594       if (!reg)
595 	reg = regno_reg_rtx[uregno];
596       dead_debug_global_entry *entry
597 	= dead_debug_global_find (debug->global, reg);
598       gcc_checking_assert (entry->reg == reg);
599       dval = entry->dtemp;
600       if (!dval)
601 	return 0;
602     }
603 
604   gcc_checking_assert (uses || global);
605 
606   breg = reg;
607   /* Recover the expression INSN stores in REG.  */
608   if (where == DEBUG_TEMP_BEFORE_WITH_VALUE)
609     {
610       rtx set = single_set (insn);
611       rtx dest, src;
612 
613       if (set)
614 	{
615 	  dest = SET_DEST (set);
616 	  src = SET_SRC (set);
617 	  /* Lose if the REG-setting insn is a CALL.  */
618 	  if (GET_CODE (src) == CALL)
619 	    {
620 	      while (uses)
621 		{
622 		  cur = uses->next;
623 		  XDELETE (uses);
624 		  uses = cur;
625 		}
626 	      return 0;
627 	    }
628 	}
629 
630       /* ??? Should we try to extract it from a PARALLEL?  */
631       if (!set)
632 	breg = NULL;
633       /* Cool, it's the same REG, we can use SRC.  */
634       else if (dest == reg)
635 	breg = cleanup_auto_inc_dec (src, VOIDmode);
636       else if (REG_P (dest))
637 	{
638 	  /* Hmm...  Something's fishy, we should be setting REG here.  */
639 	  if (REGNO (dest) != REGNO (reg))
640 	    breg = NULL;
641 	  /* If we're not overwriting all the hardware registers that
642 	     setting REG in its mode would, we won't know what to bind
643 	     the debug temp to.  ??? We could bind the debug_expr to a
644 	     CONCAT or PARALLEL with the split multi-registers, and
645 	     replace them as we found the corresponding sets.  */
646 	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
647 		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
648 		       != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
649 	    breg = NULL;
650 	  /* Ok, it's the same (hardware) REG, but with a different
651 	     mode, so SUBREG it.  */
652 	  else
653 	    breg = lowpart_subreg (GET_MODE (reg),
654 				   cleanup_auto_inc_dec (src, VOIDmode),
655 				   GET_MODE (dest));
656 	}
657       else if (GET_CODE (dest) == SUBREG)
658 	{
659 	  /* We should be setting REG here.  Lose.  */
660 	  if (REGNO (SUBREG_REG (dest)) != REGNO (reg))
661 	    breg = NULL;
662 	  /* Lose if we're setting something other than the lowpart of
663 	     REG.  */
664 	  else if (!subreg_lowpart_p (dest))
665 	    breg = NULL;
666 	  /* If we're not overwriting all the hardware registers that
667 	     setting REG in its mode would, we won't know what to bind
668 	     the debug temp to.  */
669 	  else if (REGNO (reg) < FIRST_PSEUDO_REGISTER
670 		   && (hard_regno_nregs[REGNO (reg)][GET_MODE (reg)]
671 		       != hard_regno_nregs[REGNO (reg)][GET_MODE (dest)]))
672 	    breg = NULL;
673 	  /* Yay, we can use SRC, just adjust its mode.  */
674 	  else
675 	    breg = lowpart_subreg (GET_MODE (reg),
676 				   cleanup_auto_inc_dec (src, VOIDmode),
677 				   GET_MODE (dest));
678 	}
679       /* Oh well, we're out of luck.  */
680       else
681 	breg = NULL;
682 
683       /* We couldn't figure out the value stored in REG, so reset all
684 	 of its pending debug uses.  */
685       if (!breg)
686 	{
687 	  dead_debug_reset_uses (debug, uses);
688 	  return 0;
689 	}
690     }
691 
692   /* If there's a single (debug) use of an otherwise unused REG, and
693      the debug use is not part of a larger expression, then it
694      probably doesn't make sense to introduce a new debug temp.  */
695   if (where == DEBUG_TEMP_AFTER_WITH_REG && !uses->next)
696     {
697       rtx next = DF_REF_INSN (uses->use);
698 
699       if (DEBUG_INSN_P (next) && reg == INSN_VAR_LOCATION_LOC (next))
700 	{
701 	  XDELETE (uses);
702 	  return 0;
703 	}
704     }
705 
706   if (!global)
707     /* Create DEBUG_EXPR (and DEBUG_EXPR_DECL).  */
708     dval = make_debug_expr_from_rtl (reg);
709 
710   /* Emit a debug bind insn before the insn in which reg dies.  */
711   bind = gen_rtx_VAR_LOCATION (GET_MODE (reg),
712 			       DEBUG_EXPR_TREE_DECL (dval), breg,
713 			       VAR_INIT_STATUS_INITIALIZED);
714 
715   if (where == DEBUG_TEMP_AFTER_WITH_REG
716       || where == DEBUG_TEMP_AFTER_WITH_REG_FORCE)
717     bind = emit_debug_insn_after (bind, insn);
718   else
719     bind = emit_debug_insn_before (bind, insn);
720   if (debug->to_rescan == NULL)
721     debug->to_rescan = BITMAP_ALLOC (NULL);
722   bitmap_set_bit (debug->to_rescan, INSN_UID (bind));
723 
724   /* Adjust all uses.  */
725   while ((cur = uses))
726     {
727       if (GET_MODE (*DF_REF_REAL_LOC (cur->use)) == GET_MODE (reg))
728 	*DF_REF_REAL_LOC (cur->use) = dval;
729       else
730 	*DF_REF_REAL_LOC (cur->use)
731 	  = gen_lowpart_SUBREG (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval);
732       /* ??? Should we simplify subreg of subreg?  */
733       bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use)));
734       uses = cur->next;
735       XDELETE (cur);
736     }
737 
738   return 1;
739 }
740