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