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 }