1*38fd1498Szrj /* Dead store elimination
2*38fd1498Szrj    Copyright (C) 2004-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify
7*38fd1498Szrj it under the terms of the GNU General Public License as published by
8*38fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj any later version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful,
12*38fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #include "config.h"
21*38fd1498Szrj #include "system.h"
22*38fd1498Szrj #include "coretypes.h"
23*38fd1498Szrj #include "backend.h"
24*38fd1498Szrj #include "rtl.h"
25*38fd1498Szrj #include "tree.h"
26*38fd1498Szrj #include "gimple.h"
27*38fd1498Szrj #include "tree-pass.h"
28*38fd1498Szrj #include "ssa.h"
29*38fd1498Szrj #include "gimple-pretty-print.h"
30*38fd1498Szrj #include "fold-const.h"
31*38fd1498Szrj #include "gimple-iterator.h"
32*38fd1498Szrj #include "tree-cfg.h"
33*38fd1498Szrj #include "tree-dfa.h"
34*38fd1498Szrj #include "domwalk.h"
35*38fd1498Szrj #include "tree-cfgcleanup.h"
36*38fd1498Szrj #include "params.h"
37*38fd1498Szrj #include "alias.h"
38*38fd1498Szrj 
39*38fd1498Szrj /* This file implements dead store elimination.
40*38fd1498Szrj 
41*38fd1498Szrj    A dead store is a store into a memory location which will later be
42*38fd1498Szrj    overwritten by another store without any intervening loads.  In this
43*38fd1498Szrj    case the earlier store can be deleted.
44*38fd1498Szrj 
45*38fd1498Szrj    In our SSA + virtual operand world we use immediate uses of virtual
46*38fd1498Szrj    operands to detect dead stores.  If a store's virtual definition
47*38fd1498Szrj    is used precisely once by a later store to the same location which
48*38fd1498Szrj    post dominates the first store, then the first store is dead.
49*38fd1498Szrj 
50*38fd1498Szrj    The single use of the store's virtual definition ensures that
51*38fd1498Szrj    there are no intervening aliased loads and the requirement that
52*38fd1498Szrj    the second load post dominate the first ensures that if the earlier
53*38fd1498Szrj    store executes, then the later stores will execute before the function
54*38fd1498Szrj    exits.
55*38fd1498Szrj 
56*38fd1498Szrj    It may help to think of this as first moving the earlier store to
57*38fd1498Szrj    the point immediately before the later store.  Again, the single
58*38fd1498Szrj    use of the virtual definition and the post-dominance relationship
59*38fd1498Szrj    ensure that such movement would be safe.  Clearly if there are
60*38fd1498Szrj    back to back stores, then the second is redundant.
61*38fd1498Szrj 
62*38fd1498Szrj    Reviewing section 10.7.2 in Morgan's "Building an Optimizing Compiler"
63*38fd1498Szrj    may also help in understanding this code since it discusses the
64*38fd1498Szrj    relationship between dead store and redundant load elimination.  In
65*38fd1498Szrj    fact, they are the same transformation applied to different views of
66*38fd1498Szrj    the CFG.  */
67*38fd1498Szrj 
68*38fd1498Szrj 
69*38fd1498Szrj /* Bitmap of blocks that have had EH statements cleaned.  We should
70*38fd1498Szrj    remove their dead edges eventually.  */
71*38fd1498Szrj static bitmap need_eh_cleanup;
72*38fd1498Szrj 
73*38fd1498Szrj /* Return value from dse_classify_store */
74*38fd1498Szrj enum dse_store_status
75*38fd1498Szrj {
76*38fd1498Szrj   DSE_STORE_LIVE,
77*38fd1498Szrj   DSE_STORE_MAYBE_PARTIAL_DEAD,
78*38fd1498Szrj   DSE_STORE_DEAD
79*38fd1498Szrj };
80*38fd1498Szrj 
81*38fd1498Szrj /* STMT is a statement that may write into memory.  Analyze it and
82*38fd1498Szrj    initialize WRITE to describe how STMT affects memory.
83*38fd1498Szrj 
84*38fd1498Szrj    Return TRUE if the the statement was analyzed, FALSE otherwise.
85*38fd1498Szrj 
86*38fd1498Szrj    It is always safe to return FALSE.  But typically better optimziation
87*38fd1498Szrj    can be achieved by analyzing more statements.  */
88*38fd1498Szrj 
89*38fd1498Szrj static bool
initialize_ao_ref_for_dse(gimple * stmt,ao_ref * write)90*38fd1498Szrj initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write)
91*38fd1498Szrj {
92*38fd1498Szrj   /* It's advantageous to handle certain mem* functions.  */
93*38fd1498Szrj   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
94*38fd1498Szrj     {
95*38fd1498Szrj       switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
96*38fd1498Szrj 	{
97*38fd1498Szrj 	  case BUILT_IN_MEMCPY:
98*38fd1498Szrj 	  case BUILT_IN_MEMMOVE:
99*38fd1498Szrj 	  case BUILT_IN_MEMSET:
100*38fd1498Szrj 	    {
101*38fd1498Szrj 	      tree size = NULL_TREE;
102*38fd1498Szrj 	      if (gimple_call_num_args (stmt) == 3)
103*38fd1498Szrj 		size = gimple_call_arg (stmt, 2);
104*38fd1498Szrj 	      tree ptr = gimple_call_arg (stmt, 0);
105*38fd1498Szrj 	      ao_ref_init_from_ptr_and_size (write, ptr, size);
106*38fd1498Szrj 	      return true;
107*38fd1498Szrj 	    }
108*38fd1498Szrj 	  default:
109*38fd1498Szrj 	    break;
110*38fd1498Szrj 	}
111*38fd1498Szrj     }
112*38fd1498Szrj   else if (is_gimple_assign (stmt))
113*38fd1498Szrj     {
114*38fd1498Szrj       ao_ref_init (write, gimple_assign_lhs (stmt));
115*38fd1498Szrj       return true;
116*38fd1498Szrj     }
117*38fd1498Szrj   return false;
118*38fd1498Szrj }
119*38fd1498Szrj 
120*38fd1498Szrj /* Given REF from the the alias oracle, return TRUE if it is a valid
121*38fd1498Szrj    memory reference for dead store elimination, false otherwise.
122*38fd1498Szrj 
123*38fd1498Szrj    In particular, the reference must have a known base, known maximum
124*38fd1498Szrj    size, start at a byte offset and have a size that is one or more
125*38fd1498Szrj    bytes.  */
126*38fd1498Szrj 
127*38fd1498Szrj static bool
valid_ao_ref_for_dse(ao_ref * ref)128*38fd1498Szrj valid_ao_ref_for_dse (ao_ref *ref)
129*38fd1498Szrj {
130*38fd1498Szrj   return (ao_ref_base (ref)
131*38fd1498Szrj 	  && known_size_p (ref->max_size)
132*38fd1498Szrj 	  && maybe_ne (ref->size, 0)
133*38fd1498Szrj 	  && known_eq (ref->max_size, ref->size)
134*38fd1498Szrj 	  && known_ge (ref->offset, 0)
135*38fd1498Szrj 	  && multiple_p (ref->offset, BITS_PER_UNIT)
136*38fd1498Szrj 	  && multiple_p (ref->size, BITS_PER_UNIT));
137*38fd1498Szrj }
138*38fd1498Szrj 
139*38fd1498Szrj /* Try to normalize COPY (an ao_ref) relative to REF.  Essentially when we are
140*38fd1498Szrj    done COPY will only refer bytes found within REF.  Return true if COPY
141*38fd1498Szrj    is known to intersect at least one byte of REF.  */
142*38fd1498Szrj 
143*38fd1498Szrj static bool
normalize_ref(ao_ref * copy,ao_ref * ref)144*38fd1498Szrj normalize_ref (ao_ref *copy, ao_ref *ref)
145*38fd1498Szrj {
146*38fd1498Szrj   if (!ordered_p (copy->offset, ref->offset))
147*38fd1498Szrj     return false;
148*38fd1498Szrj 
149*38fd1498Szrj   /* If COPY starts before REF, then reset the beginning of
150*38fd1498Szrj      COPY to match REF and decrease the size of COPY by the
151*38fd1498Szrj      number of bytes removed from COPY.  */
152*38fd1498Szrj   if (maybe_lt (copy->offset, ref->offset))
153*38fd1498Szrj     {
154*38fd1498Szrj       poly_int64 diff = ref->offset - copy->offset;
155*38fd1498Szrj       if (maybe_le (copy->size, diff))
156*38fd1498Szrj 	return false;
157*38fd1498Szrj       copy->size -= diff;
158*38fd1498Szrj       copy->offset = ref->offset;
159*38fd1498Szrj     }
160*38fd1498Szrj 
161*38fd1498Szrj   poly_int64 diff = copy->offset - ref->offset;
162*38fd1498Szrj   if (maybe_le (ref->size, diff))
163*38fd1498Szrj     return false;
164*38fd1498Szrj 
165*38fd1498Szrj   /* If COPY extends beyond REF, chop off its size appropriately.  */
166*38fd1498Szrj   poly_int64 limit = ref->size - diff;
167*38fd1498Szrj   if (!ordered_p (limit, copy->size))
168*38fd1498Szrj     return false;
169*38fd1498Szrj 
170*38fd1498Szrj   if (maybe_gt (copy->size, limit))
171*38fd1498Szrj     copy->size = limit;
172*38fd1498Szrj   return true;
173*38fd1498Szrj }
174*38fd1498Szrj 
175*38fd1498Szrj /* Clear any bytes written by STMT from the bitmap LIVE_BYTES.  The base
176*38fd1498Szrj    address written by STMT must match the one found in REF, which must
177*38fd1498Szrj    have its base address previously initialized.
178*38fd1498Szrj 
179*38fd1498Szrj    This routine must be conservative.  If we don't know the offset or
180*38fd1498Szrj    actual size written, assume nothing was written.  */
181*38fd1498Szrj 
182*38fd1498Szrj static void
clear_bytes_written_by(sbitmap live_bytes,gimple * stmt,ao_ref * ref)183*38fd1498Szrj clear_bytes_written_by (sbitmap live_bytes, gimple *stmt, ao_ref *ref)
184*38fd1498Szrj {
185*38fd1498Szrj   ao_ref write;
186*38fd1498Szrj   if (!initialize_ao_ref_for_dse (stmt, &write))
187*38fd1498Szrj     return;
188*38fd1498Szrj 
189*38fd1498Szrj   /* Verify we have the same base memory address, the write
190*38fd1498Szrj      has a known size and overlaps with REF.  */
191*38fd1498Szrj   HOST_WIDE_INT start, size;
192*38fd1498Szrj   if (valid_ao_ref_for_dse (&write)
193*38fd1498Szrj       && operand_equal_p (write.base, ref->base, OEP_ADDRESS_OF)
194*38fd1498Szrj       && known_eq (write.size, write.max_size)
195*38fd1498Szrj       && normalize_ref (&write, ref)
196*38fd1498Szrj       && (write.offset - ref->offset).is_constant (&start)
197*38fd1498Szrj       && write.size.is_constant (&size))
198*38fd1498Szrj     bitmap_clear_range (live_bytes, start / BITS_PER_UNIT,
199*38fd1498Szrj 			size / BITS_PER_UNIT);
200*38fd1498Szrj }
201*38fd1498Szrj 
202*38fd1498Szrj /* REF is a memory write.  Extract relevant information from it and
203*38fd1498Szrj    initialize the LIVE_BYTES bitmap.  If successful, return TRUE.
204*38fd1498Szrj    Otherwise return FALSE.  */
205*38fd1498Szrj 
206*38fd1498Szrj static bool
setup_live_bytes_from_ref(ao_ref * ref,sbitmap live_bytes)207*38fd1498Szrj setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes)
208*38fd1498Szrj {
209*38fd1498Szrj   HOST_WIDE_INT const_size;
210*38fd1498Szrj   if (valid_ao_ref_for_dse (ref)
211*38fd1498Szrj       && ref->size.is_constant (&const_size)
212*38fd1498Szrj       && (const_size / BITS_PER_UNIT
213*38fd1498Szrj 	  <= PARAM_VALUE (PARAM_DSE_MAX_OBJECT_SIZE)))
214*38fd1498Szrj     {
215*38fd1498Szrj       bitmap_clear (live_bytes);
216*38fd1498Szrj       bitmap_set_range (live_bytes, 0, const_size / BITS_PER_UNIT);
217*38fd1498Szrj       return true;
218*38fd1498Szrj     }
219*38fd1498Szrj   return false;
220*38fd1498Szrj }
221*38fd1498Szrj 
222*38fd1498Szrj /* Compute the number of elements that we can trim from the head and
223*38fd1498Szrj    tail of ORIG resulting in a bitmap that is a superset of LIVE.
224*38fd1498Szrj 
225*38fd1498Szrj    Store the number of elements trimmed from the head and tail in
226*38fd1498Szrj    TRIM_HEAD and TRIM_TAIL.
227*38fd1498Szrj 
228*38fd1498Szrj    STMT is the statement being trimmed and is used for debugging dump
229*38fd1498Szrj    output only.  */
230*38fd1498Szrj 
231*38fd1498Szrj static void
compute_trims(ao_ref * ref,sbitmap live,int * trim_head,int * trim_tail,gimple * stmt)232*38fd1498Szrj compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail,
233*38fd1498Szrj 	       gimple *stmt)
234*38fd1498Szrj {
235*38fd1498Szrj   /* We use sbitmaps biased such that ref->offset is bit zero and the bitmap
236*38fd1498Szrj      extends through ref->size.  So we know that in the original bitmap
237*38fd1498Szrj      bits 0..ref->size were true.  We don't actually need the bitmap, just
238*38fd1498Szrj      the REF to compute the trims.  */
239*38fd1498Szrj 
240*38fd1498Szrj   /* Now identify how much, if any of the tail we can chop off.  */
241*38fd1498Szrj   HOST_WIDE_INT const_size;
242*38fd1498Szrj   if (ref->size.is_constant (&const_size))
243*38fd1498Szrj     {
244*38fd1498Szrj       int last_orig = (const_size / BITS_PER_UNIT) - 1;
245*38fd1498Szrj       int last_live = bitmap_last_set_bit (live);
246*38fd1498Szrj       *trim_tail = (last_orig - last_live) & ~0x1;
247*38fd1498Szrj     }
248*38fd1498Szrj   else
249*38fd1498Szrj     *trim_tail = 0;
250*38fd1498Szrj 
251*38fd1498Szrj   /* Identify how much, if any of the head we can chop off.  */
252*38fd1498Szrj   int first_orig = 0;
253*38fd1498Szrj   int first_live = bitmap_first_set_bit (live);
254*38fd1498Szrj   *trim_head = (first_live - first_orig) & ~0x1;
255*38fd1498Szrj 
256*38fd1498Szrj   if ((*trim_head || *trim_tail)
257*38fd1498Szrj       && dump_file && (dump_flags & TDF_DETAILS))
258*38fd1498Szrj     {
259*38fd1498Szrj       fprintf (dump_file, "  Trimming statement (head = %d, tail = %d): ",
260*38fd1498Szrj 	       *trim_head, *trim_tail);
261*38fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
262*38fd1498Szrj       fprintf (dump_file, "\n");
263*38fd1498Szrj     }
264*38fd1498Szrj }
265*38fd1498Szrj 
266*38fd1498Szrj /* STMT initializes an object from COMPLEX_CST where one or more of the
267*38fd1498Szrj    bytes written may be dead stores.  REF is a representation of the
268*38fd1498Szrj    memory written.  LIVE is the bitmap of stores that are actually live.
269*38fd1498Szrj 
270*38fd1498Szrj    Attempt to rewrite STMT so that only the real or imaginary part of
271*38fd1498Szrj    the object is actually stored.  */
272*38fd1498Szrj 
273*38fd1498Szrj static void
maybe_trim_complex_store(ao_ref * ref,sbitmap live,gimple * stmt)274*38fd1498Szrj maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt)
275*38fd1498Szrj {
276*38fd1498Szrj   int trim_head, trim_tail;
277*38fd1498Szrj   compute_trims (ref, live, &trim_head, &trim_tail, stmt);
278*38fd1498Szrj 
279*38fd1498Szrj   /* The amount of data trimmed from the head or tail must be at
280*38fd1498Szrj      least half the size of the object to ensure we're trimming
281*38fd1498Szrj      the entire real or imaginary half.  By writing things this
282*38fd1498Szrj      way we avoid more O(n) bitmap operations.  */
283*38fd1498Szrj   if (known_ge (trim_tail * 2 * BITS_PER_UNIT, ref->size))
284*38fd1498Szrj     {
285*38fd1498Szrj       /* TREE_REALPART is live */
286*38fd1498Szrj       tree x = TREE_REALPART (gimple_assign_rhs1 (stmt));
287*38fd1498Szrj       tree y = gimple_assign_lhs (stmt);
288*38fd1498Szrj       y = build1 (REALPART_EXPR, TREE_TYPE (x), y);
289*38fd1498Szrj       gimple_assign_set_lhs (stmt, y);
290*38fd1498Szrj       gimple_assign_set_rhs1 (stmt, x);
291*38fd1498Szrj     }
292*38fd1498Szrj   else if (known_ge (trim_head * 2 * BITS_PER_UNIT, ref->size))
293*38fd1498Szrj     {
294*38fd1498Szrj       /* TREE_IMAGPART is live */
295*38fd1498Szrj       tree x = TREE_IMAGPART (gimple_assign_rhs1 (stmt));
296*38fd1498Szrj       tree y = gimple_assign_lhs (stmt);
297*38fd1498Szrj       y = build1 (IMAGPART_EXPR, TREE_TYPE (x), y);
298*38fd1498Szrj       gimple_assign_set_lhs (stmt, y);
299*38fd1498Szrj       gimple_assign_set_rhs1 (stmt, x);
300*38fd1498Szrj     }
301*38fd1498Szrj 
302*38fd1498Szrj   /* Other cases indicate parts of both the real and imag subobjects
303*38fd1498Szrj      are live.  We do not try to optimize those cases.  */
304*38fd1498Szrj }
305*38fd1498Szrj 
306*38fd1498Szrj /* STMT initializes an object using a CONSTRUCTOR where one or more of the
307*38fd1498Szrj    bytes written are dead stores.  ORIG is the bitmap of bytes stored by
308*38fd1498Szrj    STMT.  LIVE is the bitmap of stores that are actually live.
309*38fd1498Szrj 
310*38fd1498Szrj    Attempt to rewrite STMT so that only the real or imaginary part of
311*38fd1498Szrj    the object is actually stored.
312*38fd1498Szrj 
313*38fd1498Szrj    The most common case for getting here is a CONSTRUCTOR with no elements
314*38fd1498Szrj    being used to zero initialize an object.  We do not try to handle other
315*38fd1498Szrj    cases as those would force us to fully cover the object with the
316*38fd1498Szrj    CONSTRUCTOR node except for the components that are dead.  */
317*38fd1498Szrj 
318*38fd1498Szrj static void
maybe_trim_constructor_store(ao_ref * ref,sbitmap live,gimple * stmt)319*38fd1498Szrj maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt)
320*38fd1498Szrj {
321*38fd1498Szrj   tree ctor = gimple_assign_rhs1 (stmt);
322*38fd1498Szrj 
323*38fd1498Szrj   /* This is the only case we currently handle.  It actually seems to
324*38fd1498Szrj      catch most cases of actual interest.  */
325*38fd1498Szrj   gcc_assert (CONSTRUCTOR_NELTS (ctor) == 0);
326*38fd1498Szrj 
327*38fd1498Szrj   int head_trim = 0;
328*38fd1498Szrj   int tail_trim = 0;
329*38fd1498Szrj   compute_trims (ref, live, &head_trim, &tail_trim, stmt);
330*38fd1498Szrj 
331*38fd1498Szrj   /* Now we want to replace the constructor initializer
332*38fd1498Szrj      with memset (object + head_trim, 0, size - head_trim - tail_trim).  */
333*38fd1498Szrj   if (head_trim || tail_trim)
334*38fd1498Szrj     {
335*38fd1498Szrj       /* We want &lhs for the MEM_REF expression.  */
336*38fd1498Szrj       tree lhs_addr = build_fold_addr_expr (gimple_assign_lhs (stmt));
337*38fd1498Szrj 
338*38fd1498Szrj       if (! is_gimple_min_invariant (lhs_addr))
339*38fd1498Szrj 	return;
340*38fd1498Szrj 
341*38fd1498Szrj       /* The number of bytes for the new constructor.  */
342*38fd1498Szrj       poly_int64 ref_bytes = exact_div (ref->size, BITS_PER_UNIT);
343*38fd1498Szrj       poly_int64 count = ref_bytes - head_trim - tail_trim;
344*38fd1498Szrj 
345*38fd1498Szrj       /* And the new type for the CONSTRUCTOR.  Essentially it's just
346*38fd1498Szrj 	 a char array large enough to cover the non-trimmed parts of
347*38fd1498Szrj 	 the original CONSTRUCTOR.  Note we want explicit bounds here
348*38fd1498Szrj 	 so that we know how many bytes to clear when expanding the
349*38fd1498Szrj 	 CONSTRUCTOR.  */
350*38fd1498Szrj       tree type = build_array_type_nelts (char_type_node, count);
351*38fd1498Szrj 
352*38fd1498Szrj       /* Build a suitable alias type rather than using alias set zero
353*38fd1498Szrj 	 to avoid pessimizing.  */
354*38fd1498Szrj       tree alias_type = reference_alias_ptr_type (gimple_assign_lhs (stmt));
355*38fd1498Szrj 
356*38fd1498Szrj       /* Build a MEM_REF representing the whole accessed area, starting
357*38fd1498Szrj 	 at the first byte not trimmed.  */
358*38fd1498Szrj       tree exp = fold_build2 (MEM_REF, type, lhs_addr,
359*38fd1498Szrj 			      build_int_cst (alias_type, head_trim));
360*38fd1498Szrj 
361*38fd1498Szrj       /* Now update STMT with a new RHS and LHS.  */
362*38fd1498Szrj       gimple_assign_set_lhs (stmt, exp);
363*38fd1498Szrj       gimple_assign_set_rhs1 (stmt, build_constructor (type, NULL));
364*38fd1498Szrj     }
365*38fd1498Szrj }
366*38fd1498Szrj 
367*38fd1498Szrj /* STMT is a memcpy, memmove or memset.  Decrement the number of bytes
368*38fd1498Szrj    copied/set by DECREMENT.  */
369*38fd1498Szrj static void
decrement_count(gimple * stmt,int decrement)370*38fd1498Szrj decrement_count (gimple *stmt, int decrement)
371*38fd1498Szrj {
372*38fd1498Szrj   tree *countp = gimple_call_arg_ptr (stmt, 2);
373*38fd1498Szrj   gcc_assert (TREE_CODE (*countp) == INTEGER_CST);
374*38fd1498Szrj   *countp = wide_int_to_tree (TREE_TYPE (*countp), (TREE_INT_CST_LOW (*countp)
375*38fd1498Szrj 						    - decrement));
376*38fd1498Szrj 
377*38fd1498Szrj }
378*38fd1498Szrj 
379*38fd1498Szrj static void
increment_start_addr(gimple * stmt,tree * where,int increment)380*38fd1498Szrj increment_start_addr (gimple *stmt, tree *where, int increment)
381*38fd1498Szrj {
382*38fd1498Szrj   if (TREE_CODE (*where) == SSA_NAME)
383*38fd1498Szrj     {
384*38fd1498Szrj       tree tem = make_ssa_name (TREE_TYPE (*where));
385*38fd1498Szrj       gassign *newop
386*38fd1498Szrj         = gimple_build_assign (tem, POINTER_PLUS_EXPR, *where,
387*38fd1498Szrj 			       build_int_cst (sizetype, increment));
388*38fd1498Szrj       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
389*38fd1498Szrj       gsi_insert_before (&gsi, newop, GSI_SAME_STMT);
390*38fd1498Szrj       *where = tem;
391*38fd1498Szrj       update_stmt (gsi_stmt (gsi));
392*38fd1498Szrj       return;
393*38fd1498Szrj     }
394*38fd1498Szrj 
395*38fd1498Szrj   *where = build_fold_addr_expr (fold_build2 (MEM_REF, char_type_node,
396*38fd1498Szrj                                              *where,
397*38fd1498Szrj                                              build_int_cst (ptr_type_node,
398*38fd1498Szrj                                                             increment)));
399*38fd1498Szrj }
400*38fd1498Szrj 
401*38fd1498Szrj /* STMT is builtin call that writes bytes in bitmap ORIG, some bytes are dead
402*38fd1498Szrj    (ORIG & ~NEW) and need not be stored.  Try to rewrite STMT to reduce
403*38fd1498Szrj    the amount of data it actually writes.
404*38fd1498Szrj 
405*38fd1498Szrj    Right now we only support trimming from the head or the tail of the
406*38fd1498Szrj    memory region.  In theory we could split the mem* call, but it's
407*38fd1498Szrj    likely of marginal value.  */
408*38fd1498Szrj 
409*38fd1498Szrj static void
maybe_trim_memstar_call(ao_ref * ref,sbitmap live,gimple * stmt)410*38fd1498Szrj maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
411*38fd1498Szrj {
412*38fd1498Szrj   switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
413*38fd1498Szrj     {
414*38fd1498Szrj     case BUILT_IN_MEMCPY:
415*38fd1498Szrj     case BUILT_IN_MEMMOVE:
416*38fd1498Szrj       {
417*38fd1498Szrj 	int head_trim, tail_trim;
418*38fd1498Szrj 	compute_trims (ref, live, &head_trim, &tail_trim, stmt);
419*38fd1498Szrj 
420*38fd1498Szrj 	/* Tail trimming is easy, we can just reduce the count.  */
421*38fd1498Szrj         if (tail_trim)
422*38fd1498Szrj 	  decrement_count (stmt, tail_trim);
423*38fd1498Szrj 
424*38fd1498Szrj 	/* Head trimming requires adjusting all the arguments.  */
425*38fd1498Szrj         if (head_trim)
426*38fd1498Szrj           {
427*38fd1498Szrj 	    tree *dst = gimple_call_arg_ptr (stmt, 0);
428*38fd1498Szrj 	    increment_start_addr (stmt, dst, head_trim);
429*38fd1498Szrj 	    tree *src = gimple_call_arg_ptr (stmt, 1);
430*38fd1498Szrj 	    increment_start_addr (stmt, src, head_trim);
431*38fd1498Szrj 	    decrement_count (stmt, head_trim);
432*38fd1498Szrj 	  }
433*38fd1498Szrj         break;
434*38fd1498Szrj       }
435*38fd1498Szrj 
436*38fd1498Szrj     case BUILT_IN_MEMSET:
437*38fd1498Szrj       {
438*38fd1498Szrj 	int head_trim, tail_trim;
439*38fd1498Szrj 	compute_trims (ref, live, &head_trim, &tail_trim, stmt);
440*38fd1498Szrj 
441*38fd1498Szrj 	/* Tail trimming is easy, we can just reduce the count.  */
442*38fd1498Szrj         if (tail_trim)
443*38fd1498Szrj 	  decrement_count (stmt, tail_trim);
444*38fd1498Szrj 
445*38fd1498Szrj 	/* Head trimming requires adjusting all the arguments.  */
446*38fd1498Szrj         if (head_trim)
447*38fd1498Szrj           {
448*38fd1498Szrj 	    tree *dst = gimple_call_arg_ptr (stmt, 0);
449*38fd1498Szrj 	    increment_start_addr (stmt, dst, head_trim);
450*38fd1498Szrj 	    decrement_count (stmt, head_trim);
451*38fd1498Szrj 	  }
452*38fd1498Szrj 	break;
453*38fd1498Szrj       }
454*38fd1498Szrj 
455*38fd1498Szrj       default:
456*38fd1498Szrj 	break;
457*38fd1498Szrj     }
458*38fd1498Szrj }
459*38fd1498Szrj 
460*38fd1498Szrj /* STMT is a memory write where one or more bytes written are dead
461*38fd1498Szrj    stores.  ORIG is the bitmap of bytes stored by STMT.  LIVE is the
462*38fd1498Szrj    bitmap of stores that are actually live.
463*38fd1498Szrj 
464*38fd1498Szrj    Attempt to rewrite STMT so that it writes fewer memory locations.  Right
465*38fd1498Szrj    now we only support trimming at the start or end of the memory region.
466*38fd1498Szrj    It's not clear how much there is to be gained by trimming from the middle
467*38fd1498Szrj    of the region.  */
468*38fd1498Szrj 
469*38fd1498Szrj static void
maybe_trim_partially_dead_store(ao_ref * ref,sbitmap live,gimple * stmt)470*38fd1498Szrj maybe_trim_partially_dead_store (ao_ref *ref, sbitmap live, gimple *stmt)
471*38fd1498Szrj {
472*38fd1498Szrj   if (is_gimple_assign (stmt)
473*38fd1498Szrj       && TREE_CODE (gimple_assign_lhs (stmt)) != TARGET_MEM_REF)
474*38fd1498Szrj     {
475*38fd1498Szrj       switch (gimple_assign_rhs_code (stmt))
476*38fd1498Szrj 	{
477*38fd1498Szrj 	case CONSTRUCTOR:
478*38fd1498Szrj 	  maybe_trim_constructor_store (ref, live, stmt);
479*38fd1498Szrj 	  break;
480*38fd1498Szrj 	case COMPLEX_CST:
481*38fd1498Szrj 	  maybe_trim_complex_store (ref, live, stmt);
482*38fd1498Szrj 	  break;
483*38fd1498Szrj 	default:
484*38fd1498Szrj 	  break;
485*38fd1498Szrj 	}
486*38fd1498Szrj     }
487*38fd1498Szrj }
488*38fd1498Szrj 
489*38fd1498Szrj /* Return TRUE if USE_REF reads bytes from LIVE where live is
490*38fd1498Szrj    derived from REF, a write reference.
491*38fd1498Szrj 
492*38fd1498Szrj    While this routine may modify USE_REF, it's passed by value, not
493*38fd1498Szrj    location.  So callers do not see those modifications.  */
494*38fd1498Szrj 
495*38fd1498Szrj static bool
live_bytes_read(ao_ref use_ref,ao_ref * ref,sbitmap live)496*38fd1498Szrj live_bytes_read (ao_ref use_ref, ao_ref *ref, sbitmap live)
497*38fd1498Szrj {
498*38fd1498Szrj   /* We have already verified that USE_REF and REF hit the same object.
499*38fd1498Szrj      Now verify that there's actually an overlap between USE_REF and REF.  */
500*38fd1498Szrj   HOST_WIDE_INT start, size;
501*38fd1498Szrj   if (normalize_ref (&use_ref, ref)
502*38fd1498Szrj       && (use_ref.offset - ref->offset).is_constant (&start)
503*38fd1498Szrj       && use_ref.size.is_constant (&size))
504*38fd1498Szrj     {
505*38fd1498Szrj       /* If USE_REF covers all of REF, then it will hit one or more
506*38fd1498Szrj 	 live bytes.   This avoids useless iteration over the bitmap
507*38fd1498Szrj 	 below.  */
508*38fd1498Szrj       if (start == 0 && known_eq (size, ref->size))
509*38fd1498Szrj 	return true;
510*38fd1498Szrj 
511*38fd1498Szrj       /* Now check if any of the remaining bits in use_ref are set in LIVE.  */
512*38fd1498Szrj       return bitmap_bit_in_range_p (live, start / BITS_PER_UNIT,
513*38fd1498Szrj 				    (start + size - 1) / BITS_PER_UNIT);
514*38fd1498Szrj     }
515*38fd1498Szrj   return true;
516*38fd1498Szrj }
517*38fd1498Szrj 
518*38fd1498Szrj /* A helper of dse_optimize_stmt.
519*38fd1498Szrj    Given a GIMPLE_ASSIGN in STMT that writes to REF, find a candidate
520*38fd1498Szrj    statement *USE_STMT that may prove STMT to be dead.
521*38fd1498Szrj    Return TRUE if the above conditions are met, otherwise FALSE.  */
522*38fd1498Szrj 
523*38fd1498Szrj static dse_store_status
dse_classify_store(ao_ref * ref,gimple * stmt,gimple ** use_stmt,bool byte_tracking_enabled,sbitmap live_bytes)524*38fd1498Szrj dse_classify_store (ao_ref *ref, gimple *stmt, gimple **use_stmt,
525*38fd1498Szrj 		    bool byte_tracking_enabled, sbitmap live_bytes)
526*38fd1498Szrj {
527*38fd1498Szrj   gimple *temp;
528*38fd1498Szrj   unsigned cnt = 0;
529*38fd1498Szrj 
530*38fd1498Szrj   *use_stmt = NULL;
531*38fd1498Szrj 
532*38fd1498Szrj   /* Find the first dominated statement that clobbers (part of) the
533*38fd1498Szrj      memory stmt stores to with no intermediate statement that may use
534*38fd1498Szrj      part of the memory stmt stores.  That is, find a store that may
535*38fd1498Szrj      prove stmt to be a dead store.  */
536*38fd1498Szrj   temp = stmt;
537*38fd1498Szrj   do
538*38fd1498Szrj     {
539*38fd1498Szrj       gimple *use_stmt, *defvar_def;
540*38fd1498Szrj       imm_use_iterator ui;
541*38fd1498Szrj       bool fail = false;
542*38fd1498Szrj       tree defvar;
543*38fd1498Szrj 
544*38fd1498Szrj       /* Limit stmt walking to be linear in the number of possibly
545*38fd1498Szrj          dead stores.  */
546*38fd1498Szrj       if (++cnt > 256)
547*38fd1498Szrj 	return DSE_STORE_LIVE;
548*38fd1498Szrj 
549*38fd1498Szrj       if (gimple_code (temp) == GIMPLE_PHI)
550*38fd1498Szrj 	defvar = PHI_RESULT (temp);
551*38fd1498Szrj       else
552*38fd1498Szrj 	defvar = gimple_vdef (temp);
553*38fd1498Szrj       defvar_def = temp;
554*38fd1498Szrj       temp = NULL;
555*38fd1498Szrj       FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
556*38fd1498Szrj 	{
557*38fd1498Szrj 	  cnt++;
558*38fd1498Szrj 
559*38fd1498Szrj 	  /* If we ever reach our DSE candidate stmt again fail.  We
560*38fd1498Szrj 	     cannot handle dead stores in loops.  */
561*38fd1498Szrj 	  if (use_stmt == stmt)
562*38fd1498Szrj 	    {
563*38fd1498Szrj 	      fail = true;
564*38fd1498Szrj 	      BREAK_FROM_IMM_USE_STMT (ui);
565*38fd1498Szrj 	    }
566*38fd1498Szrj 	  /* In simple cases we can look through PHI nodes, but we
567*38fd1498Szrj 	     have to be careful with loops and with memory references
568*38fd1498Szrj 	     containing operands that are also operands of PHI nodes.
569*38fd1498Szrj 	     See gcc.c-torture/execute/20051110-*.c.  */
570*38fd1498Szrj 	  else if (gimple_code (use_stmt) == GIMPLE_PHI)
571*38fd1498Szrj 	    {
572*38fd1498Szrj 	      if (temp
573*38fd1498Szrj 		  /* Make sure we are not in a loop latch block.  */
574*38fd1498Szrj 		  || gimple_bb (stmt) == gimple_bb (use_stmt)
575*38fd1498Szrj 		  || dominated_by_p (CDI_DOMINATORS,
576*38fd1498Szrj 				     gimple_bb (stmt), gimple_bb (use_stmt))
577*38fd1498Szrj 		  /* We can look through PHIs to regions post-dominating
578*38fd1498Szrj 		     the DSE candidate stmt.  */
579*38fd1498Szrj 		  || !dominated_by_p (CDI_POST_DOMINATORS,
580*38fd1498Szrj 				      gimple_bb (stmt), gimple_bb (use_stmt)))
581*38fd1498Szrj 		{
582*38fd1498Szrj 		  fail = true;
583*38fd1498Szrj 		  BREAK_FROM_IMM_USE_STMT (ui);
584*38fd1498Szrj 		}
585*38fd1498Szrj 	      /* Do not consider the PHI as use if it dominates the
586*38fd1498Szrj 	         stmt defining the virtual operand we are processing,
587*38fd1498Szrj 		 we have processed it already in this case.  */
588*38fd1498Szrj 	      if (gimple_bb (defvar_def) != gimple_bb (use_stmt)
589*38fd1498Szrj 		  && !dominated_by_p (CDI_DOMINATORS,
590*38fd1498Szrj 				      gimple_bb (defvar_def),
591*38fd1498Szrj 				      gimple_bb (use_stmt)))
592*38fd1498Szrj 		temp = use_stmt;
593*38fd1498Szrj 	    }
594*38fd1498Szrj 	  /* If the statement is a use the store is not dead.  */
595*38fd1498Szrj 	  else if (ref_maybe_used_by_stmt_p (use_stmt, ref))
596*38fd1498Szrj 	    {
597*38fd1498Szrj 	      /* Handle common cases where we can easily build an ao_ref
598*38fd1498Szrj 		 structure for USE_STMT and in doing so we find that the
599*38fd1498Szrj 		 references hit non-live bytes and thus can be ignored.  */
600*38fd1498Szrj 	      if (byte_tracking_enabled && (!gimple_vdef (use_stmt) || !temp))
601*38fd1498Szrj 		{
602*38fd1498Szrj 		  if (is_gimple_assign (use_stmt))
603*38fd1498Szrj 		    {
604*38fd1498Szrj 		      /* Other cases were noted as non-aliasing by
605*38fd1498Szrj 			 the call to ref_maybe_used_by_stmt_p.  */
606*38fd1498Szrj 		      ao_ref use_ref;
607*38fd1498Szrj 		      ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
608*38fd1498Szrj 		      if (valid_ao_ref_for_dse (&use_ref)
609*38fd1498Szrj 			  && use_ref.base == ref->base
610*38fd1498Szrj 			  && known_eq (use_ref.size, use_ref.max_size)
611*38fd1498Szrj 			  && !live_bytes_read (use_ref, ref, live_bytes))
612*38fd1498Szrj 			{
613*38fd1498Szrj 			  /* If this statement has a VDEF, then it is the
614*38fd1498Szrj 			     first store we have seen, so walk through it.  */
615*38fd1498Szrj 			  if (gimple_vdef (use_stmt))
616*38fd1498Szrj 			    temp = use_stmt;
617*38fd1498Szrj 			  continue;
618*38fd1498Szrj 			}
619*38fd1498Szrj 		    }
620*38fd1498Szrj 		}
621*38fd1498Szrj 
622*38fd1498Szrj 	      fail = true;
623*38fd1498Szrj 	      BREAK_FROM_IMM_USE_STMT (ui);
624*38fd1498Szrj 	    }
625*38fd1498Szrj 	  /* If this is a store, remember it or bail out if we have
626*38fd1498Szrj 	     multiple ones (the will be in different CFG parts then).  */
627*38fd1498Szrj 	  else if (gimple_vdef (use_stmt))
628*38fd1498Szrj 	    {
629*38fd1498Szrj 	      if (temp)
630*38fd1498Szrj 		{
631*38fd1498Szrj 		  fail = true;
632*38fd1498Szrj 		  BREAK_FROM_IMM_USE_STMT (ui);
633*38fd1498Szrj 		}
634*38fd1498Szrj 	      temp = use_stmt;
635*38fd1498Szrj 	    }
636*38fd1498Szrj 	}
637*38fd1498Szrj 
638*38fd1498Szrj       if (fail)
639*38fd1498Szrj 	{
640*38fd1498Szrj 	  /* STMT might be partially dead and we may be able to reduce
641*38fd1498Szrj 	     how many memory locations it stores into.  */
642*38fd1498Szrj 	  if (byte_tracking_enabled && !gimple_clobber_p (stmt))
643*38fd1498Szrj 	    return DSE_STORE_MAYBE_PARTIAL_DEAD;
644*38fd1498Szrj 	  return DSE_STORE_LIVE;
645*38fd1498Szrj 	}
646*38fd1498Szrj 
647*38fd1498Szrj       /* If we didn't find any definition this means the store is dead
648*38fd1498Szrj          if it isn't a store to global reachable memory.  In this case
649*38fd1498Szrj 	 just pretend the stmt makes itself dead.  Otherwise fail.  */
650*38fd1498Szrj       if (!temp)
651*38fd1498Szrj 	{
652*38fd1498Szrj 	  if (ref_may_alias_global_p (ref))
653*38fd1498Szrj 	    return DSE_STORE_LIVE;
654*38fd1498Szrj 
655*38fd1498Szrj 	  temp = stmt;
656*38fd1498Szrj 	  break;
657*38fd1498Szrj 	}
658*38fd1498Szrj 
659*38fd1498Szrj       if (byte_tracking_enabled && temp)
660*38fd1498Szrj 	clear_bytes_written_by (live_bytes, temp, ref);
661*38fd1498Szrj     }
662*38fd1498Szrj   /* Continue walking until we reach a full kill as a single statement
663*38fd1498Szrj      or there are no more live bytes.  */
664*38fd1498Szrj   while (!stmt_kills_ref_p (temp, ref)
665*38fd1498Szrj 	 && !(byte_tracking_enabled && bitmap_empty_p (live_bytes)));
666*38fd1498Szrj 
667*38fd1498Szrj   *use_stmt = temp;
668*38fd1498Szrj   return DSE_STORE_DEAD;
669*38fd1498Szrj }
670*38fd1498Szrj 
671*38fd1498Szrj 
672*38fd1498Szrj class dse_dom_walker : public dom_walker
673*38fd1498Szrj {
674*38fd1498Szrj public:
dse_dom_walker(cdi_direction direction)675*38fd1498Szrj   dse_dom_walker (cdi_direction direction)
676*38fd1498Szrj     : dom_walker (direction),
677*38fd1498Szrj     m_live_bytes (PARAM_VALUE (PARAM_DSE_MAX_OBJECT_SIZE)),
678*38fd1498Szrj     m_byte_tracking_enabled (false) {}
679*38fd1498Szrj 
680*38fd1498Szrj   virtual edge before_dom_children (basic_block);
681*38fd1498Szrj 
682*38fd1498Szrj private:
683*38fd1498Szrj   auto_sbitmap m_live_bytes;
684*38fd1498Szrj   bool m_byte_tracking_enabled;
685*38fd1498Szrj   void dse_optimize_stmt (gimple_stmt_iterator *);
686*38fd1498Szrj };
687*38fd1498Szrj 
688*38fd1498Szrj /* Delete a dead call at GSI, which is mem* call of some kind.  */
689*38fd1498Szrj static void
delete_dead_call(gimple_stmt_iterator * gsi)690*38fd1498Szrj delete_dead_call (gimple_stmt_iterator *gsi)
691*38fd1498Szrj {
692*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
693*38fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
694*38fd1498Szrj     {
695*38fd1498Szrj       fprintf (dump_file, "  Deleted dead call: ");
696*38fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
697*38fd1498Szrj       fprintf (dump_file, "\n");
698*38fd1498Szrj     }
699*38fd1498Szrj 
700*38fd1498Szrj   tree lhs = gimple_call_lhs (stmt);
701*38fd1498Szrj   if (lhs)
702*38fd1498Szrj     {
703*38fd1498Szrj       tree ptr = gimple_call_arg (stmt, 0);
704*38fd1498Szrj       gimple *new_stmt = gimple_build_assign (lhs, ptr);
705*38fd1498Szrj       unlink_stmt_vdef (stmt);
706*38fd1498Szrj       if (gsi_replace (gsi, new_stmt, true))
707*38fd1498Szrj         bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
708*38fd1498Szrj     }
709*38fd1498Szrj   else
710*38fd1498Szrj     {
711*38fd1498Szrj       /* Then we need to fix the operand of the consuming stmt.  */
712*38fd1498Szrj       unlink_stmt_vdef (stmt);
713*38fd1498Szrj 
714*38fd1498Szrj       /* Remove the dead store.  */
715*38fd1498Szrj       if (gsi_remove (gsi, true))
716*38fd1498Szrj 	bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
717*38fd1498Szrj       release_defs (stmt);
718*38fd1498Szrj     }
719*38fd1498Szrj }
720*38fd1498Szrj 
721*38fd1498Szrj /* Delete a dead store at GSI, which is a gimple assignment. */
722*38fd1498Szrj 
723*38fd1498Szrj static void
delete_dead_assignment(gimple_stmt_iterator * gsi)724*38fd1498Szrj delete_dead_assignment (gimple_stmt_iterator *gsi)
725*38fd1498Szrj {
726*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
727*38fd1498Szrj   if (dump_file && (dump_flags & TDF_DETAILS))
728*38fd1498Szrj     {
729*38fd1498Szrj       fprintf (dump_file, "  Deleted dead store: ");
730*38fd1498Szrj       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
731*38fd1498Szrj       fprintf (dump_file, "\n");
732*38fd1498Szrj     }
733*38fd1498Szrj 
734*38fd1498Szrj   /* Then we need to fix the operand of the consuming stmt.  */
735*38fd1498Szrj   unlink_stmt_vdef (stmt);
736*38fd1498Szrj 
737*38fd1498Szrj   /* Remove the dead store.  */
738*38fd1498Szrj   basic_block bb = gimple_bb (stmt);
739*38fd1498Szrj   if (gsi_remove (gsi, true))
740*38fd1498Szrj     bitmap_set_bit (need_eh_cleanup, bb->index);
741*38fd1498Szrj 
742*38fd1498Szrj   /* And release any SSA_NAMEs set in this statement back to the
743*38fd1498Szrj      SSA_NAME manager.  */
744*38fd1498Szrj   release_defs (stmt);
745*38fd1498Szrj }
746*38fd1498Szrj 
747*38fd1498Szrj /* Attempt to eliminate dead stores in the statement referenced by BSI.
748*38fd1498Szrj 
749*38fd1498Szrj    A dead store is a store into a memory location which will later be
750*38fd1498Szrj    overwritten by another store without any intervening loads.  In this
751*38fd1498Szrj    case the earlier store can be deleted.
752*38fd1498Szrj 
753*38fd1498Szrj    In our SSA + virtual operand world we use immediate uses of virtual
754*38fd1498Szrj    operands to detect dead stores.  If a store's virtual definition
755*38fd1498Szrj    is used precisely once by a later store to the same location which
756*38fd1498Szrj    post dominates the first store, then the first store is dead.  */
757*38fd1498Szrj 
758*38fd1498Szrj void
dse_optimize_stmt(gimple_stmt_iterator * gsi)759*38fd1498Szrj dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
760*38fd1498Szrj {
761*38fd1498Szrj   gimple *stmt = gsi_stmt (*gsi);
762*38fd1498Szrj 
763*38fd1498Szrj   /* If this statement has no virtual defs, then there is nothing
764*38fd1498Szrj      to do.  */
765*38fd1498Szrj   if (!gimple_vdef (stmt))
766*38fd1498Szrj     return;
767*38fd1498Szrj 
768*38fd1498Szrj   /* Don't return early on *this_2(D) ={v} {CLOBBER}.  */
769*38fd1498Szrj   if (gimple_has_volatile_ops (stmt)
770*38fd1498Szrj       && (!gimple_clobber_p (stmt)
771*38fd1498Szrj 	  || TREE_CODE (gimple_assign_lhs (stmt)) != MEM_REF))
772*38fd1498Szrj     return;
773*38fd1498Szrj 
774*38fd1498Szrj   ao_ref ref;
775*38fd1498Szrj   if (!initialize_ao_ref_for_dse (stmt, &ref))
776*38fd1498Szrj     return;
777*38fd1498Szrj 
778*38fd1498Szrj   /* We know we have virtual definitions.  We can handle assignments and
779*38fd1498Szrj      some builtin calls.  */
780*38fd1498Szrj   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
781*38fd1498Szrj     {
782*38fd1498Szrj       switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
783*38fd1498Szrj 	{
784*38fd1498Szrj 	  case BUILT_IN_MEMCPY:
785*38fd1498Szrj 	  case BUILT_IN_MEMMOVE:
786*38fd1498Szrj 	  case BUILT_IN_MEMSET:
787*38fd1498Szrj 	    {
788*38fd1498Szrj 	      /* Occasionally calls with an explicit length of zero
789*38fd1498Szrj 		 show up in the IL.  It's pointless to do analysis
790*38fd1498Szrj 		 on them, they're trivially dead.  */
791*38fd1498Szrj 	      tree size = gimple_call_arg (stmt, 2);
792*38fd1498Szrj 	      if (integer_zerop (size))
793*38fd1498Szrj 		{
794*38fd1498Szrj 		  delete_dead_call (gsi);
795*38fd1498Szrj 		  return;
796*38fd1498Szrj 		}
797*38fd1498Szrj 
798*38fd1498Szrj 	      gimple *use_stmt;
799*38fd1498Szrj 	      enum dse_store_status store_status;
800*38fd1498Szrj 	      m_byte_tracking_enabled
801*38fd1498Szrj 		= setup_live_bytes_from_ref (&ref, m_live_bytes);
802*38fd1498Szrj 	      store_status = dse_classify_store (&ref, stmt, &use_stmt,
803*38fd1498Szrj 						 m_byte_tracking_enabled,
804*38fd1498Szrj 						 m_live_bytes);
805*38fd1498Szrj 	      if (store_status == DSE_STORE_LIVE)
806*38fd1498Szrj 		return;
807*38fd1498Szrj 
808*38fd1498Szrj 	      if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
809*38fd1498Szrj 		{
810*38fd1498Szrj 		  maybe_trim_memstar_call (&ref, m_live_bytes, stmt);
811*38fd1498Szrj 		  return;
812*38fd1498Szrj 		}
813*38fd1498Szrj 
814*38fd1498Szrj 	      if (store_status == DSE_STORE_DEAD)
815*38fd1498Szrj 		delete_dead_call (gsi);
816*38fd1498Szrj 	      return;
817*38fd1498Szrj 	    }
818*38fd1498Szrj 
819*38fd1498Szrj 	  default:
820*38fd1498Szrj 	    return;
821*38fd1498Szrj 	}
822*38fd1498Szrj     }
823*38fd1498Szrj 
824*38fd1498Szrj   if (is_gimple_assign (stmt))
825*38fd1498Szrj     {
826*38fd1498Szrj       gimple *use_stmt;
827*38fd1498Szrj 
828*38fd1498Szrj       /* Self-assignments are zombies.  */
829*38fd1498Szrj       if (operand_equal_p (gimple_assign_rhs1 (stmt),
830*38fd1498Szrj 			   gimple_assign_lhs (stmt), 0))
831*38fd1498Szrj 	use_stmt = stmt;
832*38fd1498Szrj       else
833*38fd1498Szrj 	{
834*38fd1498Szrj 	  m_byte_tracking_enabled
835*38fd1498Szrj 	    = setup_live_bytes_from_ref (&ref, m_live_bytes);
836*38fd1498Szrj 	  enum dse_store_status store_status;
837*38fd1498Szrj 	  store_status = dse_classify_store (&ref, stmt, &use_stmt,
838*38fd1498Szrj 					     m_byte_tracking_enabled,
839*38fd1498Szrj 					     m_live_bytes);
840*38fd1498Szrj 	  if (store_status == DSE_STORE_LIVE)
841*38fd1498Szrj 	    return;
842*38fd1498Szrj 
843*38fd1498Szrj 	  if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
844*38fd1498Szrj 	    {
845*38fd1498Szrj 	      maybe_trim_partially_dead_store (&ref, m_live_bytes, stmt);
846*38fd1498Szrj 	      return;
847*38fd1498Szrj 	    }
848*38fd1498Szrj 	}
849*38fd1498Szrj 
850*38fd1498Szrj       /* Now we know that use_stmt kills the LHS of stmt.  */
851*38fd1498Szrj 
852*38fd1498Szrj       /* But only remove *this_2(D) ={v} {CLOBBER} if killed by
853*38fd1498Szrj 	 another clobber stmt.  */
854*38fd1498Szrj       if (gimple_clobber_p (stmt)
855*38fd1498Szrj 	  && !gimple_clobber_p (use_stmt))
856*38fd1498Szrj 	return;
857*38fd1498Szrj 
858*38fd1498Szrj       delete_dead_assignment (gsi);
859*38fd1498Szrj     }
860*38fd1498Szrj }
861*38fd1498Szrj 
862*38fd1498Szrj edge
before_dom_children(basic_block bb)863*38fd1498Szrj dse_dom_walker::before_dom_children (basic_block bb)
864*38fd1498Szrj {
865*38fd1498Szrj   gimple_stmt_iterator gsi;
866*38fd1498Szrj 
867*38fd1498Szrj   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
868*38fd1498Szrj     {
869*38fd1498Szrj       dse_optimize_stmt (&gsi);
870*38fd1498Szrj       if (gsi_end_p (gsi))
871*38fd1498Szrj 	gsi = gsi_last_bb (bb);
872*38fd1498Szrj       else
873*38fd1498Szrj 	gsi_prev (&gsi);
874*38fd1498Szrj     }
875*38fd1498Szrj   return NULL;
876*38fd1498Szrj }
877*38fd1498Szrj 
878*38fd1498Szrj namespace {
879*38fd1498Szrj 
880*38fd1498Szrj const pass_data pass_data_dse =
881*38fd1498Szrj {
882*38fd1498Szrj   GIMPLE_PASS, /* type */
883*38fd1498Szrj   "dse", /* name */
884*38fd1498Szrj   OPTGROUP_NONE, /* optinfo_flags */
885*38fd1498Szrj   TV_TREE_DSE, /* tv_id */
886*38fd1498Szrj   ( PROP_cfg | PROP_ssa ), /* properties_required */
887*38fd1498Szrj   0, /* properties_provided */
888*38fd1498Szrj   0, /* properties_destroyed */
889*38fd1498Szrj   0, /* todo_flags_start */
890*38fd1498Szrj   0, /* todo_flags_finish */
891*38fd1498Szrj };
892*38fd1498Szrj 
893*38fd1498Szrj class pass_dse : public gimple_opt_pass
894*38fd1498Szrj {
895*38fd1498Szrj public:
pass_dse(gcc::context * ctxt)896*38fd1498Szrj   pass_dse (gcc::context *ctxt)
897*38fd1498Szrj     : gimple_opt_pass (pass_data_dse, ctxt)
898*38fd1498Szrj   {}
899*38fd1498Szrj 
900*38fd1498Szrj   /* opt_pass methods: */
clone()901*38fd1498Szrj   opt_pass * clone () { return new pass_dse (m_ctxt); }
gate(function *)902*38fd1498Szrj   virtual bool gate (function *) { return flag_tree_dse != 0; }
903*38fd1498Szrj   virtual unsigned int execute (function *);
904*38fd1498Szrj 
905*38fd1498Szrj }; // class pass_dse
906*38fd1498Szrj 
907*38fd1498Szrj unsigned int
execute(function * fun)908*38fd1498Szrj pass_dse::execute (function *fun)
909*38fd1498Szrj {
910*38fd1498Szrj   need_eh_cleanup = BITMAP_ALLOC (NULL);
911*38fd1498Szrj 
912*38fd1498Szrj   renumber_gimple_stmt_uids ();
913*38fd1498Szrj 
914*38fd1498Szrj   /* We might consider making this a property of each pass so that it
915*38fd1498Szrj      can be [re]computed on an as-needed basis.  Particularly since
916*38fd1498Szrj      this pass could be seen as an extension of DCE which needs post
917*38fd1498Szrj      dominators.  */
918*38fd1498Szrj   calculate_dominance_info (CDI_POST_DOMINATORS);
919*38fd1498Szrj   calculate_dominance_info (CDI_DOMINATORS);
920*38fd1498Szrj 
921*38fd1498Szrj   /* Dead store elimination is fundamentally a walk of the post-dominator
922*38fd1498Szrj      tree and a backwards walk of statements within each block.  */
923*38fd1498Szrj   dse_dom_walker (CDI_POST_DOMINATORS).walk (fun->cfg->x_exit_block_ptr);
924*38fd1498Szrj 
925*38fd1498Szrj   /* Removal of stores may make some EH edges dead.  Purge such edges from
926*38fd1498Szrj      the CFG as needed.  */
927*38fd1498Szrj   if (!bitmap_empty_p (need_eh_cleanup))
928*38fd1498Szrj     {
929*38fd1498Szrj       gimple_purge_all_dead_eh_edges (need_eh_cleanup);
930*38fd1498Szrj       cleanup_tree_cfg ();
931*38fd1498Szrj     }
932*38fd1498Szrj 
933*38fd1498Szrj   BITMAP_FREE (need_eh_cleanup);
934*38fd1498Szrj 
935*38fd1498Szrj   /* For now, just wipe the post-dominator information.  */
936*38fd1498Szrj   free_dominance_info (CDI_POST_DOMINATORS);
937*38fd1498Szrj   return 0;
938*38fd1498Szrj }
939*38fd1498Szrj 
940*38fd1498Szrj } // anon namespace
941*38fd1498Szrj 
942*38fd1498Szrj gimple_opt_pass *
make_pass_dse(gcc::context * ctxt)943*38fd1498Szrj make_pass_dse (gcc::context *ctxt)
944*38fd1498Szrj {
945*38fd1498Szrj   return new pass_dse (ctxt);
946*38fd1498Szrj }
947