re PR tree-optimization/79090 (DSE wrongly removes store at variable offset)
authorJeff Law <law@redhat.com>
Mon, 16 Jan 2017 23:43:05 +0000 (16:43 -0700)
committerJeff Law <law@gcc.gnu.org>
Mon, 16 Jan 2017 23:43:05 +0000 (16:43 -0700)
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.

From-SVN: r244509

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/ssa-dse-2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-29.c [new file with mode: 0644]
gcc/tree-ssa-dse.c

index 265e3a55a8a40f6b29551ce9dd7ea73fb393b5bb..850752829e61baaa757d9c9a7d022b34bc6a6a07 100644 (file)
@@ -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.
index ef1fea51a877f1e040ee549f1437cbc40fca8b5d..09c5d52aa4bf1ec33a7426cc67ef8454415a3e9d 100644 (file)
@@ -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 (file)
index 0000000..d69edd2
--- /dev/null
@@ -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 (file)
index 0000000..31529e7
--- /dev/null
@@ -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"} } */
+
index 65dcb12d8b0c1a415c1b8ad7deb074700cda2e6f..84c0b11f53b87340194ff59d664028d856a94a38 100644 (file)
@@ -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)