+2017-01-16 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/79090
+ PR tree-optimization/33562
+ PR tree-optimization/61912
+ PR tree-optimization/77485
+ * tree-ssa-dse.c (compute_trims): Accept STMT argument. Dump STMT
+ and computed trims into the dump file.
+
2017-01-17 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (LIMIT_RELOAD_CLASS): Remove.
+2017-01-16 Jeff Law <law@redhat.com>
+
+ PR tree-optimization/33562
+ PR tree-optimization/61912
+ PR tree-optimization/77485
+ PR tree-optimization/79090
+ * gcc.dg/tree-ssa/ssa-dse-29.c: New test.
+ * g++.dg/tree-ssa/ssa-dse-2.C: New test.
+
2017-01-16 Jakub Jelinek <jakub@redhat.com>
PR c/79089
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse2-details" } */
+
+typedef long unsigned int size_t;
+extern "C"
+{
+ extern void *memmove (void *__dest, const void *__src, size_t __n) throw ()
+ __attribute__ ((__nonnull__ (1, 2)));
+}
+extern void abort () __attribute__ ((__noreturn__));
+struct vec_prefix { unsigned m_num; };
+struct vl_embed { };
+struct vl_ptr { };
+struct va_heap { typedef vl_ptr default_layout; };
+template < typename T, typename A = va_heap, typename L = typename A::default_layout > struct vec { };
+template < typename T, typename A > struct vec < T, A, vl_embed >
+{
+ unsigned length (void) const { return m_vecpfx. m_num; }
+ bool is_empty (void) const { return m_vecpfx. m_num == 0; }
+ void block_remove (unsigned, unsigned);
+ vec_prefix m_vecpfx;
+ T m_vecdata[1];
+};
+template < typename T, typename A > inline void vec < T, A, vl_embed >::block_remove (unsigned ix, unsigned len)
+{
+ T * slot = &m_vecdata[ix];
+ m_vecpfx.m_num -= len;
+ memmove (slot, slot + len, (m_vecpfx.m_num - ix) * sizeof (T));
+}
+
+template < typename T > struct vec < T, va_heap, vl_ptr >
+{
+ bool is_empty (void) const { return m_vec ? m_vec-> is_empty () : true; }
+ unsigned length (void) const { return m_vec ? m_vec-> length () : 0; }
+ void block_remove (unsigned, unsigned);
+ vec < T, va_heap, vl_embed > * m_vec;
+};
+template < typename T > inline void vec < T, va_heap, vl_ptr >::block_remove (unsigned ix, unsigned len)
+{
+ m_vec->block_remove (ix, len);
+}
+
+typedef struct _list_node * _list_t;
+typedef struct _expr expr_def;
+typedef expr_def * expr_t;
+typedef _list_t av_set_t;
+static vec < expr_t > vec_av_set;
+bool
+fill_vec_av_set (av_set_t av)
+{
+ if (vec_av_set.length () > 0)
+ vec_av_set.block_remove (0, vec_av_set.length ());
+ ((!(vec_av_set.is_empty ())? abort () , 0 : 0));
+}
+
+/* { dg-final { scan-tree-dump-not "Trimming statement .head = -" "dse2" } } */
+/* { dg-final { scan-tree-dump "Deleted dead call: " "dse2" } } */
+
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse-details" } */
+
+struct z {
+ int a;
+ int b;
+ int c;
+};
+
+int
+foo(int cond, struct z *s)
+{
+
+ if (cond)
+ {
+ s->a = 1;
+ s->b = 2;
+ s->c = 3;
+ }
+ __builtin_memset (s, 0, sizeof (struct z));
+}
+
+/* { dg-final { scan-tree-dump-times "Deleted dead store" 3 "dse1"} } */
+/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse2"} } */
+/* { dg-final { scan-tree-dump-not "Deleted dead store" "dse3"} } */
+
tail of ORIG resulting in a bitmap that is a superset of LIVE.
Store the number of elements trimmed from the head and tail in
- TRIM_HEAD and TRIM_TAIL. */
+ TRIM_HEAD and TRIM_TAIL.
+
+ STMT is the statement being trimmed and is used for debugging dump
+ output only. */
static void
-compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail)
+compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail,
+ gimple *stmt)
{
/* We use sbitmaps biased such that ref->offset is bit zero and the bitmap
extends through ref->size. So we know that in the original bitmap
int first_orig = 0;
int first_live = bitmap_first_set_bit (live);
*trim_head = (first_live - first_orig) & ~0x1;
+
+ if ((*trim_head || *trim_tail)
+ && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, " Trimming statement (head = %d, tail = %d): ",
+ *trim_head, *trim_tail);
+ print_gimple_stmt (dump_file, stmt, dump_flags, 0);
+ fprintf (dump_file, "\n");
+ }
}
/* STMT initializes an object from COMPLEX_CST where one or more of the
maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt)
{
int trim_head, trim_tail;
- compute_trims (ref, live, &trim_head, &trim_tail);
+ compute_trims (ref, live, &trim_head, &trim_tail, stmt);
/* The amount of data trimmed from the head or tail must be at
least half the size of the object to ensure we're trimming
int head_trim = 0;
int tail_trim = 0;
- compute_trims (ref, live, &head_trim, &tail_trim);
+ compute_trims (ref, live, &head_trim, &tail_trim, stmt);
/* Now we want to replace the constructor initializer
with memset (object + head_trim, 0, size - head_trim - tail_trim). */
case BUILT_IN_MEMMOVE:
{
int head_trim, tail_trim;
- compute_trims (ref, live, &head_trim, &tail_trim);
+ compute_trims (ref, live, &head_trim, &tail_trim, stmt);
/* Tail trimming is easy, we can just reduce the count. */
if (tail_trim)
case BUILT_IN_MEMSET:
{
int head_trim, tail_trim;
- compute_trims (ref, live, &head_trim, &tail_trim);
+ compute_trims (ref, live, &head_trim, &tail_trim, stmt);
/* Tail trimming is easy, we can just reduce the count. */
if (tail_trim)