Commit b4934671 by Alexandre Oliva Committed by Alexandre Oliva

[PR69123] fix handling of MEMs in VTA to avoid dataflow oscillation

The problem arises because we used to drop overwritten MEMs from loc
lists of VALUEs, but not of other onepart variables, and it just so
happens that, by doing so, block 6 in the testcase has no D#5 in its
output in the first pass, because the MEM holding its (previous) value
was correctly dropped from value 88:88, but gains it in the second
pass because D#5 has the MEM location incoming directly in its loc
list, rather than indirectly in a VALUE.

This incorrect binding enables other blocks to believe they have a
tentative binding for D#5 in some cycles, but others, still operating
on the early conclusion, believe there isn't, and they oscillate from
that.

Since we check for escaping MEMs in clobbers, we won't lose anything
relevant by dropping call-clobbered or overwritten MEMs in all onepart
variables, and this ensures the loc intersection operation in onepart
vars won't let a MEM through that wasn't present in earlier
iterations.

for  gcc/ChangeLog

	PR bootstrap/69123
	* var-tracking.c (drop_overlapping_mem_locs): Operate on all
	onepart vars.  Fix typo in comment.  Fix reversed condition in
	unshare test.
	(dataflow_set_remove_mem_locs): Operate on all onepart vars.

for gcc/testsuite/ChangeLog

	PR bootstrap/69123
	* g++.dg/pr69123.C: New.

From-SVN: r232218
parent 4708731c
2016-01-11 Alexandre Oliva <aoliva@redhat.com> 2016-01-11 Alexandre Oliva <aoliva@redhat.com>
PR bootstrap/69123 PR bootstrap/69123
* var-tracking.c (drop_overlapping_mem_locs): Operate on all
onepart vars. Fix typo in comment. Fix reversed condition in
unshare test.
(dataflow_set_remove_mem_locs): Operate on all onepart vars.
PR bootstrap/69123
* var-tracking.c (dump_onepart_variable_differences): New. * var-tracking.c (dump_onepart_variable_differences): New.
(dataflow_set_different): If a detailed dump is requested, (dataflow_set_different): If a detailed dump is requested,
delay early returns and dump differences between onepart delay early returns and dump differences between onepart
......
2016-01-11 Alexandre Oliva <aoliva@redhat.com>
PR bootstrap/69123
* g++.dg/pr69123.C: New.
2016-01-11 Ilya Enkovich <enkovich.gnu@gmail.com> 2016-01-11 Ilya Enkovich <enkovich.gnu@gmail.com>
PR target/69010 PR target/69010
......
/* { dg-do compile } */
/* { dg-options "-O3 -g" } */
/* This was reduced from gcc/tree-vect-slp.c by H.J.Lu. */
struct xxx_def;
typedef xxx_def *xxx;
union rtxxx
{
const char *rt_str;
xxx rt_xxx;
};
struct xxx_def {
union u {
rtxxx fld[1];
} u;
};
extern xxx bar (void);
extern int foo1 (xxx);
static inline xxx
foo2 (xxx arg0, xxx arg1)
{
xxx rt;
rt = bar ();
(((rt)->u.fld[0]).rt_xxx) = arg0;
(((rt)->u.fld[1]).rt_xxx) = arg1;
return rt;
}
static inline xxx
foo4 (const char *arg0 )
{
xxx rt;
rt = bar ();
(((rt)->u.fld[0]).rt_str) = arg0;
(((rt)->u.fld[1]).rt_xxx) = (xxx) 0;
return rt;
}
extern xxx foo5 (long);
struct address_cost_data
{
unsigned costs[2][2][2][2];
};
void
get_address_cost (address_cost_data *data)
{
unsigned acost;
long i;
long rat, off = 0;
unsigned sym_p, var_p, off_p, rat_p;
xxx addr, base;
xxx reg0, reg1;
reg1 = bar ();
addr = foo2 (reg1, (xxx) 0);
rat = 1;
acost = 0;
reg0 = bar ();
reg1 = bar ();
for (i = 0; i < 16; i++)
{
sym_p = i & 1;
var_p = (i >> 1) & 1;
off_p = (i >> 2) & 1;
rat_p = (i >> 3) & 1;
addr = reg0;
if (rat_p)
addr = foo2 (addr, foo5 (rat)) ;
if (var_p)
addr = foo2 (addr, reg1);
if (sym_p)
base = foo4 ("");
else if (off_p)
base = foo5 (off);
else
base = (xxx) 0;
if (base)
addr = foo2 (addr, base);
acost = foo1 (addr);
data->costs[sym_p][var_p][off_p][rat_p] = acost;
}
}
...@@ -2224,7 +2224,7 @@ struct overlapping_mems ...@@ -2224,7 +2224,7 @@ struct overlapping_mems
}; };
/* Remove all MEMs that overlap with COMS->LOC from the location list /* Remove all MEMs that overlap with COMS->LOC from the location list
of a hash table entry for a value. COMS->ADDR must be a of a hash table entry for a onepart variable. COMS->ADDR must be a
canonicalized form of COMS->LOC's address, and COMS->LOC must be canonicalized form of COMS->LOC's address, and COMS->LOC must be
canonicalized itself. */ canonicalized itself. */
...@@ -2235,7 +2235,7 @@ drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms) ...@@ -2235,7 +2235,7 @@ drop_overlapping_mem_locs (variable **slot, overlapping_mems *coms)
rtx mloc = coms->loc, addr = coms->addr; rtx mloc = coms->loc, addr = coms->addr;
variable *var = *slot; variable *var = *slot;
if (var->onepart == ONEPART_VALUE) if (var->onepart != NOT_ONEPART)
{ {
location_chain *loc, **locp; location_chain *loc, **locp;
bool changed = false; bool changed = false;
...@@ -4682,11 +4682,11 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set) ...@@ -4682,11 +4682,11 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
{ {
for (loc = var->var_part[0].loc_chain; loc; loc = loc->next) for (loc = var->var_part[0].loc_chain; loc; loc = loc->next)
{ {
/* We want to remove dying MEMs that doesn't refer to DECL. */ /* We want to remove dying MEMs that don't refer to DECL. */
if (GET_CODE (loc->loc) == MEM if (GET_CODE (loc->loc) == MEM
&& (MEM_EXPR (loc->loc) != decl && (MEM_EXPR (loc->loc) != decl
|| INT_MEM_OFFSET (loc->loc) != 0) || INT_MEM_OFFSET (loc->loc) != 0)
&& !mem_dies_at_call (loc->loc)) && mem_dies_at_call (loc->loc))
break; break;
/* We want to move here MEMs that do refer to DECL. */ /* We want to move here MEMs that do refer to DECL. */
else if (GET_CODE (loc->loc) == VALUE else if (GET_CODE (loc->loc) == VALUE
...@@ -4769,14 +4769,14 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set) ...@@ -4769,14 +4769,14 @@ dataflow_set_preserve_mem_locs (variable **slot, dataflow_set *set)
} }
/* Remove all MEMs from the location list of a hash table entry for a /* Remove all MEMs from the location list of a hash table entry for a
value. */ onepart variable. */
int int
dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set) dataflow_set_remove_mem_locs (variable **slot, dataflow_set *set)
{ {
variable *var = *slot; variable *var = *slot;
if (var->onepart == ONEPART_VALUE) if (var->onepart != NOT_ONEPART)
{ {
location_chain *loc, **locp; location_chain *loc, **locp;
bool changed = false; bool changed = false;
......
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