xref: /dflybsd-src/contrib/gcc-4.7/gcc/dce.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
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