Commit af1ab449 by Richard Biener Committed by Richard Biener

re PR middle-end/60429 (Miscompilation (aliasing) with -finline-functions)

2014-03-11  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/60429
	PR tree-optimization/60485
	* tree-ssa-structalias.c (set_union_with_increment): Properly
	take into account all fields that overlap the shifted vars.
	(do_sd_constraint): Likewise.
	(do_ds_constraint): Likewise.
	(get_constraint_for_ptr_offset): Likewise.

	* gcc.dg/pr60485-1.c: New testcase.
	* gcc.dg/pr60485-2.c: Likewise.

From-SVN: r208479
parent 75b107f5
2014-03-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/60429
PR tree-optimization/60485
* tree-ssa-structalias.c (set_union_with_increment): Properly
take into account all fields that overlap the shifted vars.
(do_sd_constraint): Likewise.
(do_ds_constraint): Likewise.
(get_constraint_for_ptr_offset): Likewise.
2014-03-11 Chung-Lin Tang <cltang@codesourcery.com>
* config/nios2/nios2.c (machine_function): Add fp_save_offset field.
......
2014-03-11 Richard Biener <rguenther@suse.de>
PR tree-optimization/60429
PR tree-optimization/60485
* gcc.dg/pr60485-1.c: New testcase.
* gcc.dg/pr60485-2.c: Likewise.
2014-03-10 Jakub Jelinek <jakub@redhat.com>
PR ipa/60457
......
/* { dg-do run } */
/* { dg-options "-O2" } */
extern void abort (void);
struct S {
int *i[4];
int *p1;
int *p2;
int *p3;
int *p4;
};
int **b;
int main()
{
int i = 1;
struct S s;
s.p3 = &i;
int **p;
if (b)
p = b;
else
p = &s.i[2];
p += 4;
if (!b)
**p = 0;
if (i != 0)
abort ();
return i;
}
/* { dg-do run } */
/* { dg-options "-O2" } */
extern void abort (void);
struct S {
int *i[4];
int *p1;
int *p2;
int *p3;
int *p4;
int **x;
};
int **b;
int main()
{
int i = 1;
struct S s;
s.p3 = &i;
int **p;
if (b)
p = b;
else
p = &s.i[2];
p += 4;
/* prevert fowrprop from creating an offsetted sd constraint and
preserve the pointer offsetting constraint. */
s.x = p;
p = s.x;
if (!b)
{
int *z = *p;
/* z should point to i (and non-local/escaped). */
*z = 0;
}
if (i != 0)
abort ();
return i;
}
......@@ -993,23 +993,28 @@ set_union_with_increment (bitmap to, bitmap delta, HOST_WIDE_INT inc,
changed |= bitmap_set_bit (to, i);
else
{
unsigned HOST_WIDE_INT fieldoffset = vi->offset + inc;
HOST_WIDE_INT fieldoffset = vi->offset + inc;
unsigned HOST_WIDE_INT size = vi->size;
/* If the offset makes the pointer point to before the
variable use offset zero for the field lookup. */
if (inc < 0
&& fieldoffset > vi->offset)
fieldoffset = 0;
vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
changed |= bitmap_set_bit (to, vi->id);
/* If the result is not exactly at fieldoffset include the next
field as well. See get_constraint_for_ptr_offset for more
rationale. */
if (vi->offset != fieldoffset
&& vi->next != 0)
changed |= bitmap_set_bit (to, vi->next);
if (fieldoffset < 0)
vi = get_varinfo (vi->head);
else
vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
do
{
changed |= bitmap_set_bit (to, vi->id);
if (vi->is_full_var
|| vi->next == 0)
break;
/* We have to include all fields that overlap the current field
shifted by inc. */
vi = vi_next (vi);
}
while (vi->offset < fieldoffset + size);
}
}
......@@ -1618,16 +1623,21 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
{
varinfo_t v = get_varinfo (j);
HOST_WIDE_INT fieldoffset = v->offset + roffset;
unsigned HOST_WIDE_INT size = v->size;
unsigned int t;
if (v->is_full_var)
fieldoffset = v->offset;
;
else if (roffset != 0)
v = first_vi_for_offset (v, fieldoffset);
/* If the access is outside of the variable we can ignore it. */
if (!v)
continue;
{
if (fieldoffset < 0)
v = get_varinfo (v->head);
else
v = first_or_preceding_vi_for_offset (v, fieldoffset);
}
/* We have to include all fields that overlap the current field
shifted by roffset. */
do
{
t = find (v->id);
......@@ -1644,16 +1654,13 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
&& add_graph_edge (graph, lhs, t))
flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
/* If the variable is not exactly at the requested offset
we have to include the next one. */
if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
if (v->is_full_var
|| v->next == 0)
break;
v = vi_next (v);
fieldoffset = v->offset;
}
while (1);
while (v->offset < fieldoffset + size);
}
done:
......@@ -1716,15 +1723,20 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
varinfo_t v = get_varinfo (j);
unsigned int t;
HOST_WIDE_INT fieldoffset = v->offset + loff;
unsigned HOST_WIDE_INT size = v->size;
if (v->is_full_var)
fieldoffset = v->offset;
;
else if (loff != 0)
v = first_vi_for_offset (v, fieldoffset);
/* If the access is outside of the variable we can ignore it. */
if (!v)
continue;
{
if (fieldoffset < 0)
v = get_varinfo (v->head);
else
v = first_or_preceding_vi_for_offset (v, fieldoffset);
}
/* We have to include all fields that overlap the current field
shifted by loff. */
do
{
if (v->may_have_pointers)
......@@ -1750,16 +1762,13 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
bitmap_set_bit (changed, t);
}
/* If the variable is not exactly at the requested offset
we have to include the next one. */
if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
if (v->is_full_var
|| v->next == 0)
break;
v = vi_next (v);
fieldoffset = v->offset;
}
while (1);
while (v->offset < fieldoffset + size);
}
}
......@@ -3109,35 +3118,30 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
varinfo_t temp;
unsigned HOST_WIDE_INT offset = curr->offset + rhsoffset;
/* Search the sub-field which overlaps with the
pointed-to offset. If the result is outside of the variable
we have to provide a conservative result, as the variable is
still reachable from the resulting pointer (even though it
technically cannot point to anything). The last and first
sub-fields are such conservative results.
??? If we always had a sub-field for &object + 1 then
we could represent this in a more precise way. */
/* If curr->offset + rhsoffset is less than zero adjust it. */
if (rhsoffset < 0
&& curr->offset < offset)
offset = 0;
temp = first_or_preceding_vi_for_offset (curr, offset);
/* If the found variable is not exactly at the pointed to
result, we have to include the next variable in the
solution as well. Otherwise two increments by offset / 2
do not result in the same or a conservative superset
solution. */
if (temp->offset != offset
&& temp->next != 0)
/* We have to include all fields that overlap the current
field shifted by rhsoffset. And we include at least
the last or the first field of the variable to represent
reachability of off-bound addresses, in particular &object + 1,
conservatively correct. */
temp = first_or_preceding_vi_for_offset (curr, offset);
c.var = temp->id;
c.offset = 0;
temp = vi_next (temp);
while (temp
&& temp->offset < offset + curr->size)
{
struct constraint_expr c2;
c2.var = temp->next;
c2.var = temp->id;
c2.type = ADDRESSOF;
c2.offset = 0;
results->safe_push (c2);
temp = vi_next (temp);
}
c.var = temp->id;
c.offset = 0;
}
else
c.offset = rhsoffset;
......
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