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