aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-structalias.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-03-11 12:42:18 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-03-11 12:42:18 +0000
commitaf1ab44914e9d544f7b24c21634e02f62ef086ff (patch)
treeaf561b689b875e166348ce17ab0dfa579443ef87 /gcc/tree-ssa-structalias.c
parent75b107f5942b75e085958c04b09dbcbf12ff68ac (diff)
downloadgcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.zip
gcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.tar.gz
gcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa-structalias.c')
-rw-r--r--gcc/tree-ssa-structalias.c110
1 files changed, 57 insertions, 53 deletions
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 402b3d1..e1e1147 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -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;