ACATS already had a test covering the Ada issue, Eric also added a test to the gnat.dg testsuite. So that's well covered.

The test for the bootstrap comparison failure was (as expected) trivial to construct (ssa-dse-29.c). The test for the ppc64 big endian failures was easy to extract from sel-sched.c (ssa-dse-2.C) What was more interesting was the scanning.

I finally decided to enhance the dumps a bit to facilitate testing. If we have a trimmable store, we now dump the trimming information. The test then verifies two things. First that we don't get a negative trim, second that the dead memmove call gets deleted.

Bootstrapped and regression tested on x86_64-linux-gnu. Installing on the trunk.

Again folks, sorry for the breakage over the weekend.

Jeff
commit b241d3db9d195bdffa4349cea077ee0e94985435
Author: law <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Mon Jan 16 23:43:05 2017 +0000

    2017-01-16  Jeff Law  <l...@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.
    
        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.
    
    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244509 
138bc75d-0d04-0410-961f-82ee72b054a4

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 265e3a5..8507528 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2017-01-16  Jeff Law  <l...@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  <ubiz...@gmail.com>
 
        * config/i386/i386.h (LIMIT_RELOAD_CLASS): Remove.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ef1fea5..09c5d52 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2017-01-16  Jeff Law  <l...@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  <ja...@redhat.com>
 
        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 0000000..d69edd2
--- /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 0000000..31529e7
--- /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 65dcb12..84c0b11 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)

Reply via email to