xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/tree-ssa-dse.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1*8feb0f0bSmrg /* Dead and redundant store elimination
2*8feb0f0bSmrg    Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg 
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg 
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify
71debfc3dSmrg it under the terms of the GNU General Public License as published by
81debfc3dSmrg the Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg any later version.
101debfc3dSmrg 
111debfc3dSmrg GCC is distributed in the hope that it will be useful,
121debfc3dSmrg but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141debfc3dSmrg GNU General Public License for more details.
151debfc3dSmrg 
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3.  If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>.  */
191debfc3dSmrg 
201debfc3dSmrg #include "config.h"
211debfc3dSmrg #include "system.h"
221debfc3dSmrg #include "coretypes.h"
231debfc3dSmrg #include "backend.h"
241debfc3dSmrg #include "rtl.h"
251debfc3dSmrg #include "tree.h"
261debfc3dSmrg #include "gimple.h"
271debfc3dSmrg #include "tree-pass.h"
281debfc3dSmrg #include "ssa.h"
291debfc3dSmrg #include "gimple-pretty-print.h"
301debfc3dSmrg #include "fold-const.h"
311debfc3dSmrg #include "gimple-iterator.h"
321debfc3dSmrg #include "tree-cfg.h"
331debfc3dSmrg #include "tree-dfa.h"
341debfc3dSmrg #include "domwalk.h"
351debfc3dSmrg #include "tree-cfgcleanup.h"
361debfc3dSmrg #include "alias.h"
37c0a68be4Smrg #include "tree-ssa-loop.h"
38*8feb0f0bSmrg #include "tree-ssa-dse.h"
39*8feb0f0bSmrg #include "builtins.h"
40*8feb0f0bSmrg #include "gimple-fold.h"
41*8feb0f0bSmrg #include "gimplify.h"
421debfc3dSmrg 
431debfc3dSmrg /* This file implements dead store elimination.
441debfc3dSmrg 
451debfc3dSmrg    A dead store is a store into a memory location which will later be
461debfc3dSmrg    overwritten by another store without any intervening loads.  In this
47*8feb0f0bSmrg    case the earlier store can be deleted or trimmed if the store
48*8feb0f0bSmrg    was partially dead.
49*8feb0f0bSmrg 
50*8feb0f0bSmrg    A redundant store is a store into a memory location which stores
51*8feb0f0bSmrg    the exact same value as a prior store to the same memory location.
52*8feb0f0bSmrg    While this can often be handled by dead store elimination, removing
53*8feb0f0bSmrg    the redundant store is often better than removing or trimming the
54*8feb0f0bSmrg    dead store.
551debfc3dSmrg 
561debfc3dSmrg    In our SSA + virtual operand world we use immediate uses of virtual
57*8feb0f0bSmrg    operands to detect these cases.  If a store's virtual definition
581debfc3dSmrg    is used precisely once by a later store to the same location which
59*8feb0f0bSmrg    post dominates the first store, then the first store is dead.  If
60*8feb0f0bSmrg    the data stored is the same, then the second store is redundant.
611debfc3dSmrg 
621debfc3dSmrg    The single use of the store's virtual definition ensures that
631debfc3dSmrg    there are no intervening aliased loads and the requirement that
641debfc3dSmrg    the second load post dominate the first ensures that if the earlier
651debfc3dSmrg    store executes, then the later stores will execute before the function
661debfc3dSmrg    exits.
671debfc3dSmrg 
681debfc3dSmrg    It may help to think of this as first moving the earlier store to
691debfc3dSmrg    the point immediately before the later store.  Again, the single
701debfc3dSmrg    use of the virtual definition and the post-dominance relationship
711debfc3dSmrg    ensure that such movement would be safe.  Clearly if there are
72*8feb0f0bSmrg    back to back stores, then the second is makes the first dead.  If
73*8feb0f0bSmrg    the second store stores the same value, then the second store is
74*8feb0f0bSmrg    redundant.
751debfc3dSmrg 
761debfc3dSmrg    Reviewing section 10.7.2 in Morgan's "Building an Optimizing Compiler"
771debfc3dSmrg    may also help in understanding this code since it discusses the
781debfc3dSmrg    relationship between dead store and redundant load elimination.  In
791debfc3dSmrg    fact, they are the same transformation applied to different views of
801debfc3dSmrg    the CFG.  */
811debfc3dSmrg 
82*8feb0f0bSmrg static void delete_dead_or_redundant_call (gimple_stmt_iterator *, const char *);
831debfc3dSmrg 
841debfc3dSmrg /* Bitmap of blocks that have had EH statements cleaned.  We should
851debfc3dSmrg    remove their dead edges eventually.  */
861debfc3dSmrg static bitmap need_eh_cleanup;
871debfc3dSmrg 
881debfc3dSmrg /* STMT is a statement that may write into memory.  Analyze it and
891debfc3dSmrg    initialize WRITE to describe how STMT affects memory.
901debfc3dSmrg 
91*8feb0f0bSmrg    Return TRUE if the statement was analyzed, FALSE otherwise.
921debfc3dSmrg 
931debfc3dSmrg    It is always safe to return FALSE.  But typically better optimziation
941debfc3dSmrg    can be achieved by analyzing more statements.  */
951debfc3dSmrg 
961debfc3dSmrg static bool
initialize_ao_ref_for_dse(gimple * stmt,ao_ref * write)971debfc3dSmrg initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write)
981debfc3dSmrg {
991debfc3dSmrg   /* It's advantageous to handle certain mem* functions.  */
1001debfc3dSmrg   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
1011debfc3dSmrg     {
1021debfc3dSmrg       switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
1031debfc3dSmrg 	{
1041debfc3dSmrg 	case BUILT_IN_MEMCPY:
1051debfc3dSmrg 	case BUILT_IN_MEMMOVE:
1061debfc3dSmrg 	case BUILT_IN_MEMSET:
107*8feb0f0bSmrg 	case BUILT_IN_MEMCPY_CHK:
108*8feb0f0bSmrg 	case BUILT_IN_MEMMOVE_CHK:
109*8feb0f0bSmrg 	case BUILT_IN_MEMSET_CHK:
110*8feb0f0bSmrg 	case BUILT_IN_STRNCPY:
111*8feb0f0bSmrg 	case BUILT_IN_STRNCPY_CHK:
1121debfc3dSmrg 	  {
113*8feb0f0bSmrg 	    tree size = gimple_call_arg (stmt, 2);
1141debfc3dSmrg 	    tree ptr = gimple_call_arg (stmt, 0);
1151debfc3dSmrg 	    ao_ref_init_from_ptr_and_size (write, ptr, size);
1161debfc3dSmrg 	    return true;
1171debfc3dSmrg 	  }
118*8feb0f0bSmrg 
119*8feb0f0bSmrg 	/* A calloc call can never be dead, but it can make
120*8feb0f0bSmrg 	   subsequent stores redundant if they store 0 into
121*8feb0f0bSmrg 	   the same memory locations.  */
122*8feb0f0bSmrg 	case BUILT_IN_CALLOC:
123*8feb0f0bSmrg 	  {
124*8feb0f0bSmrg 	    tree nelem = gimple_call_arg (stmt, 0);
125*8feb0f0bSmrg 	    tree selem = gimple_call_arg (stmt, 1);
126*8feb0f0bSmrg 	    tree lhs;
127*8feb0f0bSmrg 	    if (TREE_CODE (nelem) == INTEGER_CST
128*8feb0f0bSmrg 		&& TREE_CODE (selem) == INTEGER_CST
129*8feb0f0bSmrg 		&& (lhs = gimple_call_lhs (stmt)) != NULL_TREE)
130*8feb0f0bSmrg 	      {
131*8feb0f0bSmrg 		tree size = fold_build2 (MULT_EXPR, TREE_TYPE (nelem),
132*8feb0f0bSmrg 					 nelem, selem);
133*8feb0f0bSmrg 		ao_ref_init_from_ptr_and_size (write, lhs, size);
134*8feb0f0bSmrg 		return true;
135*8feb0f0bSmrg 	      }
136*8feb0f0bSmrg 	  }
137*8feb0f0bSmrg 
1381debfc3dSmrg 	default:
1391debfc3dSmrg 	  break;
1401debfc3dSmrg 	}
1411debfc3dSmrg     }
1421debfc3dSmrg   else if (is_gimple_assign (stmt))
1431debfc3dSmrg     {
1441debfc3dSmrg       ao_ref_init (write, gimple_assign_lhs (stmt));
1451debfc3dSmrg       return true;
1461debfc3dSmrg     }
1471debfc3dSmrg   return false;
1481debfc3dSmrg }
1491debfc3dSmrg 
150*8feb0f0bSmrg /* Given REF from the alias oracle, return TRUE if it is a valid
1511debfc3dSmrg    memory reference for dead store elimination, false otherwise.
1521debfc3dSmrg 
1531debfc3dSmrg    In particular, the reference must have a known base, known maximum
1541debfc3dSmrg    size, start at a byte offset and have a size that is one or more
1551debfc3dSmrg    bytes.  */
1561debfc3dSmrg 
1571debfc3dSmrg static bool
valid_ao_ref_for_dse(ao_ref * ref)1581debfc3dSmrg valid_ao_ref_for_dse (ao_ref *ref)
1591debfc3dSmrg {
1601debfc3dSmrg   return (ao_ref_base (ref)
161a2dc1f3fSmrg 	  && known_size_p (ref->max_size)
162a2dc1f3fSmrg 	  && maybe_ne (ref->size, 0)
163a2dc1f3fSmrg 	  && known_eq (ref->max_size, ref->size)
164a2dc1f3fSmrg 	  && known_ge (ref->offset, 0)
165a2dc1f3fSmrg 	  && multiple_p (ref->offset, BITS_PER_UNIT)
166a2dc1f3fSmrg 	  && multiple_p (ref->size, BITS_PER_UNIT));
1671debfc3dSmrg }
1681debfc3dSmrg 
169a2dc1f3fSmrg /* Try to normalize COPY (an ao_ref) relative to REF.  Essentially when we are
170a2dc1f3fSmrg    done COPY will only refer bytes found within REF.  Return true if COPY
171a2dc1f3fSmrg    is known to intersect at least one byte of REF.  */
1721debfc3dSmrg 
173a2dc1f3fSmrg static bool
normalize_ref(ao_ref * copy,ao_ref * ref)1741debfc3dSmrg normalize_ref (ao_ref *copy, ao_ref *ref)
1751debfc3dSmrg {
176a2dc1f3fSmrg   if (!ordered_p (copy->offset, ref->offset))
177a2dc1f3fSmrg     return false;
178a2dc1f3fSmrg 
1791debfc3dSmrg   /* If COPY starts before REF, then reset the beginning of
1801debfc3dSmrg      COPY to match REF and decrease the size of COPY by the
1811debfc3dSmrg      number of bytes removed from COPY.  */
182a2dc1f3fSmrg   if (maybe_lt (copy->offset, ref->offset))
1831debfc3dSmrg     {
184a2dc1f3fSmrg       poly_int64 diff = ref->offset - copy->offset;
185a2dc1f3fSmrg       if (maybe_le (copy->size, diff))
186a2dc1f3fSmrg 	return false;
187a2dc1f3fSmrg       copy->size -= diff;
1881debfc3dSmrg       copy->offset = ref->offset;
1891debfc3dSmrg     }
1901debfc3dSmrg 
191a2dc1f3fSmrg   poly_int64 diff = copy->offset - ref->offset;
192a2dc1f3fSmrg   if (maybe_le (ref->size, diff))
193a2dc1f3fSmrg     return false;
194a2dc1f3fSmrg 
1951debfc3dSmrg   /* If COPY extends beyond REF, chop off its size appropriately.  */
196a2dc1f3fSmrg   poly_int64 limit = ref->size - diff;
197a2dc1f3fSmrg   if (!ordered_p (limit, copy->size))
198a2dc1f3fSmrg     return false;
199a2dc1f3fSmrg 
200a2dc1f3fSmrg   if (maybe_gt (copy->size, limit))
201a2dc1f3fSmrg     copy->size = limit;
202a2dc1f3fSmrg   return true;
2031debfc3dSmrg }
2041debfc3dSmrg 
2051debfc3dSmrg /* Clear any bytes written by STMT from the bitmap LIVE_BYTES.  The base
2061debfc3dSmrg    address written by STMT must match the one found in REF, which must
2071debfc3dSmrg    have its base address previously initialized.
2081debfc3dSmrg 
2091debfc3dSmrg    This routine must be conservative.  If we don't know the offset or
2101debfc3dSmrg    actual size written, assume nothing was written.  */
2111debfc3dSmrg 
2121debfc3dSmrg static void
clear_bytes_written_by(sbitmap live_bytes,gimple * stmt,ao_ref * ref)2131debfc3dSmrg clear_bytes_written_by (sbitmap live_bytes, gimple *stmt, ao_ref *ref)
2141debfc3dSmrg {
2151debfc3dSmrg   ao_ref write;
2161debfc3dSmrg   if (!initialize_ao_ref_for_dse (stmt, &write))
2171debfc3dSmrg     return;
2181debfc3dSmrg 
2191debfc3dSmrg   /* Verify we have the same base memory address, the write
2201debfc3dSmrg      has a known size and overlaps with REF.  */
221a2dc1f3fSmrg   HOST_WIDE_INT start, size;
2221debfc3dSmrg   if (valid_ao_ref_for_dse (&write)
2231debfc3dSmrg       && operand_equal_p (write.base, ref->base, OEP_ADDRESS_OF)
224a2dc1f3fSmrg       && known_eq (write.size, write.max_size)
225a2dc1f3fSmrg       && normalize_ref (&write, ref)
226a2dc1f3fSmrg       && (write.offset - ref->offset).is_constant (&start)
227a2dc1f3fSmrg       && write.size.is_constant (&size))
228a2dc1f3fSmrg     bitmap_clear_range (live_bytes, start / BITS_PER_UNIT,
229a2dc1f3fSmrg 			size / BITS_PER_UNIT);
2301debfc3dSmrg }
2311debfc3dSmrg 
2321debfc3dSmrg /* REF is a memory write.  Extract relevant information from it and
2331debfc3dSmrg    initialize the LIVE_BYTES bitmap.  If successful, return TRUE.
2341debfc3dSmrg    Otherwise return FALSE.  */
2351debfc3dSmrg 
2361debfc3dSmrg static bool
setup_live_bytes_from_ref(ao_ref * ref,sbitmap live_bytes)2371debfc3dSmrg setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes)
2381debfc3dSmrg {
239a2dc1f3fSmrg   HOST_WIDE_INT const_size;
2401debfc3dSmrg   if (valid_ao_ref_for_dse (ref)
241a2dc1f3fSmrg       && ref->size.is_constant (&const_size)
242a2dc1f3fSmrg       && (const_size / BITS_PER_UNIT
243*8feb0f0bSmrg 	  <= param_dse_max_object_size))
2441debfc3dSmrg     {
2451debfc3dSmrg       bitmap_clear (live_bytes);
246a2dc1f3fSmrg       bitmap_set_range (live_bytes, 0, const_size / BITS_PER_UNIT);
2471debfc3dSmrg       return true;
2481debfc3dSmrg     }
2491debfc3dSmrg   return false;
2501debfc3dSmrg }
2511debfc3dSmrg 
2521debfc3dSmrg /* Compute the number of elements that we can trim from the head and
2531debfc3dSmrg    tail of ORIG resulting in a bitmap that is a superset of LIVE.
2541debfc3dSmrg 
2551debfc3dSmrg    Store the number of elements trimmed from the head and tail in
2561debfc3dSmrg    TRIM_HEAD and TRIM_TAIL.
2571debfc3dSmrg 
2581debfc3dSmrg    STMT is the statement being trimmed and is used for debugging dump
2591debfc3dSmrg    output only.  */
2601debfc3dSmrg 
2611debfc3dSmrg static void
compute_trims(ao_ref * ref,sbitmap live,int * trim_head,int * trim_tail,gimple * stmt)2621debfc3dSmrg compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail,
2631debfc3dSmrg 	       gimple *stmt)
2641debfc3dSmrg {
2651debfc3dSmrg   /* We use sbitmaps biased such that ref->offset is bit zero and the bitmap
2661debfc3dSmrg      extends through ref->size.  So we know that in the original bitmap
2671debfc3dSmrg      bits 0..ref->size were true.  We don't actually need the bitmap, just
2681debfc3dSmrg      the REF to compute the trims.  */
2691debfc3dSmrg 
2701debfc3dSmrg   /* Now identify how much, if any of the tail we can chop off.  */
271a2dc1f3fSmrg   HOST_WIDE_INT const_size;
272c0a68be4Smrg   int last_live = bitmap_last_set_bit (live);
273a2dc1f3fSmrg   if (ref->size.is_constant (&const_size))
274a2dc1f3fSmrg     {
275a2dc1f3fSmrg       int last_orig = (const_size / BITS_PER_UNIT) - 1;
276c0a68be4Smrg       /* We can leave inconvenient amounts on the tail as
277c0a68be4Smrg 	 residual handling in mem* and str* functions is usually
278c0a68be4Smrg 	 reasonably efficient.  */
279c0a68be4Smrg       *trim_tail = last_orig - last_live;
280c0a68be4Smrg 
281c0a68be4Smrg       /* But don't trim away out of bounds accesses, as this defeats
282c0a68be4Smrg 	 proper warnings.
283c0a68be4Smrg 
284c0a68be4Smrg 	 We could have a type with no TYPE_SIZE_UNIT or we could have a VLA
285c0a68be4Smrg 	 where TYPE_SIZE_UNIT is not a constant.  */
286c0a68be4Smrg       if (*trim_tail
287c0a68be4Smrg 	  && TYPE_SIZE_UNIT (TREE_TYPE (ref->base))
288c0a68be4Smrg 	  && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (ref->base))) == INTEGER_CST
289c0a68be4Smrg 	  && compare_tree_int (TYPE_SIZE_UNIT (TREE_TYPE (ref->base)),
290c0a68be4Smrg 			       last_orig) <= 0)
291c0a68be4Smrg 	*trim_tail = 0;
292a2dc1f3fSmrg     }
293a2dc1f3fSmrg   else
294a2dc1f3fSmrg     *trim_tail = 0;
2951debfc3dSmrg 
2961debfc3dSmrg   /* Identify how much, if any of the head we can chop off.  */
2971debfc3dSmrg   int first_orig = 0;
2981debfc3dSmrg   int first_live = bitmap_first_set_bit (live);
299c0a68be4Smrg   *trim_head = first_live - first_orig;
300c0a68be4Smrg 
301c0a68be4Smrg   /* If more than a word remains, then make sure to keep the
302c0a68be4Smrg      starting point at least word aligned.  */
303c0a68be4Smrg   if (last_live - first_live > UNITS_PER_WORD)
304c0a68be4Smrg     *trim_head &= ~(UNITS_PER_WORD - 1);
3051debfc3dSmrg 
3061debfc3dSmrg   if ((*trim_head || *trim_tail)
3071debfc3dSmrg       && dump_file && (dump_flags & TDF_DETAILS))
3081debfc3dSmrg     {
3091debfc3dSmrg       fprintf (dump_file, "  Trimming statement (head = %d, tail = %d): ",
3101debfc3dSmrg 	       *trim_head, *trim_tail);
311a2dc1f3fSmrg       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
3121debfc3dSmrg       fprintf (dump_file, "\n");
3131debfc3dSmrg     }
3141debfc3dSmrg }
3151debfc3dSmrg 
3161debfc3dSmrg /* STMT initializes an object from COMPLEX_CST where one or more of the
3171debfc3dSmrg    bytes written may be dead stores.  REF is a representation of the
3181debfc3dSmrg    memory written.  LIVE is the bitmap of stores that are actually live.
3191debfc3dSmrg 
3201debfc3dSmrg    Attempt to rewrite STMT so that only the real or imaginary part of
3211debfc3dSmrg    the object is actually stored.  */
3221debfc3dSmrg 
3231debfc3dSmrg static void
maybe_trim_complex_store(ao_ref * ref,sbitmap live,gimple * stmt)3241debfc3dSmrg maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt)
3251debfc3dSmrg {
3261debfc3dSmrg   int trim_head, trim_tail;
3271debfc3dSmrg   compute_trims (ref, live, &trim_head, &trim_tail, stmt);
3281debfc3dSmrg 
3291debfc3dSmrg   /* The amount of data trimmed from the head or tail must be at
3301debfc3dSmrg      least half the size of the object to ensure we're trimming
3311debfc3dSmrg      the entire real or imaginary half.  By writing things this
3321debfc3dSmrg      way we avoid more O(n) bitmap operations.  */
333a2dc1f3fSmrg   if (known_ge (trim_tail * 2 * BITS_PER_UNIT, ref->size))
3341debfc3dSmrg     {
3351debfc3dSmrg       /* TREE_REALPART is live */
3361debfc3dSmrg       tree x = TREE_REALPART (gimple_assign_rhs1 (stmt));
3371debfc3dSmrg       tree y = gimple_assign_lhs (stmt);
3381debfc3dSmrg       y = build1 (REALPART_EXPR, TREE_TYPE (x), y);
3391debfc3dSmrg       gimple_assign_set_lhs (stmt, y);
3401debfc3dSmrg       gimple_assign_set_rhs1 (stmt, x);
3411debfc3dSmrg     }
342a2dc1f3fSmrg   else if (known_ge (trim_head * 2 * BITS_PER_UNIT, ref->size))
3431debfc3dSmrg     {
3441debfc3dSmrg       /* TREE_IMAGPART is live */
3451debfc3dSmrg       tree x = TREE_IMAGPART (gimple_assign_rhs1 (stmt));
3461debfc3dSmrg       tree y = gimple_assign_lhs (stmt);
3471debfc3dSmrg       y = build1 (IMAGPART_EXPR, TREE_TYPE (x), y);
3481debfc3dSmrg       gimple_assign_set_lhs (stmt, y);
3491debfc3dSmrg       gimple_assign_set_rhs1 (stmt, x);
3501debfc3dSmrg     }
3511debfc3dSmrg 
3521debfc3dSmrg   /* Other cases indicate parts of both the real and imag subobjects
3531debfc3dSmrg      are live.  We do not try to optimize those cases.  */
3541debfc3dSmrg }
3551debfc3dSmrg 
3561debfc3dSmrg /* STMT initializes an object using a CONSTRUCTOR where one or more of the
3571debfc3dSmrg    bytes written are dead stores.  ORIG is the bitmap of bytes stored by
3581debfc3dSmrg    STMT.  LIVE is the bitmap of stores that are actually live.
3591debfc3dSmrg 
3601debfc3dSmrg    Attempt to rewrite STMT so that only the real or imaginary part of
3611debfc3dSmrg    the object is actually stored.
3621debfc3dSmrg 
3631debfc3dSmrg    The most common case for getting here is a CONSTRUCTOR with no elements
3641debfc3dSmrg    being used to zero initialize an object.  We do not try to handle other
3651debfc3dSmrg    cases as those would force us to fully cover the object with the
3661debfc3dSmrg    CONSTRUCTOR node except for the components that are dead.  */
3671debfc3dSmrg 
3681debfc3dSmrg static void
maybe_trim_constructor_store(ao_ref * ref,sbitmap live,gimple * stmt)3691debfc3dSmrg maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt)
3701debfc3dSmrg {
3711debfc3dSmrg   tree ctor = gimple_assign_rhs1 (stmt);
3721debfc3dSmrg 
3731debfc3dSmrg   /* This is the only case we currently handle.  It actually seems to
3741debfc3dSmrg      catch most cases of actual interest.  */
3751debfc3dSmrg   gcc_assert (CONSTRUCTOR_NELTS (ctor) == 0);
3761debfc3dSmrg 
3771debfc3dSmrg   int head_trim = 0;
3781debfc3dSmrg   int tail_trim = 0;
3791debfc3dSmrg   compute_trims (ref, live, &head_trim, &tail_trim, stmt);
3801debfc3dSmrg 
3811debfc3dSmrg   /* Now we want to replace the constructor initializer
3821debfc3dSmrg      with memset (object + head_trim, 0, size - head_trim - tail_trim).  */
3831debfc3dSmrg   if (head_trim || tail_trim)
3841debfc3dSmrg     {
3851debfc3dSmrg       /* We want &lhs for the MEM_REF expression.  */
3861debfc3dSmrg       tree lhs_addr = build_fold_addr_expr (gimple_assign_lhs (stmt));
3871debfc3dSmrg 
3881debfc3dSmrg       if (! is_gimple_min_invariant (lhs_addr))
3891debfc3dSmrg 	return;
3901debfc3dSmrg 
3911debfc3dSmrg       /* The number of bytes for the new constructor.  */
392a2dc1f3fSmrg       poly_int64 ref_bytes = exact_div (ref->size, BITS_PER_UNIT);
393a2dc1f3fSmrg       poly_int64 count = ref_bytes - head_trim - tail_trim;
3941debfc3dSmrg 
3951debfc3dSmrg       /* And the new type for the CONSTRUCTOR.  Essentially it's just
3961debfc3dSmrg 	 a char array large enough to cover the non-trimmed parts of
3971debfc3dSmrg 	 the original CONSTRUCTOR.  Note we want explicit bounds here
3981debfc3dSmrg 	 so that we know how many bytes to clear when expanding the
3991debfc3dSmrg 	 CONSTRUCTOR.  */
4001debfc3dSmrg       tree type = build_array_type_nelts (char_type_node, count);
4011debfc3dSmrg 
4021debfc3dSmrg       /* Build a suitable alias type rather than using alias set zero
4031debfc3dSmrg 	 to avoid pessimizing.  */
4041debfc3dSmrg       tree alias_type = reference_alias_ptr_type (gimple_assign_lhs (stmt));
4051debfc3dSmrg 
4061debfc3dSmrg       /* Build a MEM_REF representing the whole accessed area, starting
4071debfc3dSmrg 	 at the first byte not trimmed.  */
4081debfc3dSmrg       tree exp = fold_build2 (MEM_REF, type, lhs_addr,
4091debfc3dSmrg 			      build_int_cst (alias_type, head_trim));
4101debfc3dSmrg 
4111debfc3dSmrg       /* Now update STMT with a new RHS and LHS.  */
4121debfc3dSmrg       gimple_assign_set_lhs (stmt, exp);
4131debfc3dSmrg       gimple_assign_set_rhs1 (stmt, build_constructor (type, NULL));
4141debfc3dSmrg     }
4151debfc3dSmrg }
4161debfc3dSmrg 
4171debfc3dSmrg /* STMT is a memcpy, memmove or memset.  Decrement the number of bytes
4181debfc3dSmrg    copied/set by DECREMENT.  */
4191debfc3dSmrg static void
decrement_count(gimple * stmt,int decrement)4201debfc3dSmrg decrement_count (gimple *stmt, int decrement)
4211debfc3dSmrg {
4221debfc3dSmrg   tree *countp = gimple_call_arg_ptr (stmt, 2);
4231debfc3dSmrg   gcc_assert (TREE_CODE (*countp) == INTEGER_CST);
4241debfc3dSmrg   *countp = wide_int_to_tree (TREE_TYPE (*countp), (TREE_INT_CST_LOW (*countp)
4251debfc3dSmrg 						    - decrement));
4261debfc3dSmrg }
4271debfc3dSmrg 
4281debfc3dSmrg static void
increment_start_addr(gimple * stmt,tree * where,int increment)4291debfc3dSmrg increment_start_addr (gimple *stmt, tree *where, int increment)
4301debfc3dSmrg {
431*8feb0f0bSmrg   if (tree lhs = gimple_call_lhs (stmt))
432*8feb0f0bSmrg     if (where == gimple_call_arg_ptr (stmt, 0))
433*8feb0f0bSmrg       {
434*8feb0f0bSmrg 	gassign *newop = gimple_build_assign (lhs, unshare_expr (*where));
435*8feb0f0bSmrg 	gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
436*8feb0f0bSmrg 	gsi_insert_after (&gsi, newop, GSI_SAME_STMT);
437*8feb0f0bSmrg 	gimple_call_set_lhs (stmt, NULL_TREE);
438*8feb0f0bSmrg 	update_stmt (stmt);
439*8feb0f0bSmrg       }
440*8feb0f0bSmrg 
4411debfc3dSmrg   if (TREE_CODE (*where) == SSA_NAME)
4421debfc3dSmrg     {
4431debfc3dSmrg       tree tem = make_ssa_name (TREE_TYPE (*where));
4441debfc3dSmrg       gassign *newop
4451debfc3dSmrg 	= gimple_build_assign (tem, POINTER_PLUS_EXPR, *where,
4461debfc3dSmrg 			       build_int_cst (sizetype, increment));
4471debfc3dSmrg       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
4481debfc3dSmrg       gsi_insert_before (&gsi, newop, GSI_SAME_STMT);
4491debfc3dSmrg       *where = tem;
450*8feb0f0bSmrg       update_stmt (stmt);
4511debfc3dSmrg       return;
4521debfc3dSmrg     }
4531debfc3dSmrg 
4541debfc3dSmrg   *where = build_fold_addr_expr (fold_build2 (MEM_REF, char_type_node,
4551debfc3dSmrg 					      *where,
4561debfc3dSmrg 					      build_int_cst (ptr_type_node,
4571debfc3dSmrg 							     increment)));
4581debfc3dSmrg }
4591debfc3dSmrg 
4601debfc3dSmrg /* STMT is builtin call that writes bytes in bitmap ORIG, some bytes are dead
4611debfc3dSmrg    (ORIG & ~NEW) and need not be stored.  Try to rewrite STMT to reduce
4621debfc3dSmrg    the amount of data it actually writes.
4631debfc3dSmrg 
4641debfc3dSmrg    Right now we only support trimming from the head or the tail of the
4651debfc3dSmrg    memory region.  In theory we could split the mem* call, but it's
4661debfc3dSmrg    likely of marginal value.  */
4671debfc3dSmrg 
4681debfc3dSmrg static void
maybe_trim_memstar_call(ao_ref * ref,sbitmap live,gimple * stmt)4691debfc3dSmrg maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
4701debfc3dSmrg {
471*8feb0f0bSmrg   int head_trim, tail_trim;
4721debfc3dSmrg   switch (DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)))
4731debfc3dSmrg     {
474*8feb0f0bSmrg     case BUILT_IN_STRNCPY:
475*8feb0f0bSmrg     case BUILT_IN_STRNCPY_CHK:
476*8feb0f0bSmrg       compute_trims (ref, live, &head_trim, &tail_trim, stmt);
477*8feb0f0bSmrg       if (head_trim)
478*8feb0f0bSmrg 	{
479*8feb0f0bSmrg 	  /* Head trimming of strncpy is only possible if we can
480*8feb0f0bSmrg 	     prove all bytes we would trim are non-zero (or we could
481*8feb0f0bSmrg 	     turn the strncpy into memset if there must be zero
482*8feb0f0bSmrg 	     among the head trimmed bytes).  If we don't know anything
483*8feb0f0bSmrg 	     about those bytes, the presence or absence of '\0' bytes
484*8feb0f0bSmrg 	     in there will affect whether it acts for the non-trimmed
485*8feb0f0bSmrg 	     bytes as memset or memcpy/strncpy.  */
486*8feb0f0bSmrg 	  c_strlen_data lendata = { };
487*8feb0f0bSmrg 	  int orig_head_trim = head_trim;
488*8feb0f0bSmrg 	  tree srcstr = gimple_call_arg (stmt, 1);
489*8feb0f0bSmrg 	  if (!get_range_strlen (srcstr, &lendata, /*eltsize=*/1)
490*8feb0f0bSmrg 	      || !tree_fits_uhwi_p (lendata.minlen))
491*8feb0f0bSmrg 	    head_trim = 0;
492*8feb0f0bSmrg 	  else if (tree_to_uhwi (lendata.minlen) < (unsigned) head_trim)
493*8feb0f0bSmrg 	    {
494*8feb0f0bSmrg 	      head_trim = tree_to_uhwi (lendata.minlen);
495*8feb0f0bSmrg 	      if ((orig_head_trim & (UNITS_PER_WORD - 1)) == 0)
496*8feb0f0bSmrg 		head_trim &= ~(UNITS_PER_WORD - 1);
497*8feb0f0bSmrg 	    }
498*8feb0f0bSmrg 	  if (orig_head_trim != head_trim
499*8feb0f0bSmrg 	      && dump_file
500*8feb0f0bSmrg 	      && (dump_flags & TDF_DETAILS))
501*8feb0f0bSmrg 	    fprintf (dump_file,
502*8feb0f0bSmrg 		     "  Adjusting strncpy trimming to (head = %d,"
503*8feb0f0bSmrg 		     " tail = %d)\n", head_trim, tail_trim);
504*8feb0f0bSmrg 	}
505*8feb0f0bSmrg       goto do_memcpy;
506*8feb0f0bSmrg 
5071debfc3dSmrg     case BUILT_IN_MEMCPY:
5081debfc3dSmrg     case BUILT_IN_MEMMOVE:
509*8feb0f0bSmrg     case BUILT_IN_MEMCPY_CHK:
510*8feb0f0bSmrg     case BUILT_IN_MEMMOVE_CHK:
5111debfc3dSmrg       compute_trims (ref, live, &head_trim, &tail_trim, stmt);
5121debfc3dSmrg 
513*8feb0f0bSmrg     do_memcpy:
5141debfc3dSmrg       /* Tail trimming is easy, we can just reduce the count.  */
5151debfc3dSmrg       if (tail_trim)
5161debfc3dSmrg 	decrement_count (stmt, tail_trim);
5171debfc3dSmrg 
5181debfc3dSmrg       /* Head trimming requires adjusting all the arguments.  */
5191debfc3dSmrg       if (head_trim)
5201debfc3dSmrg 	{
521*8feb0f0bSmrg 	  /* For __*_chk need to adjust also the last argument.  */
522*8feb0f0bSmrg 	  if (gimple_call_num_args (stmt) == 4)
523*8feb0f0bSmrg 	    {
524*8feb0f0bSmrg 	      tree size = gimple_call_arg (stmt, 3);
525*8feb0f0bSmrg 	      if (!tree_fits_uhwi_p (size))
526*8feb0f0bSmrg 		break;
527*8feb0f0bSmrg 	      if (!integer_all_onesp (size))
528*8feb0f0bSmrg 		{
529*8feb0f0bSmrg 		  unsigned HOST_WIDE_INT sz = tree_to_uhwi (size);
530*8feb0f0bSmrg 		  if (sz < (unsigned) head_trim)
531*8feb0f0bSmrg 		    break;
532*8feb0f0bSmrg 		  tree arg = wide_int_to_tree (TREE_TYPE (size),
533*8feb0f0bSmrg 					       sz - head_trim);
534*8feb0f0bSmrg 		  gimple_call_set_arg (stmt, 3, arg);
535*8feb0f0bSmrg 		}
536*8feb0f0bSmrg 	    }
5371debfc3dSmrg 	  tree *dst = gimple_call_arg_ptr (stmt, 0);
5381debfc3dSmrg 	  increment_start_addr (stmt, dst, head_trim);
5391debfc3dSmrg 	  tree *src = gimple_call_arg_ptr (stmt, 1);
5401debfc3dSmrg 	  increment_start_addr (stmt, src, head_trim);
5411debfc3dSmrg 	  decrement_count (stmt, head_trim);
5421debfc3dSmrg 	}
5431debfc3dSmrg       break;
5441debfc3dSmrg 
5451debfc3dSmrg     case BUILT_IN_MEMSET:
546*8feb0f0bSmrg     case BUILT_IN_MEMSET_CHK:
5471debfc3dSmrg       compute_trims (ref, live, &head_trim, &tail_trim, stmt);
5481debfc3dSmrg 
5491debfc3dSmrg       /* Tail trimming is easy, we can just reduce the count.  */
5501debfc3dSmrg       if (tail_trim)
5511debfc3dSmrg 	decrement_count (stmt, tail_trim);
5521debfc3dSmrg 
5531debfc3dSmrg       /* Head trimming requires adjusting all the arguments.  */
5541debfc3dSmrg       if (head_trim)
5551debfc3dSmrg 	{
556*8feb0f0bSmrg 	  /* For __*_chk need to adjust also the last argument.  */
557*8feb0f0bSmrg 	  if (gimple_call_num_args (stmt) == 4)
558*8feb0f0bSmrg 	    {
559*8feb0f0bSmrg 	      tree size = gimple_call_arg (stmt, 3);
560*8feb0f0bSmrg 	      if (!tree_fits_uhwi_p (size))
561*8feb0f0bSmrg 		break;
562*8feb0f0bSmrg 	      if (!integer_all_onesp (size))
563*8feb0f0bSmrg 		{
564*8feb0f0bSmrg 		  unsigned HOST_WIDE_INT sz = tree_to_uhwi (size);
565*8feb0f0bSmrg 		  if (sz < (unsigned) head_trim)
566*8feb0f0bSmrg 		    break;
567*8feb0f0bSmrg 		  tree arg = wide_int_to_tree (TREE_TYPE (size),
568*8feb0f0bSmrg 					       sz - head_trim);
569*8feb0f0bSmrg 		  gimple_call_set_arg (stmt, 3, arg);
570*8feb0f0bSmrg 		}
571*8feb0f0bSmrg 	    }
5721debfc3dSmrg 	  tree *dst = gimple_call_arg_ptr (stmt, 0);
5731debfc3dSmrg 	  increment_start_addr (stmt, dst, head_trim);
5741debfc3dSmrg 	  decrement_count (stmt, head_trim);
5751debfc3dSmrg 	}
5761debfc3dSmrg       break;
5771debfc3dSmrg 
5781debfc3dSmrg     default:
5791debfc3dSmrg       break;
5801debfc3dSmrg     }
5811debfc3dSmrg }
5821debfc3dSmrg 
5831debfc3dSmrg /* STMT is a memory write where one or more bytes written are dead
5841debfc3dSmrg    stores.  ORIG is the bitmap of bytes stored by STMT.  LIVE is the
5851debfc3dSmrg    bitmap of stores that are actually live.
5861debfc3dSmrg 
5871debfc3dSmrg    Attempt to rewrite STMT so that it writes fewer memory locations.  Right
5881debfc3dSmrg    now we only support trimming at the start or end of the memory region.
5891debfc3dSmrg    It's not clear how much there is to be gained by trimming from the middle
5901debfc3dSmrg    of the region.  */
5911debfc3dSmrg 
5921debfc3dSmrg static void
maybe_trim_partially_dead_store(ao_ref * ref,sbitmap live,gimple * stmt)5931debfc3dSmrg maybe_trim_partially_dead_store (ao_ref *ref, sbitmap live, gimple *stmt)
5941debfc3dSmrg {
5951debfc3dSmrg   if (is_gimple_assign (stmt)
5961debfc3dSmrg       && TREE_CODE (gimple_assign_lhs (stmt)) != TARGET_MEM_REF)
5971debfc3dSmrg     {
5981debfc3dSmrg       switch (gimple_assign_rhs_code (stmt))
5991debfc3dSmrg 	{
6001debfc3dSmrg 	case CONSTRUCTOR:
6011debfc3dSmrg 	  maybe_trim_constructor_store (ref, live, stmt);
6021debfc3dSmrg 	  break;
6031debfc3dSmrg 	case COMPLEX_CST:
6041debfc3dSmrg 	  maybe_trim_complex_store (ref, live, stmt);
6051debfc3dSmrg 	  break;
6061debfc3dSmrg 	default:
6071debfc3dSmrg 	  break;
6081debfc3dSmrg 	}
6091debfc3dSmrg     }
6101debfc3dSmrg }
6111debfc3dSmrg 
612a2dc1f3fSmrg /* Return TRUE if USE_REF reads bytes from LIVE where live is
613a2dc1f3fSmrg    derived from REF, a write reference.
614a2dc1f3fSmrg 
615a2dc1f3fSmrg    While this routine may modify USE_REF, it's passed by value, not
616a2dc1f3fSmrg    location.  So callers do not see those modifications.  */
617a2dc1f3fSmrg 
618a2dc1f3fSmrg static bool
live_bytes_read(ao_ref use_ref,ao_ref * ref,sbitmap live)619a2dc1f3fSmrg live_bytes_read (ao_ref use_ref, ao_ref *ref, sbitmap live)
620a2dc1f3fSmrg {
621a2dc1f3fSmrg   /* We have already verified that USE_REF and REF hit the same object.
622a2dc1f3fSmrg      Now verify that there's actually an overlap between USE_REF and REF.  */
623a2dc1f3fSmrg   HOST_WIDE_INT start, size;
624a2dc1f3fSmrg   if (normalize_ref (&use_ref, ref)
625a2dc1f3fSmrg       && (use_ref.offset - ref->offset).is_constant (&start)
626a2dc1f3fSmrg       && use_ref.size.is_constant (&size))
627a2dc1f3fSmrg     {
628a2dc1f3fSmrg       /* If USE_REF covers all of REF, then it will hit one or more
629a2dc1f3fSmrg 	 live bytes.   This avoids useless iteration over the bitmap
630a2dc1f3fSmrg 	 below.  */
631a2dc1f3fSmrg       if (start == 0 && known_eq (size, ref->size))
632a2dc1f3fSmrg 	return true;
633a2dc1f3fSmrg 
634a2dc1f3fSmrg       /* Now check if any of the remaining bits in use_ref are set in LIVE.  */
635a2dc1f3fSmrg       return bitmap_bit_in_range_p (live, start / BITS_PER_UNIT,
636a2dc1f3fSmrg 				    (start + size - 1) / BITS_PER_UNIT);
637a2dc1f3fSmrg     }
638a2dc1f3fSmrg   return true;
639a2dc1f3fSmrg }
640a2dc1f3fSmrg 
641c0a68be4Smrg /* Callback for dse_classify_store calling for_each_index.  Verify that
642c0a68be4Smrg    indices are invariant in the loop with backedge PHI in basic-block DATA.  */
643c0a68be4Smrg 
644c0a68be4Smrg static bool
check_name(tree,tree * idx,void * data)645c0a68be4Smrg check_name (tree, tree *idx, void *data)
646c0a68be4Smrg {
647c0a68be4Smrg   basic_block phi_bb = (basic_block) data;
648c0a68be4Smrg   if (TREE_CODE (*idx) == SSA_NAME
649c0a68be4Smrg       && !SSA_NAME_IS_DEFAULT_DEF (*idx)
650c0a68be4Smrg       && dominated_by_p (CDI_DOMINATORS, gimple_bb (SSA_NAME_DEF_STMT (*idx)),
651c0a68be4Smrg 			 phi_bb))
652c0a68be4Smrg     return false;
653c0a68be4Smrg   return true;
654c0a68be4Smrg }
655c0a68be4Smrg 
656*8feb0f0bSmrg /* STMT stores the value 0 into one or more memory locations
657*8feb0f0bSmrg    (via memset, empty constructor, calloc call, etc).
658*8feb0f0bSmrg 
659*8feb0f0bSmrg    See if there is a subsequent store of the value 0 to one
660*8feb0f0bSmrg    or more of the same memory location(s).  If so, the subsequent
661*8feb0f0bSmrg    store is redundant and can be removed.
662*8feb0f0bSmrg 
663*8feb0f0bSmrg    The subsequent stores could be via memset, empty constructors,
664*8feb0f0bSmrg    simple MEM stores, etc.  */
665*8feb0f0bSmrg 
666*8feb0f0bSmrg static void
dse_optimize_redundant_stores(gimple * stmt)667*8feb0f0bSmrg dse_optimize_redundant_stores (gimple *stmt)
668*8feb0f0bSmrg {
669*8feb0f0bSmrg   int cnt = 0;
670*8feb0f0bSmrg 
671*8feb0f0bSmrg   /* TBAA state of STMT, if it is a call it is effectively alias-set zero.  */
672*8feb0f0bSmrg   alias_set_type earlier_set = 0;
673*8feb0f0bSmrg   alias_set_type earlier_base_set = 0;
674*8feb0f0bSmrg   if (is_gimple_assign (stmt))
675*8feb0f0bSmrg     {
676*8feb0f0bSmrg       ao_ref lhs_ref;
677*8feb0f0bSmrg       ao_ref_init (&lhs_ref, gimple_assign_lhs (stmt));
678*8feb0f0bSmrg       earlier_set = ao_ref_alias_set (&lhs_ref);
679*8feb0f0bSmrg       earlier_base_set = ao_ref_base_alias_set (&lhs_ref);
680*8feb0f0bSmrg     }
681*8feb0f0bSmrg 
682*8feb0f0bSmrg   /* We could do something fairly complex and look through PHIs
683*8feb0f0bSmrg      like DSE_CLASSIFY_STORE, but it doesn't seem to be worth
684*8feb0f0bSmrg      the effort.
685*8feb0f0bSmrg 
686*8feb0f0bSmrg      Look at all the immediate uses of the VDEF (which are obviously
687*8feb0f0bSmrg      dominated by STMT).   See if one or more stores 0 into the same
688*8feb0f0bSmrg      memory locations a STMT, if so remove the immediate use statements.  */
689*8feb0f0bSmrg   tree defvar = gimple_vdef (stmt);
690*8feb0f0bSmrg   imm_use_iterator ui;
691*8feb0f0bSmrg   gimple *use_stmt;
692*8feb0f0bSmrg   FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
693*8feb0f0bSmrg     {
694*8feb0f0bSmrg       /* Limit stmt walking.  */
695*8feb0f0bSmrg       if (++cnt > param_dse_max_alias_queries_per_store)
696*8feb0f0bSmrg 	BREAK_FROM_IMM_USE_STMT (ui);
697*8feb0f0bSmrg 
698*8feb0f0bSmrg       /* If USE_STMT stores 0 into one or more of the same locations
699*8feb0f0bSmrg 	 as STMT and STMT would kill USE_STMT, then we can just remove
700*8feb0f0bSmrg 	 USE_STMT.  */
701*8feb0f0bSmrg       tree fndecl;
702*8feb0f0bSmrg       if ((is_gimple_assign (use_stmt)
703*8feb0f0bSmrg 	   && gimple_vdef (use_stmt)
704*8feb0f0bSmrg 	   && (gimple_assign_single_p (use_stmt)
705*8feb0f0bSmrg 	       && initializer_zerop (gimple_assign_rhs1 (use_stmt))))
706*8feb0f0bSmrg 	  || (gimple_call_builtin_p (use_stmt, BUILT_IN_NORMAL)
707*8feb0f0bSmrg 	      && (fndecl = gimple_call_fndecl (use_stmt)) != NULL
708*8feb0f0bSmrg 	      && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET
709*8feb0f0bSmrg 		  || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK)
710*8feb0f0bSmrg 	      && integer_zerop (gimple_call_arg (use_stmt, 1))))
711*8feb0f0bSmrg 	{
712*8feb0f0bSmrg 	  ao_ref write;
713*8feb0f0bSmrg 
714*8feb0f0bSmrg 	  if (!initialize_ao_ref_for_dse (use_stmt, &write))
715*8feb0f0bSmrg 	    BREAK_FROM_IMM_USE_STMT (ui)
716*8feb0f0bSmrg 
717*8feb0f0bSmrg 	  if (valid_ao_ref_for_dse (&write)
718*8feb0f0bSmrg 	      && stmt_kills_ref_p (stmt, &write))
719*8feb0f0bSmrg 	    {
720*8feb0f0bSmrg 	      gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
721*8feb0f0bSmrg 	      if (is_gimple_assign (use_stmt))
722*8feb0f0bSmrg 		{
723*8feb0f0bSmrg 		  ao_ref lhs_ref;
724*8feb0f0bSmrg 		  ao_ref_init (&lhs_ref, gimple_assign_lhs (use_stmt));
725*8feb0f0bSmrg 		  if ((earlier_set == ao_ref_alias_set (&lhs_ref)
726*8feb0f0bSmrg 		       || alias_set_subset_of (ao_ref_alias_set (&lhs_ref),
727*8feb0f0bSmrg 					       earlier_set))
728*8feb0f0bSmrg 		      && (earlier_base_set == ao_ref_base_alias_set (&lhs_ref)
729*8feb0f0bSmrg 			  || alias_set_subset_of
730*8feb0f0bSmrg 			       (ao_ref_base_alias_set (&lhs_ref),
731*8feb0f0bSmrg 						  earlier_base_set)))
732*8feb0f0bSmrg 		    delete_dead_or_redundant_assignment (&gsi, "redundant",
733*8feb0f0bSmrg 							 need_eh_cleanup);
734*8feb0f0bSmrg 		}
735*8feb0f0bSmrg 	      else if (is_gimple_call (use_stmt))
736*8feb0f0bSmrg 		{
737*8feb0f0bSmrg 		  if ((earlier_set == 0
738*8feb0f0bSmrg 		       || alias_set_subset_of (0, earlier_set))
739*8feb0f0bSmrg 		      && (earlier_base_set == 0
740*8feb0f0bSmrg 			  || alias_set_subset_of (0, earlier_base_set)))
741*8feb0f0bSmrg 		  delete_dead_or_redundant_call (&gsi, "redundant");
742*8feb0f0bSmrg 		}
743*8feb0f0bSmrg 	      else
744*8feb0f0bSmrg 		gcc_unreachable ();
745*8feb0f0bSmrg 	    }
746*8feb0f0bSmrg 	}
747*8feb0f0bSmrg     }
748*8feb0f0bSmrg }
749*8feb0f0bSmrg 
7501debfc3dSmrg /* A helper of dse_optimize_stmt.
751c0a68be4Smrg    Given a GIMPLE_ASSIGN in STMT that writes to REF, classify it
752c0a68be4Smrg    according to downstream uses and defs.  Sets *BY_CLOBBER_P to true
753c0a68be4Smrg    if only clobber statements influenced the classification result.
754c0a68be4Smrg    Returns the classification.  */
7551debfc3dSmrg 
756*8feb0f0bSmrg dse_store_status
dse_classify_store(ao_ref * ref,gimple * stmt,bool byte_tracking_enabled,sbitmap live_bytes,bool * by_clobber_p,tree stop_at_vuse)757c0a68be4Smrg dse_classify_store (ao_ref *ref, gimple *stmt,
758c0a68be4Smrg 		    bool byte_tracking_enabled, sbitmap live_bytes,
759*8feb0f0bSmrg 		    bool *by_clobber_p, tree stop_at_vuse)
7601debfc3dSmrg {
7611debfc3dSmrg   gimple *temp;
762c0a68be4Smrg   int cnt = 0;
763c0a68be4Smrg   auto_bitmap visited;
7641debfc3dSmrg 
765c0a68be4Smrg   if (by_clobber_p)
766c0a68be4Smrg     *by_clobber_p = true;
7671debfc3dSmrg 
7681debfc3dSmrg   /* Find the first dominated statement that clobbers (part of) the
7691debfc3dSmrg      memory stmt stores to with no intermediate statement that may use
7701debfc3dSmrg      part of the memory stmt stores.  That is, find a store that may
7711debfc3dSmrg      prove stmt to be a dead store.  */
7721debfc3dSmrg   temp = stmt;
7731debfc3dSmrg   do
7741debfc3dSmrg     {
775c0a68be4Smrg       gimple *use_stmt;
7761debfc3dSmrg       imm_use_iterator ui;
7771debfc3dSmrg       bool fail = false;
7781debfc3dSmrg       tree defvar;
7791debfc3dSmrg 
7801debfc3dSmrg       if (gimple_code (temp) == GIMPLE_PHI)
781c0a68be4Smrg 	{
782c0a68be4Smrg 	  /* If we visit this PHI by following a backedge then we have to
783c0a68be4Smrg 	     make sure ref->ref only refers to SSA names that are invariant
784c0a68be4Smrg 	     with respect to the loop represented by this PHI node.  */
785c0a68be4Smrg 	  if (dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt),
786c0a68be4Smrg 			      gimple_bb (temp))
787c0a68be4Smrg 	      && !for_each_index (ref->ref ? &ref->ref : &ref->base,
788c0a68be4Smrg 				  check_name, gimple_bb (temp)))
789c0a68be4Smrg 	    return DSE_STORE_LIVE;
7901debfc3dSmrg 	  defvar = PHI_RESULT (temp);
791c0a68be4Smrg 	  bitmap_set_bit (visited, SSA_NAME_VERSION (defvar));
792c0a68be4Smrg 	}
7931debfc3dSmrg       else
7941debfc3dSmrg 	defvar = gimple_vdef (temp);
795*8feb0f0bSmrg 
796*8feb0f0bSmrg       /* If we're instructed to stop walking at region boundary, do so.  */
797*8feb0f0bSmrg       if (defvar == stop_at_vuse)
798*8feb0f0bSmrg 	return DSE_STORE_LIVE;
799*8feb0f0bSmrg 
800c0a68be4Smrg       auto_vec<gimple *, 10> defs;
801c0a68be4Smrg       gimple *phi_def = NULL;
8021debfc3dSmrg       FOR_EACH_IMM_USE_STMT (use_stmt, ui, defvar)
8031debfc3dSmrg 	{
804c0a68be4Smrg 	  /* Limit stmt walking.  */
805*8feb0f0bSmrg 	  if (++cnt > param_dse_max_alias_queries_per_store)
8061debfc3dSmrg 	    {
8071debfc3dSmrg 	      fail = true;
8081debfc3dSmrg 	      BREAK_FROM_IMM_USE_STMT (ui);
8091debfc3dSmrg 	    }
810c0a68be4Smrg 
811c0a68be4Smrg 	  /* We have visited ourselves already so ignore STMT for the
812c0a68be4Smrg 	     purpose of chaining.  */
813c0a68be4Smrg 	  if (use_stmt == stmt)
814c0a68be4Smrg 	    ;
8151debfc3dSmrg 	  /* In simple cases we can look through PHI nodes, but we
8161debfc3dSmrg 	     have to be careful with loops and with memory references
8171debfc3dSmrg 	     containing operands that are also operands of PHI nodes.
8181debfc3dSmrg 	     See gcc.c-torture/execute/20051110-*.c.  */
8191debfc3dSmrg 	  else if (gimple_code (use_stmt) == GIMPLE_PHI)
8201debfc3dSmrg 	    {
821c0a68be4Smrg 	      /* If we already visited this PHI ignore it for further
822c0a68be4Smrg 		 processing.  */
823c0a68be4Smrg 	      if (!bitmap_bit_p (visited,
824c0a68be4Smrg 				 SSA_NAME_VERSION (PHI_RESULT (use_stmt))))
8251debfc3dSmrg 		{
826c0a68be4Smrg 		  defs.safe_push (use_stmt);
827c0a68be4Smrg 		  phi_def = use_stmt;
8281debfc3dSmrg 		}
8291debfc3dSmrg 	    }
8301debfc3dSmrg 	  /* If the statement is a use the store is not dead.  */
8311debfc3dSmrg 	  else if (ref_maybe_used_by_stmt_p (use_stmt, ref))
8321debfc3dSmrg 	    {
833a2dc1f3fSmrg 	      /* Handle common cases where we can easily build an ao_ref
834a2dc1f3fSmrg 		 structure for USE_STMT and in doing so we find that the
835a2dc1f3fSmrg 		 references hit non-live bytes and thus can be ignored.  */
836c0a68be4Smrg 	      if (byte_tracking_enabled
837c0a68be4Smrg 		  && is_gimple_assign (use_stmt))
838a2dc1f3fSmrg 		{
839a2dc1f3fSmrg 		  ao_ref use_ref;
840a2dc1f3fSmrg 		  ao_ref_init (&use_ref, gimple_assign_rhs1 (use_stmt));
841a2dc1f3fSmrg 		  if (valid_ao_ref_for_dse (&use_ref)
842a2dc1f3fSmrg 		      && use_ref.base == ref->base
843a2dc1f3fSmrg 		      && known_eq (use_ref.size, use_ref.max_size)
844a2dc1f3fSmrg 		      && !live_bytes_read (use_ref, ref, live_bytes))
845a2dc1f3fSmrg 		    {
846c0a68be4Smrg 		      /* If this is a store, remember it as we possibly
847c0a68be4Smrg 			 need to walk the defs uses.  */
848a2dc1f3fSmrg 		      if (gimple_vdef (use_stmt))
849c0a68be4Smrg 			defs.safe_push (use_stmt);
850a2dc1f3fSmrg 		      continue;
851a2dc1f3fSmrg 		    }
852a2dc1f3fSmrg 		}
853a2dc1f3fSmrg 
8541debfc3dSmrg 	      fail = true;
8551debfc3dSmrg 	      BREAK_FROM_IMM_USE_STMT (ui);
8561debfc3dSmrg 	    }
857c0a68be4Smrg 	  /* If this is a store, remember it as we possibly need to walk the
858c0a68be4Smrg 	     defs uses.  */
8591debfc3dSmrg 	  else if (gimple_vdef (use_stmt))
860c0a68be4Smrg 	    defs.safe_push (use_stmt);
8611debfc3dSmrg 	}
8621debfc3dSmrg 
8631debfc3dSmrg       if (fail)
8641debfc3dSmrg 	{
8651debfc3dSmrg 	  /* STMT might be partially dead and we may be able to reduce
8661debfc3dSmrg 	     how many memory locations it stores into.  */
8671debfc3dSmrg 	  if (byte_tracking_enabled && !gimple_clobber_p (stmt))
8681debfc3dSmrg 	    return DSE_STORE_MAYBE_PARTIAL_DEAD;
8691debfc3dSmrg 	  return DSE_STORE_LIVE;
8701debfc3dSmrg 	}
8711debfc3dSmrg 
8721debfc3dSmrg       /* If we didn't find any definition this means the store is dead
8731debfc3dSmrg          if it isn't a store to global reachable memory.  In this case
8741debfc3dSmrg 	 just pretend the stmt makes itself dead.  Otherwise fail.  */
875c0a68be4Smrg       if (defs.is_empty ())
8761debfc3dSmrg 	{
8771debfc3dSmrg 	  if (ref_may_alias_global_p (ref))
8781debfc3dSmrg 	    return DSE_STORE_LIVE;
8791debfc3dSmrg 
880c0a68be4Smrg 	  if (by_clobber_p)
881c0a68be4Smrg 	    *by_clobber_p = false;
8821debfc3dSmrg 	  return DSE_STORE_DEAD;
8831debfc3dSmrg 	}
8841debfc3dSmrg 
885c0a68be4Smrg       /* Process defs and remove those we need not process further.  */
886c0a68be4Smrg       for (unsigned i = 0; i < defs.length ();)
887c0a68be4Smrg 	{
888c0a68be4Smrg 	  gimple *def = defs[i];
889c0a68be4Smrg 	  gimple *use_stmt;
890c0a68be4Smrg 	  use_operand_p use_p;
891c0a68be4Smrg 	  /* If the path to check starts with a kill we do not need to
892c0a68be4Smrg 	     process it further.
893c0a68be4Smrg 	     ???  With byte tracking we need only kill the bytes currently
894c0a68be4Smrg 	     live.  */
895c0a68be4Smrg 	  if (stmt_kills_ref_p (def, ref))
896c0a68be4Smrg 	    {
897c0a68be4Smrg 	      if (by_clobber_p && !gimple_clobber_p (def))
898c0a68be4Smrg 		*by_clobber_p = false;
899c0a68be4Smrg 	      defs.unordered_remove (i);
900c0a68be4Smrg 	    }
901c0a68be4Smrg 	  /* In addition to kills we can remove defs whose only use
902c0a68be4Smrg 	     is another def in defs.  That can only ever be PHIs of which
903c0a68be4Smrg 	     we track a single for simplicity reasons (we fail for multiple
904c0a68be4Smrg 	     PHIs anyways).  We can also ignore defs that feed only into
905c0a68be4Smrg 	     already visited PHIs.  */
906c0a68be4Smrg 	  else if (gimple_code (def) != GIMPLE_PHI
907c0a68be4Smrg 		   && single_imm_use (gimple_vdef (def), &use_p, &use_stmt)
908c0a68be4Smrg 		   && (use_stmt == phi_def
909c0a68be4Smrg 		       || (gimple_code (use_stmt) == GIMPLE_PHI
910c0a68be4Smrg 			   && bitmap_bit_p (visited,
911c0a68be4Smrg 					    SSA_NAME_VERSION
912c0a68be4Smrg 					      (PHI_RESULT (use_stmt))))))
913c0a68be4Smrg 	    defs.unordered_remove (i);
914c0a68be4Smrg 	  else
915c0a68be4Smrg 	    ++i;
916c0a68be4Smrg 	}
917c0a68be4Smrg 
918c0a68be4Smrg       /* If all defs kill the ref we are done.  */
919c0a68be4Smrg       if (defs.is_empty ())
920c0a68be4Smrg 	return DSE_STORE_DEAD;
921c0a68be4Smrg       /* If more than one def survives fail.  */
922c0a68be4Smrg       if (defs.length () > 1)
923c0a68be4Smrg 	{
924c0a68be4Smrg 	  /* STMT might be partially dead and we may be able to reduce
925c0a68be4Smrg 	     how many memory locations it stores into.  */
926c0a68be4Smrg 	  if (byte_tracking_enabled && !gimple_clobber_p (stmt))
927c0a68be4Smrg 	    return DSE_STORE_MAYBE_PARTIAL_DEAD;
928c0a68be4Smrg 	  return DSE_STORE_LIVE;
929c0a68be4Smrg 	}
930c0a68be4Smrg       temp = defs[0];
931c0a68be4Smrg 
932c0a68be4Smrg       /* Track partial kills.  */
933c0a68be4Smrg       if (byte_tracking_enabled)
934c0a68be4Smrg 	{
935c0a68be4Smrg 	  clear_bytes_written_by (live_bytes, temp, ref);
936c0a68be4Smrg 	  if (bitmap_empty_p (live_bytes))
937c0a68be4Smrg 	    {
938c0a68be4Smrg 	      if (by_clobber_p && !gimple_clobber_p (temp))
939c0a68be4Smrg 		*by_clobber_p = false;
940c0a68be4Smrg 	      return DSE_STORE_DEAD;
941c0a68be4Smrg 	    }
942c0a68be4Smrg 	}
943c0a68be4Smrg     }
944c0a68be4Smrg   /* Continue walking until there are no more live bytes.  */
945c0a68be4Smrg   while (1);
946c0a68be4Smrg }
947c0a68be4Smrg 
9481debfc3dSmrg 
9491debfc3dSmrg class dse_dom_walker : public dom_walker
9501debfc3dSmrg {
9511debfc3dSmrg public:
dse_dom_walker(cdi_direction direction)9521debfc3dSmrg   dse_dom_walker (cdi_direction direction)
953a2dc1f3fSmrg     : dom_walker (direction),
954*8feb0f0bSmrg     m_live_bytes (param_dse_max_object_size),
955a2dc1f3fSmrg     m_byte_tracking_enabled (false) {}
9561debfc3dSmrg 
9571debfc3dSmrg   virtual edge before_dom_children (basic_block);
9581debfc3dSmrg 
9591debfc3dSmrg private:
960a2dc1f3fSmrg   auto_sbitmap m_live_bytes;
9611debfc3dSmrg   bool m_byte_tracking_enabled;
9621debfc3dSmrg   void dse_optimize_stmt (gimple_stmt_iterator *);
9631debfc3dSmrg };
9641debfc3dSmrg 
9651debfc3dSmrg /* Delete a dead call at GSI, which is mem* call of some kind.  */
9661debfc3dSmrg static void
delete_dead_or_redundant_call(gimple_stmt_iterator * gsi,const char * type)967*8feb0f0bSmrg delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
9681debfc3dSmrg {
9691debfc3dSmrg   gimple *stmt = gsi_stmt (*gsi);
9701debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
9711debfc3dSmrg     {
972*8feb0f0bSmrg       fprintf (dump_file, "  Deleted %s call: ", type);
973a2dc1f3fSmrg       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
9741debfc3dSmrg       fprintf (dump_file, "\n");
9751debfc3dSmrg     }
9761debfc3dSmrg 
9771debfc3dSmrg   tree lhs = gimple_call_lhs (stmt);
9781debfc3dSmrg   if (lhs)
9791debfc3dSmrg     {
9801debfc3dSmrg       tree ptr = gimple_call_arg (stmt, 0);
9811debfc3dSmrg       gimple *new_stmt = gimple_build_assign (lhs, ptr);
9821debfc3dSmrg       unlink_stmt_vdef (stmt);
9831debfc3dSmrg       if (gsi_replace (gsi, new_stmt, true))
9841debfc3dSmrg         bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
9851debfc3dSmrg     }
9861debfc3dSmrg   else
9871debfc3dSmrg     {
9881debfc3dSmrg       /* Then we need to fix the operand of the consuming stmt.  */
9891debfc3dSmrg       unlink_stmt_vdef (stmt);
9901debfc3dSmrg 
9911debfc3dSmrg       /* Remove the dead store.  */
9921debfc3dSmrg       if (gsi_remove (gsi, true))
9931debfc3dSmrg 	bitmap_set_bit (need_eh_cleanup, gimple_bb (stmt)->index);
9941debfc3dSmrg       release_defs (stmt);
9951debfc3dSmrg     }
9961debfc3dSmrg }
9971debfc3dSmrg 
9981debfc3dSmrg /* Delete a dead store at GSI, which is a gimple assignment. */
9991debfc3dSmrg 
1000*8feb0f0bSmrg void
delete_dead_or_redundant_assignment(gimple_stmt_iterator * gsi,const char * type,bitmap need_eh_cleanup)1001*8feb0f0bSmrg delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type,
1002*8feb0f0bSmrg 				     bitmap need_eh_cleanup)
10031debfc3dSmrg {
10041debfc3dSmrg   gimple *stmt = gsi_stmt (*gsi);
10051debfc3dSmrg   if (dump_file && (dump_flags & TDF_DETAILS))
10061debfc3dSmrg     {
1007*8feb0f0bSmrg       fprintf (dump_file, "  Deleted %s store: ", type);
1008a2dc1f3fSmrg       print_gimple_stmt (dump_file, stmt, 0, dump_flags);
10091debfc3dSmrg       fprintf (dump_file, "\n");
10101debfc3dSmrg     }
10111debfc3dSmrg 
10121debfc3dSmrg   /* Then we need to fix the operand of the consuming stmt.  */
10131debfc3dSmrg   unlink_stmt_vdef (stmt);
10141debfc3dSmrg 
10151debfc3dSmrg   /* Remove the dead store.  */
10161debfc3dSmrg   basic_block bb = gimple_bb (stmt);
1017*8feb0f0bSmrg   if (gsi_remove (gsi, true) && need_eh_cleanup)
10181debfc3dSmrg     bitmap_set_bit (need_eh_cleanup, bb->index);
10191debfc3dSmrg 
10201debfc3dSmrg   /* And release any SSA_NAMEs set in this statement back to the
10211debfc3dSmrg      SSA_NAME manager.  */
10221debfc3dSmrg   release_defs (stmt);
10231debfc3dSmrg }
10241debfc3dSmrg 
10251debfc3dSmrg /* Attempt to eliminate dead stores in the statement referenced by BSI.
10261debfc3dSmrg 
10271debfc3dSmrg    A dead store is a store into a memory location which will later be
10281debfc3dSmrg    overwritten by another store without any intervening loads.  In this
10291debfc3dSmrg    case the earlier store can be deleted.
10301debfc3dSmrg 
10311debfc3dSmrg    In our SSA + virtual operand world we use immediate uses of virtual
10321debfc3dSmrg    operands to detect dead stores.  If a store's virtual definition
10331debfc3dSmrg    is used precisely once by a later store to the same location which
10341debfc3dSmrg    post dominates the first store, then the first store is dead.  */
10351debfc3dSmrg 
10361debfc3dSmrg void
dse_optimize_stmt(gimple_stmt_iterator * gsi)10371debfc3dSmrg dse_dom_walker::dse_optimize_stmt (gimple_stmt_iterator *gsi)
10381debfc3dSmrg {
10391debfc3dSmrg   gimple *stmt = gsi_stmt (*gsi);
10401debfc3dSmrg 
10411debfc3dSmrg   /* If this statement has no virtual defs, then there is nothing
10421debfc3dSmrg      to do.  */
10431debfc3dSmrg   if (!gimple_vdef (stmt))
10441debfc3dSmrg     return;
10451debfc3dSmrg 
10461debfc3dSmrg   /* Don't return early on *this_2(D) ={v} {CLOBBER}.  */
10471debfc3dSmrg   if (gimple_has_volatile_ops (stmt)
10481debfc3dSmrg       && (!gimple_clobber_p (stmt)
10491debfc3dSmrg 	  || TREE_CODE (gimple_assign_lhs (stmt)) != MEM_REF))
10501debfc3dSmrg     return;
10511debfc3dSmrg 
10521debfc3dSmrg   ao_ref ref;
10531debfc3dSmrg   if (!initialize_ao_ref_for_dse (stmt, &ref))
10541debfc3dSmrg     return;
10551debfc3dSmrg 
10561debfc3dSmrg   /* We know we have virtual definitions.  We can handle assignments and
10571debfc3dSmrg      some builtin calls.  */
10581debfc3dSmrg   if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
10591debfc3dSmrg     {
1060*8feb0f0bSmrg       tree fndecl = gimple_call_fndecl (stmt);
1061*8feb0f0bSmrg       switch (DECL_FUNCTION_CODE (fndecl))
10621debfc3dSmrg 	{
10631debfc3dSmrg 	case BUILT_IN_MEMCPY:
10641debfc3dSmrg 	case BUILT_IN_MEMMOVE:
1065*8feb0f0bSmrg 	case BUILT_IN_STRNCPY:
10661debfc3dSmrg 	case BUILT_IN_MEMSET:
1067*8feb0f0bSmrg 	case BUILT_IN_MEMCPY_CHK:
1068*8feb0f0bSmrg 	case BUILT_IN_MEMMOVE_CHK:
1069*8feb0f0bSmrg 	case BUILT_IN_STRNCPY_CHK:
1070*8feb0f0bSmrg 	case BUILT_IN_MEMSET_CHK:
10711debfc3dSmrg 	  {
10721debfc3dSmrg 	    /* Occasionally calls with an explicit length of zero
10731debfc3dSmrg 	       show up in the IL.  It's pointless to do analysis
10741debfc3dSmrg 	       on them, they're trivially dead.  */
10751debfc3dSmrg 	    tree size = gimple_call_arg (stmt, 2);
10761debfc3dSmrg 	    if (integer_zerop (size))
10771debfc3dSmrg 	      {
1078*8feb0f0bSmrg 		delete_dead_or_redundant_call (gsi, "dead");
10791debfc3dSmrg 		return;
10801debfc3dSmrg 	      }
10811debfc3dSmrg 
1082*8feb0f0bSmrg 	    /* If this is a memset call that initializes an object
1083*8feb0f0bSmrg 	       to zero, it may be redundant with an earlier memset
1084*8feb0f0bSmrg 	       or empty CONSTRUCTOR of a larger object.  */
1085*8feb0f0bSmrg 	    if ((DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET
1086*8feb0f0bSmrg 		 || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET_CHK)
1087*8feb0f0bSmrg 		&& integer_zerop (gimple_call_arg (stmt, 1)))
1088*8feb0f0bSmrg 	      dse_optimize_redundant_stores (stmt);
1089*8feb0f0bSmrg 
10901debfc3dSmrg 	    enum dse_store_status store_status;
10911debfc3dSmrg 	    m_byte_tracking_enabled
10921debfc3dSmrg 	      = setup_live_bytes_from_ref (&ref, m_live_bytes);
1093c0a68be4Smrg 	    store_status = dse_classify_store (&ref, stmt,
10941debfc3dSmrg 					       m_byte_tracking_enabled,
10951debfc3dSmrg 					       m_live_bytes);
10961debfc3dSmrg 	    if (store_status == DSE_STORE_LIVE)
10971debfc3dSmrg 	      return;
10981debfc3dSmrg 
10991debfc3dSmrg 	    if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
11001debfc3dSmrg 	      {
11011debfc3dSmrg 		maybe_trim_memstar_call (&ref, m_live_bytes, stmt);
11021debfc3dSmrg 		return;
11031debfc3dSmrg 	      }
11041debfc3dSmrg 
11051debfc3dSmrg 	    if (store_status == DSE_STORE_DEAD)
1106*8feb0f0bSmrg 	      delete_dead_or_redundant_call (gsi, "dead");
11071debfc3dSmrg 	    return;
11081debfc3dSmrg 	  }
11091debfc3dSmrg 
1110*8feb0f0bSmrg 	case BUILT_IN_CALLOC:
1111*8feb0f0bSmrg 	  /* We already know the arguments are integer constants.  */
1112*8feb0f0bSmrg 	  dse_optimize_redundant_stores (stmt);
1113*8feb0f0bSmrg 	  return;
1114*8feb0f0bSmrg 
11151debfc3dSmrg 	default:
11161debfc3dSmrg 	  return;
11171debfc3dSmrg 	}
11181debfc3dSmrg     }
11191debfc3dSmrg 
11201debfc3dSmrg   if (is_gimple_assign (stmt))
11211debfc3dSmrg     {
1122c0a68be4Smrg       bool by_clobber_p = false;
11231debfc3dSmrg 
1124*8feb0f0bSmrg       /* Check if this statement stores zero to a memory location,
1125*8feb0f0bSmrg 	 and if there is a subsequent store of zero to the same
1126*8feb0f0bSmrg 	 memory location.  If so, remove the subsequent store.  */
1127*8feb0f0bSmrg       if (gimple_assign_single_p (stmt)
1128*8feb0f0bSmrg 	  && initializer_zerop (gimple_assign_rhs1 (stmt)))
1129*8feb0f0bSmrg 	dse_optimize_redundant_stores (stmt);
1130*8feb0f0bSmrg 
11311debfc3dSmrg       /* Self-assignments are zombies.  */
11321debfc3dSmrg       if (operand_equal_p (gimple_assign_rhs1 (stmt),
11331debfc3dSmrg 			   gimple_assign_lhs (stmt), 0))
1134c0a68be4Smrg 	;
11351debfc3dSmrg       else
11361debfc3dSmrg 	{
11371debfc3dSmrg 	  m_byte_tracking_enabled
11381debfc3dSmrg 	    = setup_live_bytes_from_ref (&ref, m_live_bytes);
11391debfc3dSmrg 	  enum dse_store_status store_status;
1140c0a68be4Smrg 	  store_status = dse_classify_store (&ref, stmt,
11411debfc3dSmrg 					     m_byte_tracking_enabled,
1142c0a68be4Smrg 					     m_live_bytes, &by_clobber_p);
11431debfc3dSmrg 	  if (store_status == DSE_STORE_LIVE)
11441debfc3dSmrg 	    return;
11451debfc3dSmrg 
11461debfc3dSmrg 	  if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD)
11471debfc3dSmrg 	    {
11481debfc3dSmrg 	      maybe_trim_partially_dead_store (&ref, m_live_bytes, stmt);
11491debfc3dSmrg 	      return;
11501debfc3dSmrg 	    }
11511debfc3dSmrg 	}
11521debfc3dSmrg 
11531debfc3dSmrg       /* Now we know that use_stmt kills the LHS of stmt.  */
11541debfc3dSmrg 
11551debfc3dSmrg       /* But only remove *this_2(D) ={v} {CLOBBER} if killed by
11561debfc3dSmrg 	 another clobber stmt.  */
11571debfc3dSmrg       if (gimple_clobber_p (stmt)
1158c0a68be4Smrg 	  && !by_clobber_p)
11591debfc3dSmrg 	return;
11601debfc3dSmrg 
1161*8feb0f0bSmrg       delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup);
11621debfc3dSmrg     }
11631debfc3dSmrg }
11641debfc3dSmrg 
11651debfc3dSmrg edge
before_dom_children(basic_block bb)11661debfc3dSmrg dse_dom_walker::before_dom_children (basic_block bb)
11671debfc3dSmrg {
11681debfc3dSmrg   gimple_stmt_iterator gsi;
11691debfc3dSmrg 
11701debfc3dSmrg   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi);)
11711debfc3dSmrg     {
11721debfc3dSmrg       dse_optimize_stmt (&gsi);
11731debfc3dSmrg       if (gsi_end_p (gsi))
11741debfc3dSmrg 	gsi = gsi_last_bb (bb);
11751debfc3dSmrg       else
11761debfc3dSmrg 	gsi_prev (&gsi);
11771debfc3dSmrg     }
11781debfc3dSmrg   return NULL;
11791debfc3dSmrg }
11801debfc3dSmrg 
11811debfc3dSmrg namespace {
11821debfc3dSmrg 
11831debfc3dSmrg const pass_data pass_data_dse =
11841debfc3dSmrg {
11851debfc3dSmrg   GIMPLE_PASS, /* type */
11861debfc3dSmrg   "dse", /* name */
11871debfc3dSmrg   OPTGROUP_NONE, /* optinfo_flags */
11881debfc3dSmrg   TV_TREE_DSE, /* tv_id */
11891debfc3dSmrg   ( PROP_cfg | PROP_ssa ), /* properties_required */
11901debfc3dSmrg   0, /* properties_provided */
11911debfc3dSmrg   0, /* properties_destroyed */
11921debfc3dSmrg   0, /* todo_flags_start */
11931debfc3dSmrg   0, /* todo_flags_finish */
11941debfc3dSmrg };
11951debfc3dSmrg 
11961debfc3dSmrg class pass_dse : public gimple_opt_pass
11971debfc3dSmrg {
11981debfc3dSmrg public:
pass_dse(gcc::context * ctxt)11991debfc3dSmrg   pass_dse (gcc::context *ctxt)
12001debfc3dSmrg     : gimple_opt_pass (pass_data_dse, ctxt)
12011debfc3dSmrg   {}
12021debfc3dSmrg 
12031debfc3dSmrg   /* opt_pass methods: */
clone()12041debfc3dSmrg   opt_pass * clone () { return new pass_dse (m_ctxt); }
gate(function *)12051debfc3dSmrg   virtual bool gate (function *) { return flag_tree_dse != 0; }
12061debfc3dSmrg   virtual unsigned int execute (function *);
12071debfc3dSmrg 
12081debfc3dSmrg }; // class pass_dse
12091debfc3dSmrg 
12101debfc3dSmrg unsigned int
execute(function * fun)12111debfc3dSmrg pass_dse::execute (function *fun)
12121debfc3dSmrg {
12131debfc3dSmrg   need_eh_cleanup = BITMAP_ALLOC (NULL);
12141debfc3dSmrg 
1215c0a68be4Smrg   renumber_gimple_stmt_uids (cfun);
12161debfc3dSmrg 
12171debfc3dSmrg   /* We might consider making this a property of each pass so that it
12181debfc3dSmrg      can be [re]computed on an as-needed basis.  Particularly since
12191debfc3dSmrg      this pass could be seen as an extension of DCE which needs post
12201debfc3dSmrg      dominators.  */
12211debfc3dSmrg   calculate_dominance_info (CDI_POST_DOMINATORS);
12221debfc3dSmrg   calculate_dominance_info (CDI_DOMINATORS);
12231debfc3dSmrg 
12241debfc3dSmrg   /* Dead store elimination is fundamentally a walk of the post-dominator
12251debfc3dSmrg      tree and a backwards walk of statements within each block.  */
12261debfc3dSmrg   dse_dom_walker (CDI_POST_DOMINATORS).walk (fun->cfg->x_exit_block_ptr);
12271debfc3dSmrg 
12281debfc3dSmrg   /* Removal of stores may make some EH edges dead.  Purge such edges from
12291debfc3dSmrg      the CFG as needed.  */
12301debfc3dSmrg   if (!bitmap_empty_p (need_eh_cleanup))
12311debfc3dSmrg     {
12321debfc3dSmrg       gimple_purge_all_dead_eh_edges (need_eh_cleanup);
12331debfc3dSmrg       cleanup_tree_cfg ();
12341debfc3dSmrg     }
12351debfc3dSmrg 
12361debfc3dSmrg   BITMAP_FREE (need_eh_cleanup);
12371debfc3dSmrg 
12381debfc3dSmrg   /* For now, just wipe the post-dominator information.  */
12391debfc3dSmrg   free_dominance_info (CDI_POST_DOMINATORS);
12401debfc3dSmrg   return 0;
12411debfc3dSmrg }
12421debfc3dSmrg 
12431debfc3dSmrg } // anon namespace
12441debfc3dSmrg 
12451debfc3dSmrg gimple_opt_pass *
make_pass_dse(gcc::context * ctxt)12461debfc3dSmrg make_pass_dse (gcc::context *ctxt)
12471debfc3dSmrg {
12481debfc3dSmrg   return new pass_dse (ctxt);
12491debfc3dSmrg }
1250