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