diff options
author | Richard Biener <rguenther@suse.de> | 2014-03-11 12:42:18 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2014-03-11 12:42:18 +0000 |
commit | af1ab44914e9d544f7b24c21634e02f62ef086ff (patch) | |
tree | af561b689b875e166348ce17ab0dfa579443ef87 /gcc/tree-ssa-structalias.c | |
parent | 75b107f5942b75e085958c04b09dbcbf12ff68ac (diff) | |
download | gcc-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.c | 110 |
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; |