annotate gcc/valtrack.c @ 131:84e7813d76e9

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