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