diff mbox

Add tests for recent dse bugs

Message ID 30008220-61a1-4db3-b5fa-de8b2a1ae605@redhat.com
State New
Headers show

Commit Message

Jeff Law Jan. 16, 2017, 11:44 p.m. UTC
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  <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.
    
    	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

Comments

Christophe Lyon Jan. 17, 2017, 10:06 a.m. UTC | #1
Hi Jeff,


On 17 January 2017 at 00:44, Jeff Law <law@redhat.com> wrote:
>
>
> 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  <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.
>
>         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  <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.
> 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  <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.
> +

The new ssa-dse-2.C test fails on arm because:
warning: declaration of 'void* memmove(void*, const void*, size_t)'
conflicts with built-in declaration 'void* memmove(void*, const void*,
unsigned int)' [-Wbuiltin-declaration-mismatch]

Christophe

>  2017-01-16  Jakub Jelinek  <jakub@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)
>
diff mbox

Patch

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  <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.
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  <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
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)