Mercurial > hg > CbC > CbC_gcc
comparison gcc/dce.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* RTL dead code elimination. | 1 /* RTL dead code elimination. |
2 Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 | 2 Copyright (C) 2005-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 GCC is free software; you can redistribute it and/or modify it under | 6 GCC is free software; you can redistribute it and/or modify it under |
8 the terms of the GNU General Public License as published by the Free | 7 the terms of the GNU General Public License as published by the Free |
19 <http://www.gnu.org/licenses/>. */ | 18 <http://www.gnu.org/licenses/>. */ |
20 | 19 |
21 #include "config.h" | 20 #include "config.h" |
22 #include "system.h" | 21 #include "system.h" |
23 #include "coretypes.h" | 22 #include "coretypes.h" |
24 #include "hashtab.h" | 23 #include "backend.h" |
25 #include "tm.h" | |
26 #include "rtl.h" | 24 #include "rtl.h" |
27 #include "tree.h" | 25 #include "tree.h" |
28 #include "regs.h" | 26 #include "predict.h" |
29 #include "hard-reg-set.h" | |
30 #include "flags.h" | |
31 #include "except.h" | |
32 #include "df.h" | 27 #include "df.h" |
33 #include "cselib.h" | 28 #include "memmodel.h" |
29 #include "tm_p.h" | |
30 #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ | |
31 #include "cfgrtl.h" | |
32 #include "cfgbuild.h" | |
33 #include "cfgcleanup.h" | |
34 #include "dce.h" | 34 #include "dce.h" |
35 #include "timevar.h" | 35 #include "valtrack.h" |
36 #include "tree-pass.h" | 36 #include "tree-pass.h" |
37 #include "dbgcnt.h" | 37 #include "dbgcnt.h" |
38 #include "tm_p.h" | |
39 #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ | |
40 | 38 |
41 | 39 |
42 /* ------------------------------------------------------------------------- | 40 /* ------------------------------------------------------------------------- |
43 Core mark/delete routines | 41 Core mark/delete routines |
44 ------------------------------------------------------------------------- */ | 42 ------------------------------------------------------------------------- */ |
45 | 43 |
46 /* True if we are invoked while the df engine is running; in this case, | 44 /* True if we are invoked while the df engine is running; in this case, |
47 we don't want to reenter it. */ | 45 we don't want to reenter it. */ |
48 static bool df_in_progress = false; | 46 static bool df_in_progress = false; |
49 | 47 |
48 /* True if we are allowed to alter the CFG in this pass. */ | |
49 static bool can_alter_cfg = false; | |
50 | |
50 /* Instructions that have been marked but whose dependencies have not | 51 /* Instructions that have been marked but whose dependencies have not |
51 yet been processed. */ | 52 yet been processed. */ |
52 static VEC(rtx,heap) *worklist; | 53 static vec<rtx_insn *> worklist; |
53 | 54 |
54 /* Bitmap of instructions marked as needed indexed by INSN_UID. */ | 55 /* Bitmap of instructions marked as needed indexed by INSN_UID. */ |
55 static sbitmap marked; | 56 static sbitmap marked; |
56 | 57 |
57 /* Bitmap obstacks used for block processing by the fast algorithm. */ | 58 /* Bitmap obstacks used for block processing by the fast algorithm. */ |
58 static bitmap_obstack dce_blocks_bitmap_obstack; | 59 static bitmap_obstack dce_blocks_bitmap_obstack; |
59 static bitmap_obstack dce_tmp_bitmap_obstack; | 60 static bitmap_obstack dce_tmp_bitmap_obstack; |
60 | 61 |
61 static bool find_call_stack_args (rtx, bool, bool, bitmap); | 62 static bool find_call_stack_args (rtx_call_insn *, bool, bool, bitmap); |
62 | 63 |
63 /* A subroutine for which BODY is part of the instruction being tested; | 64 /* A subroutine for which BODY is part of the instruction being tested; |
64 either the top-level pattern, or an element of a PARALLEL. The | 65 either the top-level pattern, or an element of a PARALLEL. The |
65 instruction is known not to be a bare USE or CLOBBER. */ | 66 instruction is known not to be a bare USE or CLOBBER. */ |
66 | 67 |
88 | 89 |
89 /* Return true if INSN is a normal instruction that can be deleted by | 90 /* Return true if INSN is a normal instruction that can be deleted by |
90 the DCE pass. */ | 91 the DCE pass. */ |
91 | 92 |
92 static bool | 93 static bool |
93 deletable_insn_p (rtx insn, bool fast, bitmap arg_stores) | 94 deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores) |
94 { | 95 { |
95 rtx body, x; | 96 rtx body, x; |
96 int i; | 97 int i; |
98 df_ref def; | |
97 | 99 |
98 if (CALL_P (insn) | 100 if (CALL_P (insn) |
99 /* We cannot delete calls inside of the recursive dce because | 101 /* We cannot delete calls inside of the recursive dce because |
100 this may cause basic blocks to be deleted and this messes up | 102 this may cause basic blocks to be deleted and this messes up |
101 the rest of the stack of optimization passes. */ | 103 the rest of the stack of optimization passes. */ |
105 && (!SIBLING_CALL_P (insn)) | 107 && (!SIBLING_CALL_P (insn)) |
106 /* We can delete dead const or pure calls as long as they do not | 108 /* We can delete dead const or pure calls as long as they do not |
107 infinite loop. */ | 109 infinite loop. */ |
108 && (RTL_CONST_OR_PURE_CALL_P (insn) | 110 && (RTL_CONST_OR_PURE_CALL_P (insn) |
109 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) | 111 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) |
110 return find_call_stack_args (insn, false, fast, arg_stores); | 112 return find_call_stack_args (as_a <rtx_call_insn *> (insn), false, |
113 fast, arg_stores); | |
111 | 114 |
112 /* Don't delete jumps, notes and the like. */ | 115 /* Don't delete jumps, notes and the like. */ |
113 if (!NONJUMP_INSN_P (insn)) | 116 if (!NONJUMP_INSN_P (insn)) |
114 return false; | 117 return false; |
115 | 118 |
116 /* Don't delete insns that can throw. */ | 119 /* Don't delete insns that may throw if we cannot do so. */ |
117 if (!insn_nothrow_p (insn)) | 120 if (!(cfun->can_delete_dead_exceptions && can_alter_cfg) |
121 && !insn_nothrow_p (insn)) | |
118 return false; | 122 return false; |
123 | |
124 /* If INSN sets a global_reg, leave it untouched. */ | |
125 FOR_EACH_INSN_DEF (def, insn) | |
126 if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def)) | |
127 && global_regs[DF_REF_REGNO (def)]) | |
128 return false; | |
129 /* Initialization of pseudo PIC register should never be removed. */ | |
130 else if (DF_REF_REG (def) == pic_offset_table_rtx | |
131 && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) | |
132 return false; | |
119 | 133 |
120 body = PATTERN (insn); | 134 body = PATTERN (insn); |
121 switch (GET_CODE (body)) | 135 switch (GET_CODE (body)) |
122 { | 136 { |
123 case USE: | 137 case USE: |
152 | 166 |
153 | 167 |
154 /* Return true if INSN has been marked as needed. */ | 168 /* Return true if INSN has been marked as needed. */ |
155 | 169 |
156 static inline int | 170 static inline int |
157 marked_insn_p (rtx insn) | 171 marked_insn_p (rtx_insn *insn) |
158 { | 172 { |
159 /* Artificial defs are always needed and they do not have an insn. | 173 /* Artificial defs are always needed and they do not have an insn. |
160 We should never see them here. */ | 174 We should never see them here. */ |
161 gcc_assert (insn); | 175 gcc_assert (insn); |
162 return TEST_BIT (marked, INSN_UID (insn)); | 176 return bitmap_bit_p (marked, INSN_UID (insn)); |
163 } | 177 } |
164 | 178 |
165 | 179 |
166 /* If INSN has not yet been marked as needed, mark it now, and add it to | 180 /* If INSN has not yet been marked as needed, mark it now, and add it to |
167 the worklist. */ | 181 the worklist. */ |
168 | 182 |
169 static void | 183 static void |
170 mark_insn (rtx insn, bool fast) | 184 mark_insn (rtx_insn *insn, bool fast) |
171 { | 185 { |
172 if (!marked_insn_p (insn)) | 186 if (!marked_insn_p (insn)) |
173 { | 187 { |
174 if (!fast) | 188 if (!fast) |
175 VEC_safe_push (rtx, heap, worklist, insn); | 189 worklist.safe_push (insn); |
176 SET_BIT (marked, INSN_UID (insn)); | 190 bitmap_set_bit (marked, INSN_UID (insn)); |
177 if (dump_file) | 191 if (dump_file) |
178 fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn)); | 192 fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn)); |
179 if (CALL_P (insn) | 193 if (CALL_P (insn) |
180 && !df_in_progress | 194 && !df_in_progress |
181 && !SIBLING_CALL_P (insn) | 195 && !SIBLING_CALL_P (insn) |
182 && (RTL_CONST_OR_PURE_CALL_P (insn) | 196 && (RTL_CONST_OR_PURE_CALL_P (insn) |
183 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) | 197 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))) |
184 find_call_stack_args (insn, true, fast, NULL); | 198 find_call_stack_args (as_a <rtx_call_insn *> (insn), true, fast, NULL); |
185 } | 199 } |
186 } | 200 } |
187 | 201 |
188 | 202 |
189 /* A note_stores callback used by mark_nonreg_stores. DATA is the | 203 /* A note_stores callback used by mark_nonreg_stores. DATA is the |
191 | 205 |
192 static void | 206 static void |
193 mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data) | 207 mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data) |
194 { | 208 { |
195 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) | 209 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) |
196 mark_insn ((rtx) data, true); | 210 mark_insn ((rtx_insn *) data, true); |
197 } | 211 } |
198 | 212 |
199 | 213 |
200 /* A note_stores callback used by mark_nonreg_stores. DATA is the | 214 /* A note_stores callback used by mark_nonreg_stores. DATA is the |
201 instruction containing DEST. */ | 215 instruction containing DEST. */ |
202 | 216 |
203 static void | 217 static void |
204 mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data) | 218 mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data) |
205 { | 219 { |
206 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) | 220 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest)) |
207 mark_insn ((rtx) data, false); | 221 mark_insn ((rtx_insn *) data, false); |
208 } | 222 } |
209 | 223 |
210 | 224 |
211 /* Mark INSN if BODY stores to a non-register destination. */ | 225 /* Mark INSN if BODY stores to a non-register destination. */ |
212 | 226 |
213 static void | 227 static void |
214 mark_nonreg_stores (rtx body, rtx insn, bool fast) | 228 mark_nonreg_stores (rtx body, rtx_insn *insn, bool fast) |
215 { | 229 { |
216 if (fast) | 230 if (fast) |
217 note_stores (body, mark_nonreg_stores_1, insn); | 231 note_stores (body, mark_nonreg_stores_1, insn); |
218 else | 232 else |
219 note_stores (body, mark_nonreg_stores_2, insn); | 233 note_stores (body, mark_nonreg_stores_2, insn); |
220 } | 234 } |
221 | 235 |
222 | 236 |
223 /* Return true if store to MEM, starting OFF bytes from stack pointer, | 237 /* Return true if a store to SIZE bytes, starting OFF bytes from stack pointer, |
224 is a call argument store, and clear corresponding bits from SP_BYTES | 238 is a call argument store, and clear corresponding bits from SP_BYTES |
225 bitmap if it is. */ | 239 bitmap if it is. */ |
226 | 240 |
227 static bool | 241 static bool |
228 check_argument_store (rtx mem, HOST_WIDE_INT off, HOST_WIDE_INT min_sp_off, | 242 check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off, |
229 HOST_WIDE_INT max_sp_off, bitmap sp_bytes) | 243 HOST_WIDE_INT min_sp_off, HOST_WIDE_INT max_sp_off, |
244 bitmap sp_bytes) | |
230 { | 245 { |
231 HOST_WIDE_INT byte; | 246 HOST_WIDE_INT byte; |
232 for (byte = off; byte < off + GET_MODE_SIZE (GET_MODE (mem)); byte++) | 247 for (byte = off; byte < off + size; byte++) |
233 { | 248 { |
234 if (byte < min_sp_off | 249 if (byte < min_sp_off |
235 || byte >= max_sp_off | 250 || byte >= max_sp_off |
236 || !bitmap_clear_bit (sp_bytes, byte - min_sp_off)) | 251 || !bitmap_clear_bit (sp_bytes, byte - min_sp_off)) |
237 return false; | 252 return false; |
246 otherwise return false. This function should be first called | 261 otherwise return false. This function should be first called |
247 with DO_MARK false, and only when the CALL_INSN is actually | 262 with DO_MARK false, and only when the CALL_INSN is actually |
248 going to be marked called again with DO_MARK true. */ | 263 going to be marked called again with DO_MARK true. */ |
249 | 264 |
250 static bool | 265 static bool |
251 find_call_stack_args (rtx call_insn, bool do_mark, bool fast, | 266 find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast, |
252 bitmap arg_stores) | 267 bitmap arg_stores) |
253 { | 268 { |
254 rtx p, insn, prev_insn; | 269 rtx p; |
270 rtx_insn *insn, *prev_insn; | |
255 bool ret; | 271 bool ret; |
256 HOST_WIDE_INT min_sp_off, max_sp_off; | 272 HOST_WIDE_INT min_sp_off, max_sp_off; |
257 bitmap sp_bytes; | 273 bitmap sp_bytes; |
258 | 274 |
259 gcc_assert (CALL_P (call_insn)); | 275 gcc_assert (CALL_P (call_insn)); |
273 stored arguments. */ | 289 stored arguments. */ |
274 for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1)) | 290 for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1)) |
275 if (GET_CODE (XEXP (p, 0)) == USE | 291 if (GET_CODE (XEXP (p, 0)) == USE |
276 && MEM_P (XEXP (XEXP (p, 0), 0))) | 292 && MEM_P (XEXP (XEXP (p, 0), 0))) |
277 { | 293 { |
278 rtx mem = XEXP (XEXP (p, 0), 0), addr, size; | 294 rtx mem = XEXP (XEXP (p, 0), 0), addr; |
279 HOST_WIDE_INT off = 0; | 295 HOST_WIDE_INT off = 0, size; |
296 if (!MEM_SIZE_KNOWN_P (mem)) | |
297 return false; | |
280 size = MEM_SIZE (mem); | 298 size = MEM_SIZE (mem); |
281 if (size == NULL_RTX) | |
282 return false; | |
283 addr = XEXP (mem, 0); | 299 addr = XEXP (mem, 0); |
284 if (GET_CODE (addr) == PLUS | 300 if (GET_CODE (addr) == PLUS |
285 && REG_P (XEXP (addr, 0)) | 301 && REG_P (XEXP (addr, 0)) |
286 && CONST_INT_P (XEXP (addr, 1))) | 302 && CONST_INT_P (XEXP (addr, 1))) |
287 { | 303 { |
294 return false; | 310 return false; |
295 /* If not fast, use chains to see if addr wasn't set to | 311 /* If not fast, use chains to see if addr wasn't set to |
296 sp + offset. */ | 312 sp + offset. */ |
297 if (!fast) | 313 if (!fast) |
298 { | 314 { |
299 df_ref *use_rec; | 315 df_ref use; |
300 struct df_link *defs; | 316 struct df_link *defs; |
301 rtx set; | 317 rtx set; |
302 | 318 |
303 for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++) | 319 FOR_EACH_INSN_USE (use, call_insn) |
304 if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) | 320 if (rtx_equal_p (addr, DF_REF_REG (use))) |
305 break; | 321 break; |
306 | 322 |
307 if (*use_rec == NULL) | 323 if (use == NULL) |
308 return false; | 324 return false; |
309 | 325 |
310 for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) | 326 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) |
311 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) | 327 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) |
312 break; | 328 break; |
313 | 329 |
314 if (defs == NULL) | 330 if (defs == NULL) |
315 return false; | 331 return false; |
327 } | 343 } |
328 else | 344 else |
329 return false; | 345 return false; |
330 } | 346 } |
331 min_sp_off = MIN (min_sp_off, off); | 347 min_sp_off = MIN (min_sp_off, off); |
332 max_sp_off = MAX (max_sp_off, off + INTVAL (size)); | 348 max_sp_off = MAX (max_sp_off, off + size); |
333 } | 349 } |
334 | 350 |
335 if (min_sp_off >= max_sp_off) | 351 if (min_sp_off >= max_sp_off) |
336 return true; | 352 return true; |
337 sp_bytes = BITMAP_ALLOC (NULL); | 353 sp_bytes = BITMAP_ALLOC (NULL); |
353 off = INTVAL (XEXP (addr, 1)); | 369 off = INTVAL (XEXP (addr, 1)); |
354 addr = XEXP (addr, 0); | 370 addr = XEXP (addr, 0); |
355 } | 371 } |
356 if (addr != stack_pointer_rtx) | 372 if (addr != stack_pointer_rtx) |
357 { | 373 { |
358 df_ref *use_rec; | 374 df_ref use; |
359 struct df_link *defs; | 375 struct df_link *defs; |
360 rtx set; | 376 rtx set; |
361 | 377 |
362 for (use_rec = DF_INSN_USES (call_insn); *use_rec; use_rec++) | 378 FOR_EACH_INSN_USE (use, call_insn) |
363 if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) | 379 if (rtx_equal_p (addr, DF_REF_REG (use))) |
364 break; | 380 break; |
365 | 381 |
366 for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) | 382 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) |
367 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) | 383 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) |
368 break; | 384 break; |
369 | 385 |
370 set = single_set (DF_REF_INSN (defs->ref)); | 386 set = single_set (DF_REF_INSN (defs->ref)); |
371 off += INTVAL (XEXP (SET_SRC (set), 1)); | 387 off += INTVAL (XEXP (SET_SRC (set), 1)); |
372 } | 388 } |
373 for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++) | 389 for (byte = off; byte < off + MEM_SIZE (mem); byte++) |
374 { | 390 { |
375 if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) | 391 if (!bitmap_set_bit (sp_bytes, byte - min_sp_off)) |
376 gcc_unreachable (); | 392 gcc_unreachable (); |
377 } | 393 } |
378 } | 394 } |
385 { | 401 { |
386 rtx set, mem, addr; | 402 rtx set, mem, addr; |
387 HOST_WIDE_INT off; | 403 HOST_WIDE_INT off; |
388 | 404 |
389 if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn))) | 405 if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn))) |
390 prev_insn = NULL_RTX; | 406 prev_insn = NULL; |
391 else | 407 else |
392 prev_insn = PREV_INSN (insn); | 408 prev_insn = PREV_INSN (insn); |
393 | 409 |
394 if (CALL_P (insn)) | 410 if (CALL_P (insn)) |
395 break; | 411 break; |
418 { | 434 { |
419 if (!REG_P (addr)) | 435 if (!REG_P (addr)) |
420 break; | 436 break; |
421 if (!fast) | 437 if (!fast) |
422 { | 438 { |
423 df_ref *use_rec; | 439 df_ref use; |
424 struct df_link *defs; | 440 struct df_link *defs; |
425 rtx set; | 441 rtx set; |
426 | 442 |
427 for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) | 443 FOR_EACH_INSN_USE (use, insn) |
428 if (rtx_equal_p (addr, DF_REF_REG (*use_rec))) | 444 if (rtx_equal_p (addr, DF_REF_REG (use))) |
429 break; | 445 break; |
430 | 446 |
431 if (*use_rec == NULL) | 447 if (use == NULL) |
432 break; | 448 break; |
433 | 449 |
434 for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) | 450 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) |
435 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) | 451 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) |
436 break; | 452 break; |
437 | 453 |
438 if (defs == NULL) | 454 if (defs == NULL) |
439 break; | 455 break; |
451 } | 467 } |
452 else | 468 else |
453 break; | 469 break; |
454 } | 470 } |
455 | 471 |
456 if (GET_MODE_SIZE (GET_MODE (mem)) == 0 | 472 if (!MEM_SIZE_KNOWN_P (mem) |
457 || !check_argument_store (mem, off, min_sp_off, | 473 || !check_argument_store (MEM_SIZE (mem), off, min_sp_off, |
458 max_sp_off, sp_bytes)) | 474 max_sp_off, sp_bytes)) |
459 break; | 475 break; |
460 | 476 |
461 if (!deletable_insn_p (insn, fast, NULL)) | 477 if (!deletable_insn_p (insn, fast, NULL)) |
462 break; | 478 break; |
483 | 499 |
484 /* Remove all REG_EQUAL and REG_EQUIV notes referring to the registers INSN | 500 /* Remove all REG_EQUAL and REG_EQUIV notes referring to the registers INSN |
485 writes to. */ | 501 writes to. */ |
486 | 502 |
487 static void | 503 static void |
488 remove_reg_equal_equiv_notes_for_defs (rtx insn) | 504 remove_reg_equal_equiv_notes_for_defs (rtx_insn *insn) |
489 { | 505 { |
490 df_ref *def_rec; | 506 df_ref def; |
491 | 507 |
492 for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) | 508 FOR_EACH_INSN_DEF (def, insn) |
493 remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (*def_rec)); | 509 remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (def)); |
494 } | 510 } |
495 | 511 |
512 /* Scan all BBs for debug insns and reset those that reference values | |
513 defined in unmarked insns. */ | |
514 | |
515 static void | |
516 reset_unmarked_insns_debug_uses (void) | |
517 { | |
518 basic_block bb; | |
519 rtx_insn *insn, *next; | |
520 | |
521 FOR_EACH_BB_REVERSE_FN (bb, cfun) | |
522 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) | |
523 if (DEBUG_INSN_P (insn)) | |
524 { | |
525 df_ref use; | |
526 | |
527 FOR_EACH_INSN_USE (use, insn) | |
528 { | |
529 struct df_link *defs; | |
530 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) | |
531 { | |
532 rtx_insn *ref_insn; | |
533 if (DF_REF_IS_ARTIFICIAL (defs->ref)) | |
534 continue; | |
535 ref_insn = DF_REF_INSN (defs->ref); | |
536 if (!marked_insn_p (ref_insn)) | |
537 break; | |
538 } | |
539 if (!defs) | |
540 continue; | |
541 /* ??? FIXME could we propagate the values assigned to | |
542 each of the DEFs? */ | |
543 INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC (); | |
544 df_insn_rescan_debug_internal (insn); | |
545 break; | |
546 } | |
547 } | |
548 } | |
496 | 549 |
497 /* Delete every instruction that hasn't been marked. */ | 550 /* Delete every instruction that hasn't been marked. */ |
498 | 551 |
499 static void | 552 static void |
500 delete_unmarked_insns (void) | 553 delete_unmarked_insns (void) |
501 { | 554 { |
502 basic_block bb; | 555 basic_block bb; |
503 rtx insn, next; | 556 rtx_insn *insn, *next; |
504 bool must_clean = false; | 557 bool must_clean = false; |
505 | 558 |
506 FOR_EACH_BB_REVERSE (bb) | 559 FOR_EACH_BB_REVERSE_FN (bb, cfun) |
507 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) | 560 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next) |
508 if (INSN_P (insn)) | 561 if (NONDEBUG_INSN_P (insn)) |
509 { | 562 { |
510 /* Always delete no-op moves. */ | 563 /* Always delete no-op moves. */ |
511 if (noop_move_p (insn)) | 564 if (noop_move_p (insn)) |
512 ; | 565 ; |
513 | 566 |
534 to the stack pointer, this will almost always lead to a | 587 to the stack pointer, this will almost always lead to a |
535 miscompile. */ | 588 miscompile. */ |
536 if (!dbg_cnt (dce)) | 589 if (!dbg_cnt (dce)) |
537 continue; | 590 continue; |
538 | 591 |
592 if (crtl->shrink_wrapped_separate | |
593 && find_reg_note (insn, REG_CFA_RESTORE, NULL)) | |
594 { | |
595 if (dump_file) | |
596 fprintf (dump_file, "DCE: NOT deleting insn %d, it's a " | |
597 "callee-save restore\n", INSN_UID (insn)); | |
598 continue; | |
599 } | |
600 | |
539 if (dump_file) | 601 if (dump_file) |
540 fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); | 602 fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn)); |
541 | 603 |
542 /* Before we delete the insn we have to remove the REG_EQUAL notes | 604 /* Before we delete the insn we have to remove the REG_EQUAL notes |
543 for the destination regs in order to avoid dangling notes. */ | 605 for the destination regs in order to avoid dangling notes. */ |
565 | 627 |
566 static void | 628 static void |
567 prescan_insns_for_dce (bool fast) | 629 prescan_insns_for_dce (bool fast) |
568 { | 630 { |
569 basic_block bb; | 631 basic_block bb; |
570 rtx insn, prev; | 632 rtx_insn *insn, *prev; |
571 bitmap arg_stores = NULL; | 633 bitmap arg_stores = NULL; |
572 | 634 |
573 if (dump_file) | 635 if (dump_file) |
574 fprintf (dump_file, "Finding needed instructions:\n"); | 636 fprintf (dump_file, "Finding needed instructions:\n"); |
575 | 637 |
576 if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS) | 638 if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS) |
577 arg_stores = BITMAP_ALLOC (NULL); | 639 arg_stores = BITMAP_ALLOC (NULL); |
578 | 640 |
579 FOR_EACH_BB (bb) | 641 FOR_EACH_BB_FN (bb, cfun) |
580 { | 642 { |
581 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) | 643 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) |
582 if (INSN_P (insn)) | 644 if (NONDEBUG_INSN_P (insn)) |
583 { | 645 { |
584 /* Don't mark argument stores now. They will be marked | 646 /* Don't mark argument stores now. They will be marked |
585 if needed when the associated CALL is marked. */ | 647 if needed when the associated CALL is marked. */ |
586 if (arg_stores && bitmap_bit_p (arg_stores, INSN_UID (insn))) | 648 if (arg_stores && bitmap_bit_p (arg_stores, INSN_UID (insn))) |
587 continue; | 649 continue; |
612 static void | 674 static void |
613 mark_artificial_uses (void) | 675 mark_artificial_uses (void) |
614 { | 676 { |
615 basic_block bb; | 677 basic_block bb; |
616 struct df_link *defs; | 678 struct df_link *defs; |
617 df_ref *use_rec; | 679 df_ref use; |
618 | 680 |
619 FOR_ALL_BB (bb) | 681 FOR_ALL_BB_FN (bb, cfun) |
620 { | 682 FOR_EACH_ARTIFICIAL_USE (use, bb->index) |
621 for (use_rec = df_get_artificial_uses (bb->index); | 683 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next) |
622 *use_rec; use_rec++) | 684 if (!DF_REF_IS_ARTIFICIAL (defs->ref)) |
623 for (defs = DF_REF_CHAIN (*use_rec); defs; defs = defs->next) | 685 mark_insn (DF_REF_INSN (defs->ref), false); |
624 if (! DF_REF_IS_ARTIFICIAL (defs->ref)) | |
625 mark_insn (DF_REF_INSN (defs->ref), false); | |
626 } | |
627 } | 686 } |
628 | 687 |
629 | 688 |
630 /* Mark every instruction that defines a register value that INSN uses. */ | 689 /* Mark every instruction that defines a register value that INSN uses. */ |
631 | 690 |
632 static void | 691 static void |
633 mark_reg_dependencies (rtx insn) | 692 mark_reg_dependencies (rtx_insn *insn) |
634 { | 693 { |
635 struct df_link *defs; | 694 struct df_link *defs; |
636 df_ref *use_rec; | 695 df_ref use; |
637 | 696 |
638 if (DEBUG_INSN_P (insn)) | 697 if (DEBUG_INSN_P (insn)) |
639 return; | 698 return; |
640 | 699 |
641 for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) | 700 FOR_EACH_INSN_USE (use, insn) |
642 { | 701 { |
643 df_ref use = *use_rec; | |
644 if (dump_file) | 702 if (dump_file) |
645 { | 703 { |
646 fprintf (dump_file, "Processing use of "); | 704 fprintf (dump_file, "Processing use of "); |
647 print_simple_rtl (dump_file, DF_REF_REG (use)); | 705 print_simple_rtl (dump_file, DF_REF_REG (use)); |
648 fprintf (dump_file, " in insn %d:\n", INSN_UID (insn)); | 706 fprintf (dump_file, " in insn %d:\n", INSN_UID (insn)); |
660 init_dce (bool fast) | 718 init_dce (bool fast) |
661 { | 719 { |
662 if (!df_in_progress) | 720 if (!df_in_progress) |
663 { | 721 { |
664 if (!fast) | 722 if (!fast) |
665 df_chain_add_problem (DF_UD_CHAIN); | 723 { |
724 df_set_flags (DF_RD_PRUNE_DEAD_DEFS); | |
725 df_chain_add_problem (DF_UD_CHAIN); | |
726 } | |
666 df_analyze (); | 727 df_analyze (); |
667 } | 728 } |
668 | 729 |
669 if (dump_file) | 730 if (dump_file) |
670 df_dump (dump_file); | 731 df_dump (dump_file); |
671 | 732 |
672 if (fast) | 733 if (fast) |
673 { | 734 { |
674 bitmap_obstack_initialize (&dce_blocks_bitmap_obstack); | 735 bitmap_obstack_initialize (&dce_blocks_bitmap_obstack); |
675 bitmap_obstack_initialize (&dce_tmp_bitmap_obstack); | 736 bitmap_obstack_initialize (&dce_tmp_bitmap_obstack); |
676 } | 737 can_alter_cfg = false; |
738 } | |
739 else | |
740 can_alter_cfg = true; | |
677 | 741 |
678 marked = sbitmap_alloc (get_max_uid () + 1); | 742 marked = sbitmap_alloc (get_max_uid () + 1); |
679 sbitmap_zero (marked); | 743 bitmap_clear (marked); |
680 } | 744 } |
681 | 745 |
682 | 746 |
683 /* Free the data allocated by init_dce. */ | 747 /* Free the data allocated by init_dce. */ |
684 | 748 |
698 /* UD-chain based DCE. */ | 762 /* UD-chain based DCE. */ |
699 | 763 |
700 static unsigned int | 764 static unsigned int |
701 rest_of_handle_ud_dce (void) | 765 rest_of_handle_ud_dce (void) |
702 { | 766 { |
703 rtx insn; | 767 rtx_insn *insn; |
704 | 768 |
705 init_dce (false); | 769 init_dce (false); |
706 | 770 |
707 prescan_insns_for_dce (false); | 771 prescan_insns_for_dce (false); |
708 mark_artificial_uses (); | 772 mark_artificial_uses (); |
709 while (VEC_length (rtx, worklist) > 0) | 773 while (worklist.length () > 0) |
710 { | 774 { |
711 insn = VEC_pop (rtx, worklist); | 775 insn = worklist.pop (); |
712 mark_reg_dependencies (insn); | 776 mark_reg_dependencies (insn); |
713 } | 777 } |
714 VEC_free (rtx, heap, worklist); | 778 worklist.release (); |
779 | |
780 if (MAY_HAVE_DEBUG_INSNS) | |
781 reset_unmarked_insns_debug_uses (); | |
715 | 782 |
716 /* Before any insns are deleted, we must remove the chains since | 783 /* Before any insns are deleted, we must remove the chains since |
717 they are not bidirectional. */ | 784 they are not bidirectional. */ |
718 df_remove_problem (df_chain); | 785 df_remove_problem (df_chain); |
719 delete_unmarked_insns (); | 786 delete_unmarked_insns (); |
721 fini_dce (false); | 788 fini_dce (false); |
722 return 0; | 789 return 0; |
723 } | 790 } |
724 | 791 |
725 | 792 |
726 static bool | 793 namespace { |
727 gate_ud_dce (void) | 794 |
728 { | 795 const pass_data pass_data_ud_rtl_dce = |
729 return optimize > 1 && flag_dce | 796 { |
730 && dbg_cnt (dce_ud); | 797 RTL_PASS, /* type */ |
731 } | 798 "ud_dce", /* name */ |
732 | 799 OPTGROUP_NONE, /* optinfo_flags */ |
733 struct rtl_opt_pass pass_ud_rtl_dce = | 800 TV_DCE, /* tv_id */ |
734 { | 801 0, /* properties_required */ |
735 { | 802 0, /* properties_provided */ |
736 RTL_PASS, | 803 0, /* properties_destroyed */ |
737 "ud dce", /* name */ | 804 0, /* todo_flags_start */ |
738 gate_ud_dce, /* gate */ | 805 TODO_df_finish, /* todo_flags_finish */ |
739 rest_of_handle_ud_dce, /* execute */ | |
740 NULL, /* sub */ | |
741 NULL, /* next */ | |
742 0, /* static_pass_number */ | |
743 TV_DCE, /* tv_id */ | |
744 0, /* properties_required */ | |
745 0, /* properties_provided */ | |
746 0, /* properties_destroyed */ | |
747 0, /* todo_flags_start */ | |
748 TODO_dump_func | | |
749 TODO_df_finish | TODO_verify_rtl_sharing | | |
750 TODO_ggc_collect /* todo_flags_finish */ | |
751 } | |
752 }; | 806 }; |
807 | |
808 class pass_ud_rtl_dce : public rtl_opt_pass | |
809 { | |
810 public: | |
811 pass_ud_rtl_dce (gcc::context *ctxt) | |
812 : rtl_opt_pass (pass_data_ud_rtl_dce, ctxt) | |
813 {} | |
814 | |
815 /* opt_pass methods: */ | |
816 virtual bool gate (function *) | |
817 { | |
818 return optimize > 1 && flag_dce && dbg_cnt (dce_ud); | |
819 } | |
820 | |
821 virtual unsigned int execute (function *) | |
822 { | |
823 return rest_of_handle_ud_dce (); | |
824 } | |
825 | |
826 }; // class pass_ud_rtl_dce | |
827 | |
828 } // anon namespace | |
829 | |
830 rtl_opt_pass * | |
831 make_pass_ud_rtl_dce (gcc::context *ctxt) | |
832 { | |
833 return new pass_ud_rtl_dce (ctxt); | |
834 } | |
753 | 835 |
754 | 836 |
755 /* ------------------------------------------------------------------------- | 837 /* ------------------------------------------------------------------------- |
756 Fast DCE functions | 838 Fast DCE functions |
757 ------------------------------------------------------------------------- */ | 839 ------------------------------------------------------------------------- */ |
758 | 840 |
759 /* Process basic block BB. Return true if the live_in set has | 841 /* Process basic block BB. Return true if the live_in set has |
760 changed. REDO_OUT is true if the info at the bottom of the block | 842 changed. REDO_OUT is true if the info at the bottom of the block |
761 needs to be recalculated before starting. AU is the proper set of | 843 needs to be recalculated before starting. AU is the proper set of |
762 artificial uses. */ | 844 artificial uses. Track global substitution of uses of dead pseudos |
845 in debug insns using GLOBAL_DEBUG. */ | |
763 | 846 |
764 static bool | 847 static bool |
765 word_dce_process_block (basic_block bb, bool redo_out) | 848 word_dce_process_block (basic_block bb, bool redo_out, |
849 struct dead_debug_global *global_debug) | |
766 { | 850 { |
767 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); | 851 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); |
768 rtx insn; | 852 rtx_insn *insn; |
769 bool block_changed; | 853 bool block_changed; |
854 struct dead_debug_local debug; | |
770 | 855 |
771 if (redo_out) | 856 if (redo_out) |
772 { | 857 { |
773 /* Need to redo the live_out set of this block if when one of | 858 /* Need to redo the live_out set of this block if when one of |
774 the succs of this block has had a change in it live in | 859 the succs of this block has had a change in it live in |
786 fprintf (dump_file, "processing block %d live out = ", bb->index); | 871 fprintf (dump_file, "processing block %d live out = ", bb->index); |
787 df_print_word_regset (dump_file, DF_WORD_LR_OUT (bb)); | 872 df_print_word_regset (dump_file, DF_WORD_LR_OUT (bb)); |
788 } | 873 } |
789 | 874 |
790 bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); | 875 bitmap_copy (local_live, DF_WORD_LR_OUT (bb)); |
876 dead_debug_local_init (&debug, NULL, global_debug); | |
791 | 877 |
792 FOR_BB_INSNS_REVERSE (bb, insn) | 878 FOR_BB_INSNS_REVERSE (bb, insn) |
793 if (NONDEBUG_INSN_P (insn)) | 879 if (DEBUG_INSN_P (insn)) |
880 { | |
881 df_ref use; | |
882 FOR_EACH_INSN_USE (use, insn) | |
883 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER | |
884 && (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (use))) | |
885 == 2 * UNITS_PER_WORD) | |
886 && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use)) | |
887 && !bitmap_bit_p (local_live, 2 * DF_REF_REGNO (use) + 1)) | |
888 dead_debug_add (&debug, use, DF_REF_REGNO (use)); | |
889 } | |
890 else if (INSN_P (insn)) | |
794 { | 891 { |
795 bool any_changed; | 892 bool any_changed; |
893 | |
796 /* No matter if the instruction is needed or not, we remove | 894 /* No matter if the instruction is needed or not, we remove |
797 any regno in the defs from the live set. */ | 895 any regno in the defs from the live set. */ |
798 any_changed = df_word_lr_simulate_defs (insn, local_live); | 896 any_changed = df_word_lr_simulate_defs (insn, local_live); |
799 if (any_changed) | 897 if (any_changed) |
800 mark_insn (insn, true); | 898 mark_insn (insn, true); |
801 | 899 |
802 /* On the other hand, we do not allow the dead uses to set | 900 /* On the other hand, we do not allow the dead uses to set |
803 anything in local_live. */ | 901 anything in local_live. */ |
804 if (marked_insn_p (insn)) | 902 if (marked_insn_p (insn)) |
805 df_word_lr_simulate_uses (insn, local_live); | 903 df_word_lr_simulate_uses (insn, local_live); |
904 | |
905 /* Insert debug temps for dead REGs used in subsequent debug | |
906 insns. We may have to emit a debug temp even if the insn | |
907 was marked, in case the debug use was after the point of | |
908 death. */ | |
909 if (debug.used && !bitmap_empty_p (debug.used)) | |
910 { | |
911 df_ref def; | |
912 | |
913 FOR_EACH_INSN_DEF (def, insn) | |
914 dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, | |
915 marked_insn_p (insn) | |
916 && !control_flow_insn_p (insn) | |
917 ? DEBUG_TEMP_AFTER_WITH_REG_FORCE | |
918 : DEBUG_TEMP_BEFORE_WITH_VALUE); | |
919 } | |
806 | 920 |
807 if (dump_file) | 921 if (dump_file) |
808 { | 922 { |
809 fprintf (dump_file, "finished processing insn %d live out = ", | 923 fprintf (dump_file, "finished processing insn %d live out = ", |
810 INSN_UID (insn)); | 924 INSN_UID (insn)); |
814 | 928 |
815 block_changed = !bitmap_equal_p (local_live, DF_WORD_LR_IN (bb)); | 929 block_changed = !bitmap_equal_p (local_live, DF_WORD_LR_IN (bb)); |
816 if (block_changed) | 930 if (block_changed) |
817 bitmap_copy (DF_WORD_LR_IN (bb), local_live); | 931 bitmap_copy (DF_WORD_LR_IN (bb), local_live); |
818 | 932 |
933 dead_debug_local_finish (&debug, NULL); | |
819 BITMAP_FREE (local_live); | 934 BITMAP_FREE (local_live); |
820 return block_changed; | 935 return block_changed; |
821 } | 936 } |
822 | 937 |
823 | 938 |
824 /* Process basic block BB. Return true if the live_in set has | 939 /* Process basic block BB. Return true if the live_in set has |
825 changed. REDO_OUT is true if the info at the bottom of the block | 940 changed. REDO_OUT is true if the info at the bottom of the block |
826 needs to be recalculated before starting. AU is the proper set of | 941 needs to be recalculated before starting. AU is the proper set of |
827 artificial uses. */ | 942 artificial uses. Track global substitution of uses of dead pseudos |
943 in debug insns using GLOBAL_DEBUG. */ | |
828 | 944 |
829 static bool | 945 static bool |
830 dce_process_block (basic_block bb, bool redo_out, bitmap au) | 946 dce_process_block (basic_block bb, bool redo_out, bitmap au, |
947 struct dead_debug_global *global_debug) | |
831 { | 948 { |
832 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); | 949 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack); |
833 rtx insn; | 950 rtx_insn *insn; |
834 bool block_changed; | 951 bool block_changed; |
835 df_ref *def_rec; | 952 df_ref def; |
953 struct dead_debug_local debug; | |
836 | 954 |
837 if (redo_out) | 955 if (redo_out) |
838 { | 956 { |
839 /* Need to redo the live_out set of this block if when one of | 957 /* Need to redo the live_out set of this block if when one of |
840 the succs of this block has had a change in it live in | 958 the succs of this block has had a change in it live in |
854 } | 972 } |
855 | 973 |
856 bitmap_copy (local_live, DF_LR_OUT (bb)); | 974 bitmap_copy (local_live, DF_LR_OUT (bb)); |
857 | 975 |
858 df_simulate_initialize_backwards (bb, local_live); | 976 df_simulate_initialize_backwards (bb, local_live); |
977 dead_debug_local_init (&debug, NULL, global_debug); | |
859 | 978 |
860 FOR_BB_INSNS_REVERSE (bb, insn) | 979 FOR_BB_INSNS_REVERSE (bb, insn) |
861 if (INSN_P (insn)) | 980 if (DEBUG_INSN_P (insn)) |
981 { | |
982 df_ref use; | |
983 FOR_EACH_INSN_USE (use, insn) | |
984 if (!bitmap_bit_p (local_live, DF_REF_REGNO (use)) | |
985 && !bitmap_bit_p (au, DF_REF_REGNO (use))) | |
986 dead_debug_add (&debug, use, DF_REF_REGNO (use)); | |
987 } | |
988 else if (INSN_P (insn)) | |
862 { | 989 { |
863 bool needed = marked_insn_p (insn); | 990 bool needed = marked_insn_p (insn); |
864 | 991 |
865 /* The insn is needed if there is someone who uses the output. */ | 992 /* The insn is needed if there is someone who uses the output. */ |
866 if (!needed) | 993 if (!needed) |
867 for (def_rec = DF_INSN_DEFS (insn); *def_rec; def_rec++) | 994 FOR_EACH_INSN_DEF (def, insn) |
868 if (bitmap_bit_p (local_live, DF_REF_REGNO (*def_rec)) | 995 if (bitmap_bit_p (local_live, DF_REF_REGNO (def)) |
869 || bitmap_bit_p (au, DF_REF_REGNO (*def_rec))) | 996 || bitmap_bit_p (au, DF_REF_REGNO (def))) |
870 { | 997 { |
871 needed = true; | 998 needed = true; |
872 mark_insn (insn, true); | 999 mark_insn (insn, true); |
873 break; | 1000 break; |
874 } | 1001 } |
879 | 1006 |
880 /* On the other hand, we do not allow the dead uses to set | 1007 /* On the other hand, we do not allow the dead uses to set |
881 anything in local_live. */ | 1008 anything in local_live. */ |
882 if (needed) | 1009 if (needed) |
883 df_simulate_uses (insn, local_live); | 1010 df_simulate_uses (insn, local_live); |
1011 | |
1012 /* Insert debug temps for dead REGs used in subsequent debug | |
1013 insns. We may have to emit a debug temp even if the insn | |
1014 was marked, in case the debug use was after the point of | |
1015 death. */ | |
1016 if (debug.used && !bitmap_empty_p (debug.used)) | |
1017 FOR_EACH_INSN_DEF (def, insn) | |
1018 dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn, | |
1019 needed && !control_flow_insn_p (insn) | |
1020 ? DEBUG_TEMP_AFTER_WITH_REG_FORCE | |
1021 : DEBUG_TEMP_BEFORE_WITH_VALUE); | |
884 } | 1022 } |
885 | 1023 |
1024 dead_debug_local_finish (&debug, NULL); | |
886 df_simulate_finalize_backwards (bb, local_live); | 1025 df_simulate_finalize_backwards (bb, local_live); |
887 | 1026 |
888 block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb)); | 1027 block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb)); |
889 if (block_changed) | 1028 if (block_changed) |
890 bitmap_copy (DF_LR_IN (bb), local_live); | 1029 bitmap_copy (DF_LR_IN (bb), local_live); |
917 bb_has_eh_pred once per insn, so we cache the information | 1056 bb_has_eh_pred once per insn, so we cache the information |
918 here. */ | 1057 here. */ |
919 bitmap au = &df->regular_block_artificial_uses; | 1058 bitmap au = &df->regular_block_artificial_uses; |
920 bitmap au_eh = &df->eh_block_artificial_uses; | 1059 bitmap au_eh = &df->eh_block_artificial_uses; |
921 int i; | 1060 int i; |
1061 struct dead_debug_global global_debug; | |
922 | 1062 |
923 prescan_insns_for_dce (true); | 1063 prescan_insns_for_dce (true); |
924 | 1064 |
925 for (i = 0; i < n_blocks; i++) | 1065 for (i = 0; i < n_blocks; i++) |
926 bitmap_set_bit (all_blocks, postorder[i]); | 1066 bitmap_set_bit (all_blocks, postorder[i]); |
1067 | |
1068 dead_debug_global_init (&global_debug, NULL); | |
927 | 1069 |
928 while (global_changed) | 1070 while (global_changed) |
929 { | 1071 { |
930 global_changed = false; | 1072 global_changed = false; |
931 | 1073 |
932 for (i = 0; i < n_blocks; i++) | 1074 for (i = 0; i < n_blocks; i++) |
933 { | 1075 { |
934 int index = postorder[i]; | 1076 int index = postorder[i]; |
935 basic_block bb = BASIC_BLOCK (index); | 1077 basic_block bb = BASIC_BLOCK_FOR_FN (cfun, index); |
936 bool local_changed; | 1078 bool local_changed; |
937 | 1079 |
938 if (index < NUM_FIXED_BLOCKS) | 1080 if (index < NUM_FIXED_BLOCKS) |
939 { | 1081 { |
940 bitmap_set_bit (processed, index); | 1082 bitmap_set_bit (processed, index); |
941 continue; | 1083 continue; |
942 } | 1084 } |
943 | 1085 |
944 if (word_level) | 1086 if (word_level) |
945 local_changed | 1087 local_changed |
946 = word_dce_process_block (bb, bitmap_bit_p (redo_out, index)); | 1088 = word_dce_process_block (bb, bitmap_bit_p (redo_out, index), |
1089 &global_debug); | |
947 else | 1090 else |
948 local_changed | 1091 local_changed |
949 = dce_process_block (bb, bitmap_bit_p (redo_out, index), | 1092 = dce_process_block (bb, bitmap_bit_p (redo_out, index), |
950 bb_has_eh_pred (bb) ? au_eh : au); | 1093 bb_has_eh_pred (bb) ? au_eh : au, |
1094 &global_debug); | |
951 bitmap_set_bit (processed, index); | 1095 bitmap_set_bit (processed, index); |
952 | 1096 |
953 if (local_changed) | 1097 if (local_changed) |
954 { | 1098 { |
955 edge e; | 1099 edge e; |
973 int old_flag = df_clear_flags (DF_LR_RUN_DCE); | 1117 int old_flag = df_clear_flags (DF_LR_RUN_DCE); |
974 | 1118 |
975 /* So something was deleted that requires a redo. Do it on | 1119 /* So something was deleted that requires a redo. Do it on |
976 the cheap. */ | 1120 the cheap. */ |
977 delete_unmarked_insns (); | 1121 delete_unmarked_insns (); |
978 sbitmap_zero (marked); | 1122 bitmap_clear (marked); |
979 bitmap_clear (processed); | 1123 bitmap_clear (processed); |
980 bitmap_clear (redo_out); | 1124 bitmap_clear (redo_out); |
981 | 1125 |
982 /* We do not need to rescan any instructions. We only need | 1126 /* We do not need to rescan any instructions. We only need |
983 to redo the dataflow equations for the blocks that had a | 1127 to redo the dataflow equations for the blocks that had a |
993 | 1137 |
994 prescan_insns_for_dce (true); | 1138 prescan_insns_for_dce (true); |
995 } | 1139 } |
996 } | 1140 } |
997 | 1141 |
1142 dead_debug_global_finish (&global_debug, NULL); | |
1143 | |
998 delete_unmarked_insns (); | 1144 delete_unmarked_insns (); |
999 | 1145 |
1000 BITMAP_FREE (processed); | 1146 BITMAP_FREE (processed); |
1001 BITMAP_FREE (redo_out); | 1147 BITMAP_FREE (redo_out); |
1002 BITMAP_FREE (all_blocks); | 1148 BITMAP_FREE (all_blocks); |
1073 if (flag_dce) | 1219 if (flag_dce) |
1074 rest_of_handle_fast_dce (); | 1220 rest_of_handle_fast_dce (); |
1075 } | 1221 } |
1076 | 1222 |
1077 | 1223 |
1078 static bool | 1224 namespace { |
1079 gate_fast_dce (void) | 1225 |
1080 { | 1226 const pass_data pass_data_fast_rtl_dce = |
1081 return optimize > 0 && flag_dce | 1227 { |
1082 && dbg_cnt (dce_fast); | 1228 RTL_PASS, /* type */ |
1083 } | 1229 "rtl_dce", /* name */ |
1084 | 1230 OPTGROUP_NONE, /* optinfo_flags */ |
1085 struct rtl_opt_pass pass_fast_rtl_dce = | 1231 TV_DCE, /* tv_id */ |
1086 { | 1232 0, /* properties_required */ |
1087 { | 1233 0, /* properties_provided */ |
1088 RTL_PASS, | 1234 0, /* properties_destroyed */ |
1089 "rtl dce", /* name */ | 1235 0, /* todo_flags_start */ |
1090 gate_fast_dce, /* gate */ | 1236 TODO_df_finish, /* todo_flags_finish */ |
1091 rest_of_handle_fast_dce, /* execute */ | |
1092 NULL, /* sub */ | |
1093 NULL, /* next */ | |
1094 0, /* static_pass_number */ | |
1095 TV_DCE, /* tv_id */ | |
1096 0, /* properties_required */ | |
1097 0, /* properties_provided */ | |
1098 0, /* properties_destroyed */ | |
1099 0, /* todo_flags_start */ | |
1100 TODO_dump_func | | |
1101 TODO_df_finish | TODO_verify_rtl_sharing | | |
1102 TODO_ggc_collect /* todo_flags_finish */ | |
1103 } | |
1104 }; | 1237 }; |
1238 | |
1239 class pass_fast_rtl_dce : public rtl_opt_pass | |
1240 { | |
1241 public: | |
1242 pass_fast_rtl_dce (gcc::context *ctxt) | |
1243 : rtl_opt_pass (pass_data_fast_rtl_dce, ctxt) | |
1244 {} | |
1245 | |
1246 /* opt_pass methods: */ | |
1247 virtual bool gate (function *) | |
1248 { | |
1249 return optimize > 0 && flag_dce && dbg_cnt (dce_fast); | |
1250 } | |
1251 | |
1252 virtual unsigned int execute (function *) | |
1253 { | |
1254 return rest_of_handle_fast_dce (); | |
1255 } | |
1256 | |
1257 }; // class pass_fast_rtl_dce | |
1258 | |
1259 } // anon namespace | |
1260 | |
1261 rtl_opt_pass * | |
1262 make_pass_fast_rtl_dce (gcc::context *ctxt) | |
1263 { | |
1264 return new pass_fast_rtl_dce (ctxt); | |
1265 } |