From: Jeff Law Date: Mon, 16 Jan 2017 23:43:05 +0000 (-0700) Subject: re PR tree-optimization/79090 (DSE wrongly removes store at variable offset) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=a59afbe2fecf938caff8462378acc0506ea4ff5c;p=gcc.git re PR tree-optimization/79090 (DSE wrongly removes store at variable offset) 2017-01-16 Jeff Law 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. 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. From-SVN: r244509 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 265e3a55a8a..850752829e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-01-16 Jeff Law + + 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 * config/i386/i386.h (LIMIT_RELOAD_CLASS): Remove. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ef1fea51a87..09c5d52aa4b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2017-01-16 Jeff Law + + 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 PR c/79089 diff --git a/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C b/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C new file mode 100644 index 00000000000..d69edd2dedc --- /dev/null +++ b/gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C @@ -0,0 +1,59 @@ +/* { 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" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c new file mode 100644 index 00000000000..31529e7caed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c @@ -0,0 +1,26 @@ +/* { 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"} } */ + diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 65dcb12d8b0..84c0b11f53b 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -212,10 +212,14 @@ setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes) 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 @@ -231,6 +235,15 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail) 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 @@ -244,7 +257,7 @@ static void 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 @@ -296,7 +309,7 @@ maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt) 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). */ @@ -384,7 +397,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt) 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) @@ -405,7 +418,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt) 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)