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