Commit a59afbe2 by Jeff Law Committed by Jeff Law

re PR tree-optimization/79090 (DSE wrongly removes store at variable offset)

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
parent af995bf0
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> 2017-01-17 Uros Bizjak <ubizjak@gmail.com>
* config/i386/i386.h (LIMIT_RELOAD_CLASS): Remove. * 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> 2017-01-16 Jakub Jelinek <jakub@redhat.com>
PR c/79089 PR c/79089
......
/* { 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" } } */
/* { 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"} } */
...@@ -212,10 +212,14 @@ setup_live_bytes_from_ref (ao_ref *ref, sbitmap live_bytes) ...@@ -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. 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 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 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 /* 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 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) ...@@ -231,6 +235,15 @@ compute_trims (ao_ref *ref, sbitmap live, int *trim_head, int *trim_tail)
int first_orig = 0; int first_orig = 0;
int first_live = bitmap_first_set_bit (live); int first_live = bitmap_first_set_bit (live);
*trim_head = (first_live - first_orig) & ~0x1; *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 /* STMT initializes an object from COMPLEX_CST where one or more of the
...@@ -244,7 +257,7 @@ static void ...@@ -244,7 +257,7 @@ static void
maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt) maybe_trim_complex_store (ao_ref *ref, sbitmap live, gimple *stmt)
{ {
int trim_head, trim_tail; 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 /* 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 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) ...@@ -296,7 +309,7 @@ maybe_trim_constructor_store (ao_ref *ref, sbitmap live, gimple *stmt)
int head_trim = 0; int head_trim = 0;
int tail_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 /* Now we want to replace the constructor initializer
with memset (object + head_trim, 0, size - head_trim - tail_trim). */ 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) ...@@ -384,7 +397,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
case BUILT_IN_MEMMOVE: case BUILT_IN_MEMMOVE:
{ {
int head_trim, tail_trim; 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. */ /* Tail trimming is easy, we can just reduce the count. */
if (tail_trim) if (tail_trim)
...@@ -405,7 +418,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt) ...@@ -405,7 +418,7 @@ maybe_trim_memstar_call (ao_ref *ref, sbitmap live, gimple *stmt)
case BUILT_IN_MEMSET: case BUILT_IN_MEMSET:
{ {
int head_trim, tail_trim; 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. */ /* Tail trimming is easy, we can just reduce the count. */
if (tail_trim) if (tail_trim)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment