]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/dce.c
re PR c++/84927 (ICE with NSDMI and reference)
[thirdparty/gcc.git] / gcc / dce.c
CommitLineData
6fb5fa3c 1/* RTL dead code elimination.
85ec4feb 2 Copyright (C) 2005-2018 Free Software Foundation, Inc.
6fb5fa3c
DB
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
9dcd6f09 8Software Foundation; either version 3, or (at your option) any later
6fb5fa3c
DB
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
9dcd6f09
NC
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
6fb5fa3c
DB
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
c7131fb2 23#include "backend.h"
6fb5fa3c 24#include "rtl.h"
957060b5
AM
25#include "tree.h"
26#include "predict.h"
c7131fb2 27#include "df.h"
4d0cdd0c 28#include "memmodel.h"
957060b5 29#include "tm_p.h"
957060b5 30#include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */
60393bbc
AM
31#include "cfgrtl.h"
32#include "cfgbuild.h"
33#include "cfgcleanup.h"
6fb5fa3c 34#include "dce.h"
08df6c0d 35#include "valtrack.h"
6fb5fa3c
DB
36#include "tree-pass.h"
37#include "dbgcnt.h"
38
6fb5fa3c
DB
39
40/* -------------------------------------------------------------------------
41 Core mark/delete routines
42 ------------------------------------------------------------------------- */
43
2e6be65e
EB
44/* True if we are invoked while the df engine is running; in this case,
45 we don't want to reenter it. */
6fb5fa3c
DB
46static bool df_in_progress = false;
47
2da02156
EB
48/* True if we are allowed to alter the CFG in this pass. */
49static bool can_alter_cfg = false;
50
6fb5fa3c
DB
51/* Instructions that have been marked but whose dependencies have not
52 yet been processed. */
0ece9321 53static vec<rtx_insn *> worklist;
6fb5fa3c 54
2e6be65e
EB
55/* Bitmap of instructions marked as needed indexed by INSN_UID. */
56static sbitmap marked;
57
58/* Bitmap obstacks used for block processing by the fast algorithm. */
6fb5fa3c
DB
59static bitmap_obstack dce_blocks_bitmap_obstack;
60static bitmap_obstack dce_tmp_bitmap_obstack;
61
0ece9321 62static bool find_call_stack_args (rtx_call_insn *, bool, bool, bitmap);
6fb5fa3c 63
d4d7f1d1
RS
64/* A subroutine for which BODY is part of the instruction being tested;
65 either the top-level pattern, or an element of a PARALLEL. The
66 instruction is known not to be a bare USE or CLOBBER. */
6fb5fa3c
DB
67
68static bool
d4d7f1d1 69deletable_insn_p_1 (rtx body)
6fb5fa3c 70{
6cad9859 71 switch (GET_CODE (body))
6fb5fa3c 72 {
6fb5fa3c
DB
73 case PREFETCH:
74 case TRAP_IF:
75 /* The UNSPEC case was added here because the ia-64 claims that
76 USEs do not work after reload and generates UNSPECS rather
77 than USEs. Since dce is run after reload we need to avoid
78 deleting these even if they are dead. If it turns out that
79 USEs really do work after reload, the ia-64 should be
80 changed, and the UNSPEC case can be removed. */
81 case UNSPEC:
82 return false;
83
d4d7f1d1 84 default:
1d65f45c 85 return !volatile_refs_p (body);
d4d7f1d1
RS
86 }
87}
88
2e6be65e 89
d4d7f1d1
RS
90/* Return true if INSN is a normal instruction that can be deleted by
91 the DCE pass. */
92
93static bool
0ece9321 94deletable_insn_p (rtx_insn *insn, bool fast, bitmap arg_stores)
d4d7f1d1
RS
95{
96 rtx body, x;
97 int i;
bfac633a 98 df_ref def;
d4d7f1d1 99
5ba5ab9b
KZ
100 if (CALL_P (insn)
101 /* We cannot delete calls inside of the recursive dce because
102 this may cause basic blocks to be deleted and this messes up
103 the rest of the stack of optimization passes. */
104 && (!df_in_progress)
105 /* We cannot delete pure or const sibling calls because it is
106 hard to see the result. */
becfd6e5 107 && (!SIBLING_CALL_P (insn))
5ba5ab9b
KZ
108 /* We can delete dead const or pure calls as long as they do not
109 infinite loop. */
becfd6e5
KZ
110 && (RTL_CONST_OR_PURE_CALL_P (insn)
111 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
0ece9321
DM
112 return find_call_stack_args (as_a <rtx_call_insn *> (insn), false,
113 fast, arg_stores);
becfd6e5 114
642d55de
EB
115 /* Don't delete jumps, notes and the like. */
116 if (!NONJUMP_INSN_P (insn))
117 return false;
118
2da02156
EB
119 /* Don't delete insns that may throw if we cannot do so. */
120 if (!(cfun->can_delete_dead_exceptions && can_alter_cfg)
121 && !insn_nothrow_p (insn))
642d55de
EB
122 return false;
123
211d71a7 124 /* If INSN sets a global_reg, leave it untouched. */
bfac633a
RS
125 FOR_EACH_INSN_DEF (def, insn)
126 if (HARD_REGISTER_NUM_P (DF_REF_REGNO (def))
127 && global_regs[DF_REF_REGNO (def)])
211d71a7 128 return false;
56873e13
ES
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;
211d71a7 133
45399fdc
JJ
134 /* Callee-save restores are needed. */
135 if (RTX_FRAME_RELATED_P (insn)
136 && crtl->shrink_wrapped_separate
137 && find_reg_note (insn, REG_CFA_RESTORE, NULL))
138 return false;
139
d4d7f1d1
RS
140 body = PATTERN (insn);
141 switch (GET_CODE (body))
142 {
143 case USE:
b5b8b0ac 144 case VAR_LOCATION:
d4d7f1d1
RS
145 return false;
146
6fb5fa3c
DB
147 case CLOBBER:
148 if (fast)
149 {
150 /* A CLOBBER of a dead pseudo register serves no purpose.
151 That is not necessarily true for hard registers until
152 after reload. */
6cad9859 153 x = XEXP (body, 0);
6fb5fa3c
DB
154 return REG_P (x) && (!HARD_REGISTER_P (x) || reload_completed);
155 }
d4d7f1d1 156 else
6fb5fa3c
DB
157 /* Because of the way that use-def chains are built, it is not
158 possible to tell if the clobber is dead because it can
159 never be the target of a use-def chain. */
160 return false;
161
6cad9859 162 case PARALLEL:
d4d7f1d1
RS
163 for (i = XVECLEN (body, 0) - 1; i >= 0; i--)
164 if (!deletable_insn_p_1 (XVECEXP (body, 0, i)))
165 return false;
166 return true;
6cad9859 167
6fb5fa3c 168 default:
d4d7f1d1 169 return deletable_insn_p_1 (body);
6fb5fa3c
DB
170 }
171}
172
173
2e6be65e 174/* Return true if INSN has been marked as needed. */
6fb5fa3c
DB
175
176static inline int
0ece9321 177marked_insn_p (rtx_insn *insn)
6fb5fa3c 178{
50e94c7e
SB
179 /* Artificial defs are always needed and they do not have an insn.
180 We should never see them here. */
181 gcc_assert (insn);
d7c028c0 182 return bitmap_bit_p (marked, INSN_UID (insn));
6fb5fa3c
DB
183}
184
185
186/* If INSN has not yet been marked as needed, mark it now, and add it to
187 the worklist. */
188
189static void
0ece9321 190mark_insn (rtx_insn *insn, bool fast)
6fb5fa3c
DB
191{
192 if (!marked_insn_p (insn))
193 {
194 if (!fast)
9771b263 195 worklist.safe_push (insn);
d7c028c0 196 bitmap_set_bit (marked, INSN_UID (insn));
6fb5fa3c
DB
197 if (dump_file)
198 fprintf (dump_file, " Adding insn %d to worklist\n", INSN_UID (insn));
0196c95e
JJ
199 if (CALL_P (insn)
200 && !df_in_progress
201 && !SIBLING_CALL_P (insn)
202 && (RTL_CONST_OR_PURE_CALL_P (insn)
203 && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn)))
0ece9321 204 find_call_stack_args (as_a <rtx_call_insn *> (insn), true, fast, NULL);
6fb5fa3c
DB
205 }
206}
207
208
209/* A note_stores callback used by mark_nonreg_stores. DATA is the
210 instruction containing DEST. */
211
212static void
7bc980e1 213mark_nonreg_stores_1 (rtx dest, const_rtx pattern, void *data)
6fb5fa3c
DB
214{
215 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
0ece9321 216 mark_insn ((rtx_insn *) data, true);
6fb5fa3c
DB
217}
218
219
220/* A note_stores callback used by mark_nonreg_stores. DATA is the
221 instruction containing DEST. */
222
223static void
7bc980e1 224mark_nonreg_stores_2 (rtx dest, const_rtx pattern, void *data)
6fb5fa3c
DB
225{
226 if (GET_CODE (pattern) != CLOBBER && !REG_P (dest))
0ece9321 227 mark_insn ((rtx_insn *) data, false);
6fb5fa3c
DB
228}
229
230
231/* Mark INSN if BODY stores to a non-register destination. */
232
233static void
0ece9321 234mark_nonreg_stores (rtx body, rtx_insn *insn, bool fast)
6fb5fa3c
DB
235{
236 if (fast)
237 note_stores (body, mark_nonreg_stores_1, insn);
238 else
239 note_stores (body, mark_nonreg_stores_2, insn);
240}
241
242
7eb87420 243/* Return true if a store to SIZE bytes, starting OFF bytes from stack pointer,
2e0642cd
JJ
244 is a call argument store, and clear corresponding bits from SP_BYTES
245 bitmap if it is. */
246
247static bool
7eb87420
RS
248check_argument_store (HOST_WIDE_INT size, HOST_WIDE_INT off,
249 HOST_WIDE_INT min_sp_off, HOST_WIDE_INT max_sp_off,
250 bitmap sp_bytes)
2e0642cd
JJ
251{
252 HOST_WIDE_INT byte;
7eb87420 253 for (byte = off; byte < off + size; byte++)
2e0642cd
JJ
254 {
255 if (byte < min_sp_off
256 || byte >= max_sp_off
257 || !bitmap_clear_bit (sp_bytes, byte - min_sp_off))
258 return false;
259 }
260 return true;
261}
262
263
0196c95e
JJ
264/* Try to find all stack stores of CALL_INSN arguments if
265 ACCUMULATE_OUTGOING_ARGS. If all stack stores have been found
266 and it is therefore safe to eliminate the call, return true,
267 otherwise return false. This function should be first called
268 with DO_MARK false, and only when the CALL_INSN is actually
269 going to be marked called again with DO_MARK true. */
270
271static bool
0ece9321 272find_call_stack_args (rtx_call_insn *call_insn, bool do_mark, bool fast,
0196c95e
JJ
273 bitmap arg_stores)
274{
0ece9321
DM
275 rtx p;
276 rtx_insn *insn, *prev_insn;
0196c95e
JJ
277 bool ret;
278 HOST_WIDE_INT min_sp_off, max_sp_off;
279 bitmap sp_bytes;
280
281 gcc_assert (CALL_P (call_insn));
282 if (!ACCUMULATE_OUTGOING_ARGS)
283 return true;
284
285 if (!do_mark)
286 {
287 gcc_assert (arg_stores);
288 bitmap_clear (arg_stores);
289 }
290
291 min_sp_off = INTTYPE_MAXIMUM (HOST_WIDE_INT);
292 max_sp_off = 0;
293
294 /* First determine the minimum and maximum offset from sp for
295 stored arguments. */
296 for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
297 if (GET_CODE (XEXP (p, 0)) == USE
298 && MEM_P (XEXP (XEXP (p, 0), 0)))
299 {
f5541398
RS
300 rtx mem = XEXP (XEXP (p, 0), 0), addr;
301 HOST_WIDE_INT off = 0, size;
d05d7551 302 if (!MEM_SIZE_KNOWN_P (mem) || !MEM_SIZE (mem).is_constant (&size))
0196c95e
JJ
303 return false;
304 addr = XEXP (mem, 0);
305 if (GET_CODE (addr) == PLUS
306 && REG_P (XEXP (addr, 0))
307 && CONST_INT_P (XEXP (addr, 1)))
308 {
309 off = INTVAL (XEXP (addr, 1));
310 addr = XEXP (addr, 0);
311 }
312 if (addr != stack_pointer_rtx)
313 {
314 if (!REG_P (addr))
315 return false;
316 /* If not fast, use chains to see if addr wasn't set to
317 sp + offset. */
318 if (!fast)
319 {
bfac633a 320 df_ref use;
0196c95e
JJ
321 struct df_link *defs;
322 rtx set;
323
bfac633a
RS
324 FOR_EACH_INSN_USE (use, call_insn)
325 if (rtx_equal_p (addr, DF_REF_REG (use)))
0196c95e
JJ
326 break;
327
bfac633a 328 if (use == NULL)
0196c95e
JJ
329 return false;
330
bfac633a 331 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
0196c95e
JJ
332 if (! DF_REF_IS_ARTIFICIAL (defs->ref))
333 break;
334
335 if (defs == NULL)
336 return false;
337
338 set = single_set (DF_REF_INSN (defs->ref));
339 if (!set)
340 return false;
341
342 if (GET_CODE (SET_SRC (set)) != PLUS
343 || XEXP (SET_SRC (set), 0) != stack_pointer_rtx
344 || !CONST_INT_P (XEXP (SET_SRC (set), 1)))
345 return false;
346
347 off += INTVAL (XEXP (SET_SRC (set), 1));
348 }
349 else
350 return false;
351 }
352 min_sp_off = MIN (min_sp_off, off);
f5541398 353 max_sp_off = MAX (max_sp_off, off + size);
0196c95e
JJ
354 }
355
356 if (min_sp_off >= max_sp_off)
357 return true;
358 sp_bytes = BITMAP_ALLOC (NULL);
359
360 /* Set bits in SP_BYTES bitmap for bytes relative to sp + min_sp_off
361 which contain arguments. Checking has been done in the previous
362 loop. */
363 for (p = CALL_INSN_FUNCTION_USAGE (call_insn); p; p = XEXP (p, 1))
364 if (GET_CODE (XEXP (p, 0)) == USE
365 && MEM_P (XEXP (XEXP (p, 0), 0)))
366 {
367 rtx mem = XEXP (XEXP (p, 0), 0), addr;
d05d7551
RS
368 HOST_WIDE_INT off = 0, byte, size;
369 /* Checked in the previous iteration. */
370 size = MEM_SIZE (mem).to_constant ();
0196c95e
JJ
371 addr = XEXP (mem, 0);
372 if (GET_CODE (addr) == PLUS
373 && REG_P (XEXP (addr, 0))
374 && CONST_INT_P (XEXP (addr, 1)))
375 {
376 off = INTVAL (XEXP (addr, 1));
377 addr = XEXP (addr, 0);
378 }
379 if (addr != stack_pointer_rtx)
380 {
bfac633a 381 df_ref use;
0196c95e
JJ
382 struct df_link *defs;
383 rtx set;
384
bfac633a
RS
385 FOR_EACH_INSN_USE (use, call_insn)
386 if (rtx_equal_p (addr, DF_REF_REG (use)))
0196c95e
JJ
387 break;
388
bfac633a 389 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
0196c95e
JJ
390 if (! DF_REF_IS_ARTIFICIAL (defs->ref))
391 break;
392
393 set = single_set (DF_REF_INSN (defs->ref));
394 off += INTVAL (XEXP (SET_SRC (set), 1));
395 }
d05d7551 396 for (byte = off; byte < off + size; byte++)
0196c95e 397 {
821bb7f8
RG
398 if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
399 gcc_unreachable ();
0196c95e
JJ
400 }
401 }
402
403 /* Walk backwards, looking for argument stores. The search stops
750900db 404 when seeing another call, sp adjustment or memory store other than
0196c95e
JJ
405 argument store. */
406 ret = false;
407 for (insn = PREV_INSN (call_insn); insn; insn = prev_insn)
408 {
409 rtx set, mem, addr;
2e0642cd 410 HOST_WIDE_INT off;
0196c95e
JJ
411
412 if (insn == BB_HEAD (BLOCK_FOR_INSN (call_insn)))
0ece9321 413 prev_insn = NULL;
0196c95e
JJ
414 else
415 prev_insn = PREV_INSN (insn);
416
417 if (CALL_P (insn))
418 break;
419
2e0642cd 420 if (!NONDEBUG_INSN_P (insn))
0196c95e
JJ
421 continue;
422
423 set = single_set (insn);
424 if (!set || SET_DEST (set) == stack_pointer_rtx)
425 break;
426
427 if (!MEM_P (SET_DEST (set)))
428 continue;
429
430 mem = SET_DEST (set);
431 addr = XEXP (mem, 0);
432 off = 0;
433 if (GET_CODE (addr) == PLUS
434 && REG_P (XEXP (addr, 0))
435 && CONST_INT_P (XEXP (addr, 1)))
436 {
437 off = INTVAL (XEXP (addr, 1));
438 addr = XEXP (addr, 0);
439 }
440 if (addr != stack_pointer_rtx)
441 {
442 if (!REG_P (addr))
443 break;
444 if (!fast)
445 {
bfac633a 446 df_ref use;
0196c95e
JJ
447 struct df_link *defs;
448 rtx set;
449
bfac633a
RS
450 FOR_EACH_INSN_USE (use, insn)
451 if (rtx_equal_p (addr, DF_REF_REG (use)))
0196c95e
JJ
452 break;
453
bfac633a 454 if (use == NULL)
0196c95e
JJ
455 break;
456
bfac633a 457 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
0196c95e
JJ
458 if (! DF_REF_IS_ARTIFICIAL (defs->ref))
459 break;
460
461 if (defs == NULL)
462 break;
463
464 set = single_set (DF_REF_INSN (defs->ref));
465 if (!set)
466 break;
467
468 if (GET_CODE (SET_SRC (set)) != PLUS
469 || XEXP (SET_SRC (set), 0) != stack_pointer_rtx
470 || !CONST_INT_P (XEXP (SET_SRC (set), 1)))
471 break;
472
473 off += INTVAL (XEXP (SET_SRC (set), 1));
474 }
475 else
476 break;
477 }
478
d05d7551 479 HOST_WIDE_INT size;
7eb87420 480 if (!MEM_SIZE_KNOWN_P (mem)
d05d7551
RS
481 || !MEM_SIZE (mem).is_constant (&size)
482 || !check_argument_store (size, off, min_sp_off,
2e0642cd 483 max_sp_off, sp_bytes))
0196c95e
JJ
484 break;
485
0196c95e
JJ
486 if (!deletable_insn_p (insn, fast, NULL))
487 break;
488
489 if (do_mark)
490 mark_insn (insn, fast);
491 else
492 bitmap_set_bit (arg_stores, INSN_UID (insn));
493
494 if (bitmap_empty_p (sp_bytes))
495 {
496 ret = true;
497 break;
498 }
499 }
500
501 BITMAP_FREE (sp_bytes);
502 if (!ret && arg_stores)
503 bitmap_clear (arg_stores);
504
505 return ret;
506}
507
508
885c9b5d
EB
509/* Remove all REG_EQUAL and REG_EQUIV notes referring to the registers INSN
510 writes to. */
6fb5fa3c
DB
511
512static void
0ece9321 513remove_reg_equal_equiv_notes_for_defs (rtx_insn *insn)
6fb5fa3c 514{
bfac633a 515 df_ref def;
885c9b5d 516
bfac633a
RS
517 FOR_EACH_INSN_DEF (def, insn)
518 remove_reg_equal_equiv_notes_for_regno (DF_REF_REGNO (def));
6fb5fa3c
DB
519}
520
a7a110bb
AO
521/* Scan all BBs for debug insns and reset those that reference values
522 defined in unmarked insns. */
523
524static void
525reset_unmarked_insns_debug_uses (void)
526{
527 basic_block bb;
0ece9321 528 rtx_insn *insn, *next;
a7a110bb 529
4f42035e 530 FOR_EACH_BB_REVERSE_FN (bb, cfun)
a7a110bb
AO
531 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
532 if (DEBUG_INSN_P (insn))
533 {
bfac633a 534 df_ref use;
a7a110bb 535
bfac633a 536 FOR_EACH_INSN_USE (use, insn)
a7a110bb 537 {
a7a110bb
AO
538 struct df_link *defs;
539 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
540 {
0ece9321 541 rtx_insn *ref_insn;
a7a110bb
AO
542 if (DF_REF_IS_ARTIFICIAL (defs->ref))
543 continue;
8ced31fe
JJ
544 ref_insn = DF_REF_INSN (defs->ref);
545 if (!marked_insn_p (ref_insn))
a7a110bb
AO
546 break;
547 }
548 if (!defs)
549 continue;
550 /* ??? FIXME could we propagate the values assigned to
551 each of the DEFs? */
552 INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
553 df_insn_rescan_debug_internal (insn);
8ced31fe 554 break;
a7a110bb
AO
555 }
556 }
557}
6fb5fa3c 558
9ed7b221 559/* Delete every instruction that hasn't been marked. */
6fb5fa3c
DB
560
561static void
562delete_unmarked_insns (void)
563{
564 basic_block bb;
0ece9321 565 rtx_insn *insn, *next;
5ba5ab9b 566 bool must_clean = false;
6fb5fa3c 567
4f42035e 568 FOR_EACH_BB_REVERSE_FN (bb, cfun)
cd3f1729 569 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, next)
a7a110bb 570 if (NONDEBUG_INSN_P (insn))
6fb5fa3c 571 {
9ed7b221 572 /* Always delete no-op moves. */
6fb5fa3c 573 if (noop_move_p (insn))
9ed7b221
EB
574 ;
575
9ed7b221 576 /* Otherwise rely only on the DCE algorithm. */
6fb5fa3c
DB
577 else if (marked_insn_p (insn))
578 continue;
579
cd3f1729
KZ
580 /* Beware that reaching a dbg counter limit here can result
581 in miscompiled file. This occurs when a group of insns
582 must be deleted together, typically because the kept insn
583 depends on the output from the deleted insn. Deleting
584 this insns in reverse order (both at the bb level and
585 when looking at the blocks) minimizes this, but does not
586 eliminate it, since it is possible for the using insn to
587 be top of a block and the producer to be at the bottom of
588 the block. However, in most cases this will only result
589 in an uninitialized use of an insn that is dead anyway.
590
591 However, there is one rare case that will cause a
592 miscompile: deletion of non-looping pure and constant
593 calls on a machine where ACCUMULATE_OUTGOING_ARGS is true.
594 In this case it is possible to remove the call, but leave
595 the argument pushes to the stack. Because of the changes
596 to the stack pointer, this will almost always lead to a
597 miscompile. */
6fb5fa3c
DB
598 if (!dbg_cnt (dce))
599 continue;
600
601 if (dump_file)
602 fprintf (dump_file, "DCE: Deleting insn %d\n", INSN_UID (insn));
603
885c9b5d 604 /* Before we delete the insn we have to remove the REG_EQUAL notes
9ed7b221 605 for the destination regs in order to avoid dangling notes. */
885c9b5d 606 remove_reg_equal_equiv_notes_for_defs (insn);
6fb5fa3c 607
5ba5ab9b
KZ
608 /* If a pure or const call is deleted, this may make the cfg
609 have unreachable blocks. We rememeber this and call
610 delete_unreachable_blocks at the end. */
611 if (CALL_P (insn))
612 must_clean = true;
613
9ed7b221 614 /* Now delete the insn. */
6fb5fa3c 615 delete_insn_and_edges (insn);
6fb5fa3c 616 }
5ba5ab9b
KZ
617
618 /* Deleted a pure or const call. */
619 if (must_clean)
620 delete_unreachable_blocks ();
6fb5fa3c
DB
621}
622
623
6fb5fa3c
DB
624/* Go through the instructions and mark those whose necessity is not
625 dependent on inter-instruction information. Make sure all other
626 instructions are not marked. */
627
628static void
629prescan_insns_for_dce (bool fast)
630{
631 basic_block bb;
0ece9321 632 rtx_insn *insn, *prev;
0196c95e
JJ
633 bitmap arg_stores = NULL;
634
6fb5fa3c
DB
635 if (dump_file)
636 fprintf (dump_file, "Finding needed instructions:\n");
0196c95e
JJ
637
638 if (!df_in_progress && ACCUMULATE_OUTGOING_ARGS)
639 arg_stores = BITMAP_ALLOC (NULL);
640
11cd3bed 641 FOR_EACH_BB_FN (bb, cfun)
0196c95e
JJ
642 {
643 FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev)
a7a110bb 644 if (NONDEBUG_INSN_P (insn))
0196c95e
JJ
645 {
646 /* Don't mark argument stores now. They will be marked
647 if needed when the associated CALL is marked. */
648 if (arg_stores && bitmap_bit_p (arg_stores, INSN_UID (insn)))
649 continue;
650 if (deletable_insn_p (insn, fast, arg_stores))
651 mark_nonreg_stores (PATTERN (insn), insn, fast);
652 else
653 mark_insn (insn, fast);
654 }
655 /* find_call_stack_args only looks at argument stores in the
656 same bb. */
657 if (arg_stores)
658 bitmap_clear (arg_stores);
659 }
660
661 if (arg_stores)
662 BITMAP_FREE (arg_stores);
6fb5fa3c
DB
663
664 if (dump_file)
665 fprintf (dump_file, "Finished finding needed instructions:\n");
666}
667
668
669/* UD-based DSE routines. */
670
6ed3da00 671/* Mark instructions that define artificially-used registers, such as
6fb5fa3c
DB
672 the frame pointer and the stack pointer. */
673
674static void
675mark_artificial_uses (void)
676{
677 basic_block bb;
678 struct df_link *defs;
292321a5 679 df_ref use;
6fb5fa3c 680
04a90bec 681 FOR_ALL_BB_FN (bb, cfun)
292321a5
RS
682 FOR_EACH_ARTIFICIAL_USE (use, bb->index)
683 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
684 if (!DF_REF_IS_ARTIFICIAL (defs->ref))
685 mark_insn (DF_REF_INSN (defs->ref), false);
6fb5fa3c
DB
686}
687
2e6be65e 688
6fb5fa3c
DB
689/* Mark every instruction that defines a register value that INSN uses. */
690
691static void
0ece9321 692mark_reg_dependencies (rtx_insn *insn)
6fb5fa3c
DB
693{
694 struct df_link *defs;
bfac633a 695 df_ref use;
6fb5fa3c 696
b5b8b0ac
AO
697 if (DEBUG_INSN_P (insn))
698 return;
699
bfac633a 700 FOR_EACH_INSN_USE (use, insn)
6fb5fa3c 701 {
6fb5fa3c
DB
702 if (dump_file)
703 {
704 fprintf (dump_file, "Processing use of ");
705 print_simple_rtl (dump_file, DF_REF_REG (use));
706 fprintf (dump_file, " in insn %d:\n", INSN_UID (insn));
707 }
708 for (defs = DF_REF_CHAIN (use); defs; defs = defs->next)
50e94c7e
SB
709 if (! DF_REF_IS_ARTIFICIAL (defs->ref))
710 mark_insn (DF_REF_INSN (defs->ref), false);
6fb5fa3c
DB
711 }
712}
713
714
2e6be65e
EB
715/* Initialize global variables for a new DCE pass. */
716
6fb5fa3c 717static void
2e6be65e
EB
718init_dce (bool fast)
719{
720 if (!df_in_progress)
721 {
722 if (!fast)
7b19209f
SB
723 {
724 df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
725 df_chain_add_problem (DF_UD_CHAIN);
726 }
2e6be65e
EB
727 df_analyze ();
728 }
729
730 if (dump_file)
731 df_dump (dump_file);
732
733 if (fast)
734 {
735 bitmap_obstack_initialize (&dce_blocks_bitmap_obstack);
736 bitmap_obstack_initialize (&dce_tmp_bitmap_obstack);
2da02156 737 can_alter_cfg = false;
2e6be65e 738 }
2da02156
EB
739 else
740 can_alter_cfg = true;
2e6be65e
EB
741
742 marked = sbitmap_alloc (get_max_uid () + 1);
f61e445a 743 bitmap_clear (marked);
2e6be65e
EB
744}
745
746
747/* Free the data allocated by init_dce. */
748
749static void
750fini_dce (bool fast)
6fb5fa3c
DB
751{
752 sbitmap_free (marked);
2e6be65e
EB
753
754 if (fast)
755 {
756 bitmap_obstack_release (&dce_blocks_bitmap_obstack);
757 bitmap_obstack_release (&dce_tmp_bitmap_obstack);
758 }
6fb5fa3c
DB
759}
760
761
762/* UD-chain based DCE. */
763
764static unsigned int
765rest_of_handle_ud_dce (void)
766{
0ece9321 767 rtx_insn *insn;
6fb5fa3c 768
6fb5fa3c
DB
769 init_dce (false);
770
771 prescan_insns_for_dce (false);
772 mark_artificial_uses ();
9771b263 773 while (worklist.length () > 0)
6fb5fa3c 774 {
9771b263 775 insn = worklist.pop ();
6fb5fa3c
DB
776 mark_reg_dependencies (insn);
777 }
9771b263 778 worklist.release ();
2e6be65e 779
36f52e8f 780 if (MAY_HAVE_DEBUG_BIND_INSNS)
a7a110bb
AO
781 reset_unmarked_insns_debug_uses ();
782
6fb5fa3c
DB
783 /* Before any insns are deleted, we must remove the chains since
784 they are not bidirectional. */
785 df_remove_problem (df_chain);
786 delete_unmarked_insns ();
787
2e6be65e 788 fini_dce (false);
6fb5fa3c
DB
789 return 0;
790}
791
792
17795822
TS
793namespace {
794
795const pass_data pass_data_ud_rtl_dce =
6fb5fa3c 796{
27a4cd48
DM
797 RTL_PASS, /* type */
798 "ud_dce", /* name */
799 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
800 TV_DCE, /* tv_id */
801 0, /* properties_required */
802 0, /* properties_provided */
803 0, /* properties_destroyed */
804 0, /* todo_flags_start */
3bea341f 805 TODO_df_finish, /* todo_flags_finish */
6fb5fa3c
DB
806};
807
17795822 808class pass_ud_rtl_dce : public rtl_opt_pass
27a4cd48
DM
809{
810public:
c3284718
RS
811 pass_ud_rtl_dce (gcc::context *ctxt)
812 : rtl_opt_pass (pass_data_ud_rtl_dce, ctxt)
27a4cd48
DM
813 {}
814
815 /* opt_pass methods: */
1a3d085c
TS
816 virtual bool gate (function *)
817 {
818 return optimize > 1 && flag_dce && dbg_cnt (dce_ud);
819 }
820
be55bfe6
TS
821 virtual unsigned int execute (function *)
822 {
823 return rest_of_handle_ud_dce ();
824 }
27a4cd48
DM
825
826}; // class pass_ud_rtl_dce
827
17795822
TS
828} // anon namespace
829
27a4cd48
DM
830rtl_opt_pass *
831make_pass_ud_rtl_dce (gcc::context *ctxt)
832{
833 return new pass_ud_rtl_dce (ctxt);
834}
835
2e6be65e 836
6fb5fa3c
DB
837/* -------------------------------------------------------------------------
838 Fast DCE functions
839 ------------------------------------------------------------------------- */
840
cc806ac1
RS
841/* Process basic block BB. Return true if the live_in set has
842 changed. REDO_OUT is true if the info at the bottom of the block
843 needs to be recalculated before starting. AU is the proper set of
e9f950ba
AO
844 artificial uses. Track global substitution of uses of dead pseudos
845 in debug insns using GLOBAL_DEBUG. */
6fb5fa3c
DB
846
847static bool
e9f950ba
AO
848word_dce_process_block (basic_block bb, bool redo_out,
849 struct dead_debug_global *global_debug)
6fb5fa3c
DB
850{
851 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
0ece9321 852 rtx_insn *insn;
6fb5fa3c 853 bool block_changed;
e9f950ba 854 struct dead_debug_local debug;
6fb5fa3c
DB
855
856 if (redo_out)
857 {
858 /* Need to redo the live_out set of this block if when one of
859 the succs of this block has had a change in it live in
860 set. */
861 edge e;
862 edge_iterator ei;
8d074192
BS
863 df_confluence_function_n con_fun_n = df_word_lr->problem->con_fun_n;
864 bitmap_clear (DF_WORD_LR_OUT (bb));
6fb5fa3c
DB
865 FOR_EACH_EDGE (e, ei, bb->succs)
866 (*con_fun_n) (e);
867 }
868
869 if (dump_file)
870 {
871 fprintf (dump_file, "processing block %d live out = ", bb->index);
8d074192 872 df_print_word_regset (dump_file, DF_WORD_LR_OUT (bb));
6fb5fa3c
DB
873 }
874
8d074192 875 bitmap_copy (local_live, DF_WORD_LR_OUT (bb));
e9f950ba 876 dead_debug_local_init (&debug, NULL, global_debug);
cc806ac1
RS
877
878 FOR_BB_INSNS_REVERSE (bb, insn)
1adbb361
AO
879 if (DEBUG_INSN_P (insn))
880 {
bfac633a
RS
881 df_ref use;
882 FOR_EACH_INSN_USE (use, insn)
883 if (DF_REF_REGNO (use) >= FIRST_PSEUDO_REGISTER
cf098191
RS
884 && known_eq (GET_MODE_SIZE (GET_MODE (DF_REF_REAL_REG (use))),
885 2 * UNITS_PER_WORD)
bfac633a
RS
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));
1adbb361
AO
889 }
890 else if (INSN_P (insn))
cc806ac1 891 {
8d074192 892 bool any_changed;
1adbb361 893
cc806ac1
RS
894 /* No matter if the instruction is needed or not, we remove
895 any regno in the defs from the live set. */
8d074192
BS
896 any_changed = df_word_lr_simulate_defs (insn, local_live);
897 if (any_changed)
898 mark_insn (insn, true);
cc806ac1
RS
899
900 /* On the other hand, we do not allow the dead uses to set
901 anything in local_live. */
902 if (marked_insn_p (insn))
8d074192 903 df_word_lr_simulate_uses (insn, local_live);
6f9e260c 904
39bc0f01 905 /* Insert debug temps for dead REGs used in subsequent debug
6f9e260c
AO
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))
1adbb361 910 {
bfac633a 911 df_ref def;
1adbb361 912
bfac633a
RS
913 FOR_EACH_INSN_DEF (def, insn)
914 dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn,
85d87497
JJ
915 marked_insn_p (insn)
916 && !control_flow_insn_p (insn)
917 ? DEBUG_TEMP_AFTER_WITH_REG_FORCE
918 : DEBUG_TEMP_BEFORE_WITH_VALUE);
1adbb361
AO
919 }
920
cc806ac1
RS
921 if (dump_file)
922 {
b8698a0f 923 fprintf (dump_file, "finished processing insn %d live out = ",
cc806ac1 924 INSN_UID (insn));
8d074192 925 df_print_word_regset (dump_file, local_live);
cc806ac1
RS
926 }
927 }
b8698a0f 928
8d074192 929 block_changed = !bitmap_equal_p (local_live, DF_WORD_LR_IN (bb));
cc806ac1 930 if (block_changed)
8d074192
BS
931 bitmap_copy (DF_WORD_LR_IN (bb), local_live);
932
e9f950ba 933 dead_debug_local_finish (&debug, NULL);
cc806ac1
RS
934 BITMAP_FREE (local_live);
935 return block_changed;
936}
937
938
939/* Process basic block BB. Return true if the live_in set has
940 changed. REDO_OUT is true if the info at the bottom of the block
941 needs to be recalculated before starting. AU is the proper set of
e9f950ba
AO
942 artificial uses. Track global substitution of uses of dead pseudos
943 in debug insns using GLOBAL_DEBUG. */
cc806ac1
RS
944
945static bool
e9f950ba
AO
946dce_process_block (basic_block bb, bool redo_out, bitmap au,
947 struct dead_debug_global *global_debug)
cc806ac1
RS
948{
949 bitmap local_live = BITMAP_ALLOC (&dce_tmp_bitmap_obstack);
0ece9321 950 rtx_insn *insn;
cc806ac1 951 bool block_changed;
bfac633a 952 df_ref def;
e9f950ba 953 struct dead_debug_local debug;
6fb5fa3c 954
cc806ac1 955 if (redo_out)
6fb5fa3c 956 {
cc806ac1
RS
957 /* Need to redo the live_out set of this block if when one of
958 the succs of this block has had a change in it live in
959 set. */
960 edge e;
961 edge_iterator ei;
962 df_confluence_function_n con_fun_n = df_lr->problem->con_fun_n;
963 bitmap_clear (DF_LR_OUT (bb));
964 FOR_EACH_EDGE (e, ei, bb->succs)
965 (*con_fun_n) (e);
6fb5fa3c
DB
966 }
967
cc806ac1 968 if (dump_file)
6fb5fa3c 969 {
fafe34f9 970 fprintf (dump_file, "processing block %d lr out = ", bb->index);
cc806ac1 971 df_print_regset (dump_file, DF_LR_OUT (bb));
6fb5fa3c
DB
972 }
973
cc806ac1
RS
974 bitmap_copy (local_live, DF_LR_OUT (bb));
975
02b47899 976 df_simulate_initialize_backwards (bb, local_live);
e9f950ba 977 dead_debug_local_init (&debug, NULL, global_debug);
541d3103 978
6fb5fa3c 979 FOR_BB_INSNS_REVERSE (bb, insn)
1adbb361
AO
980 if (DEBUG_INSN_P (insn))
981 {
bfac633a
RS
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));
1adbb361
AO
987 }
988 else if (INSN_P (insn))
6fb5fa3c 989 {
f251709a 990 bool needed = marked_insn_p (insn);
9ed7b221
EB
991
992 /* The insn is needed if there is someone who uses the output. */
f251709a 993 if (!needed)
bfac633a
RS
994 FOR_EACH_INSN_DEF (def, insn)
995 if (bitmap_bit_p (local_live, DF_REF_REGNO (def))
996 || bitmap_bit_p (au, DF_REF_REGNO (def)))
39bc0f01
AO
997 {
998 needed = true;
999 mark_insn (insn, true);
1000 break;
1001 }
b8698a0f 1002
6fb5fa3c
DB
1003 /* No matter if the instruction is needed or not, we remove
1004 any regno in the defs from the live set. */
1005 df_simulate_defs (insn, local_live);
1006
1007 /* On the other hand, we do not allow the dead uses to set
1008 anything in local_live. */
f251709a 1009 if (needed)
6fb5fa3c 1010 df_simulate_uses (insn, local_live);
6f9e260c 1011
39bc0f01 1012 /* Insert debug temps for dead REGs used in subsequent debug
6f9e260c
AO
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))
bfac633a
RS
1017 FOR_EACH_INSN_DEF (def, insn)
1018 dead_debug_insert_temp (&debug, DF_REF_REGNO (def), insn,
85d87497
JJ
1019 needed && !control_flow_insn_p (insn)
1020 ? DEBUG_TEMP_AFTER_WITH_REG_FORCE
1021 : DEBUG_TEMP_BEFORE_WITH_VALUE);
6fb5fa3c 1022 }
b8698a0f 1023
e9f950ba 1024 dead_debug_local_finish (&debug, NULL);
02b47899 1025 df_simulate_finalize_backwards (bb, local_live);
6fb5fa3c
DB
1026
1027 block_changed = !bitmap_equal_p (local_live, DF_LR_IN (bb));
1028 if (block_changed)
1029 bitmap_copy (DF_LR_IN (bb), local_live);
1030
1031 BITMAP_FREE (local_live);
1032 return block_changed;
1033}
1034
2e6be65e 1035
8d074192
BS
1036/* Perform fast DCE once initialization is done. If WORD_LEVEL is
1037 true, use the word level dce, otherwise do it at the pseudo
cc806ac1 1038 level. */
2e6be65e 1039
6fb5fa3c 1040static void
8d074192 1041fast_dce (bool word_level)
6fb5fa3c
DB
1042{
1043 int *postorder = df_get_postorder (DF_BACKWARD);
1044 int n_blocks = df_get_n_blocks (DF_BACKWARD);
6fb5fa3c
DB
1045 /* The set of blocks that have been seen on this iteration. */
1046 bitmap processed = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
1047 /* The set of blocks that need to have the out vectors reset because
1048 the in of one of their successors has changed. */
1049 bitmap redo_out = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
1050 bitmap all_blocks = BITMAP_ALLOC (&dce_blocks_bitmap_obstack);
1051 bool global_changed = true;
cc806ac1
RS
1052
1053 /* These regs are considered always live so if they end up dying
1054 because of some def, we need to bring the back again. Calling
1055 df_simulate_fixup_sets has the disadvantage of calling
1056 bb_has_eh_pred once per insn, so we cache the information
1057 here. */
a7e3698d
JH
1058 bitmap au = &df->regular_block_artificial_uses;
1059 bitmap au_eh = &df->eh_block_artificial_uses;
9ed7b221 1060 int i;
e9f950ba 1061 struct dead_debug_global global_debug;
6fb5fa3c
DB
1062
1063 prescan_insns_for_dce (true);
1064
1065 for (i = 0; i < n_blocks; i++)
1066 bitmap_set_bit (all_blocks, postorder[i]);
1067
e9f950ba
AO
1068 dead_debug_global_init (&global_debug, NULL);
1069
6fb5fa3c
DB
1070 while (global_changed)
1071 {
1072 global_changed = false;
9ed7b221 1073
6fb5fa3c
DB
1074 for (i = 0; i < n_blocks; i++)
1075 {
1076 int index = postorder[i];
06e28de2 1077 basic_block bb = BASIC_BLOCK_FOR_FN (cfun, index);
6fb5fa3c
DB
1078 bool local_changed;
1079
1080 if (index < NUM_FIXED_BLOCKS)
1081 {
1082 bitmap_set_bit (processed, index);
1083 continue;
1084 }
1085
8d074192 1086 if (word_level)
b8698a0f 1087 local_changed
e9f950ba
AO
1088 = word_dce_process_block (bb, bitmap_bit_p (redo_out, index),
1089 &global_debug);
cc806ac1 1090 else
b8698a0f 1091 local_changed
cc806ac1 1092 = dce_process_block (bb, bitmap_bit_p (redo_out, index),
e9f950ba
AO
1093 bb_has_eh_pred (bb) ? au_eh : au,
1094 &global_debug);
6fb5fa3c 1095 bitmap_set_bit (processed, index);
b8698a0f 1096
6fb5fa3c
DB
1097 if (local_changed)
1098 {
1099 edge e;
1100 edge_iterator ei;
1101 FOR_EACH_EDGE (e, ei, bb->preds)
1102 if (bitmap_bit_p (processed, e->src->index))
1103 /* Be tricky about when we need to iterate the
1104 analysis. We only have redo the analysis if the
1105 bitmaps change at the top of a block that is the
1106 entry to a loop. */
1107 global_changed = true;
1108 else
1109 bitmap_set_bit (redo_out, e->src->index);
1110 }
1111 }
b8698a0f 1112
6fb5fa3c
DB
1113 if (global_changed)
1114 {
1115 /* Turn off the RUN_DCE flag to prevent recursive calls to
1116 dce. */
1117 int old_flag = df_clear_flags (DF_LR_RUN_DCE);
1118
1119 /* So something was deleted that requires a redo. Do it on
1120 the cheap. */
1121 delete_unmarked_insns ();
f61e445a 1122 bitmap_clear (marked);
6fb5fa3c
DB
1123 bitmap_clear (processed);
1124 bitmap_clear (redo_out);
b8698a0f 1125
6fb5fa3c
DB
1126 /* We do not need to rescan any instructions. We only need
1127 to redo the dataflow equations for the blocks that had a
1128 change at the top of the block. Then we need to redo the
b8698a0f 1129 iteration. */
8d074192
BS
1130 if (word_level)
1131 df_analyze_problem (df_word_lr, all_blocks, postorder, n_blocks);
cc806ac1
RS
1132 else
1133 df_analyze_problem (df_lr, all_blocks, postorder, n_blocks);
6fb5fa3c
DB
1134
1135 if (old_flag & DF_LR_RUN_DCE)
1136 df_set_flags (DF_LR_RUN_DCE);
9ed7b221 1137
6fb5fa3c
DB
1138 prescan_insns_for_dce (true);
1139 }
6fb5fa3c
DB
1140 }
1141
e9f950ba
AO
1142 dead_debug_global_finish (&global_debug, NULL);
1143
6fb5fa3c
DB
1144 delete_unmarked_insns ();
1145
1146 BITMAP_FREE (processed);
1147 BITMAP_FREE (redo_out);
1148 BITMAP_FREE (all_blocks);
1149}
1150
1151
cc806ac1 1152/* Fast register level DCE. */
6fb5fa3c
DB
1153
1154static unsigned int
1155rest_of_handle_fast_dce (void)
1156{
1157 init_dce (true);
cc806ac1
RS
1158 fast_dce (false);
1159 fini_dce (true);
1160 return 0;
1161}
1162
1163
1164/* Fast byte level DCE. */
1165
8d074192
BS
1166void
1167run_word_dce (void)
cc806ac1 1168{
25aef556
BS
1169 int old_flags;
1170
1171 if (!flag_dce)
1172 return;
1173
8d074192 1174 timevar_push (TV_DCE);
25aef556 1175 old_flags = df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN);
8d074192 1176 df_word_lr_add_problem ();
cc806ac1
RS
1177 init_dce (true);
1178 fast_dce (true);
2e6be65e 1179 fini_dce (true);
25aef556 1180 df_set_flags (old_flags);
8d074192 1181 timevar_pop (TV_DCE);
6fb5fa3c
DB
1182}
1183
1184
1185/* This is an internal call that is used by the df live register
1186 problem to run fast dce as a side effect of creating the live
1187 information. The stack is organized so that the lr problem is run,
1188 this pass is run, which updates the live info and the df scanning
1189 info, and then returns to allow the rest of the problems to be run.
1190
1191 This can be called by elsewhere but it will not update the bit
2e6be65e 1192 vectors for any other problems than LR. */
6fb5fa3c
DB
1193
1194void
1195run_fast_df_dce (void)
1196{
1197 if (flag_dce)
1198 {
1199 /* If dce is able to delete something, it has to happen
1200 immediately. Otherwise there will be problems handling the
1201 eq_notes. */
81f40b79
ILT
1202 int old_flags =
1203 df_clear_flags (DF_DEFER_INSN_RESCAN + DF_NO_INSN_RESCAN);
1204
6fb5fa3c
DB
1205 df_in_progress = true;
1206 rest_of_handle_fast_dce ();
2e6be65e
EB
1207 df_in_progress = false;
1208
6fb5fa3c
DB
1209 df_set_flags (old_flags);
1210 }
1211}
1212
2e6be65e 1213
9ed7b221
EB
1214/* Run a fast DCE pass. */
1215
1216void
1217run_fast_dce (void)
6fb5fa3c 1218{
9ed7b221
EB
1219 if (flag_dce)
1220 rest_of_handle_fast_dce ();
6fb5fa3c
DB
1221}
1222
1223
17795822
TS
1224namespace {
1225
1226const pass_data pass_data_fast_rtl_dce =
6fb5fa3c 1227{
27a4cd48
DM
1228 RTL_PASS, /* type */
1229 "rtl_dce", /* name */
1230 OPTGROUP_NONE, /* optinfo_flags */
27a4cd48
DM
1231 TV_DCE, /* tv_id */
1232 0, /* properties_required */
1233 0, /* properties_provided */
1234 0, /* properties_destroyed */
1235 0, /* todo_flags_start */
3bea341f 1236 TODO_df_finish, /* todo_flags_finish */
6fb5fa3c 1237};
27a4cd48 1238
17795822 1239class pass_fast_rtl_dce : public rtl_opt_pass
27a4cd48
DM
1240{
1241public:
c3284718
RS
1242 pass_fast_rtl_dce (gcc::context *ctxt)
1243 : rtl_opt_pass (pass_data_fast_rtl_dce, ctxt)
27a4cd48
DM
1244 {}
1245
1246 /* opt_pass methods: */
1a3d085c
TS
1247 virtual bool gate (function *)
1248 {
1249 return optimize > 0 && flag_dce && dbg_cnt (dce_fast);
1250 }
1251
be55bfe6
TS
1252 virtual unsigned int execute (function *)
1253 {
1254 return rest_of_handle_fast_dce ();
1255 }
27a4cd48
DM
1256
1257}; // class pass_fast_rtl_dce
1258
17795822
TS
1259} // anon namespace
1260
27a4cd48
DM
1261rtl_opt_pass *
1262make_pass_fast_rtl_dce (gcc::context *ctxt)
1263{
1264 return new pass_fast_rtl_dce (ctxt);
1265}