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