------- Comment #30 from rguenth at gcc dot gnu dot org 2007-06-05 09:27 ------- See this testcase (reduced from spec2k6 dealII by Micha):
struct I { int ix; struct II { int j,i; void *ptr; } ii; };// inner; struct O : public I { // int x; int y; }; static int geti (struct O *o) { return o->ii.i; } extern void init(struct O*); extern void deinit(struct O*); extern int getcond(void); struct O::I *getinner (struct O*); int reset (int cond) { struct O cell; struct O *o; struct I::II *in; int *pi; o = &cell; init (o); in = &o->ii; while (getcond()) { if (o->y) cell.ii.i = -2; if (!getcond()) { in->i = -1; in->j = o->ii.i; break; } } pi = &in->j; pi++; deinit(&cell); return *pi; } and note how we compute the wrong points-to solution for in: o_3 = { cell cell.y cell.ptr cell.i cell.j } in_4 = { cell.y cell.ptr cell.j } we are missing cell.i in the points-to set. This is because with looking simply for vars with oldoffset + offset is appearantly not enough here. cell + 64 -> cell.j cell.y + 64 -> off structure cell.ptr + 64 -> cell.y cell.i + 64 -> cell.ptr (actually in the middle of it) cell.j + 64 -> cell.ptr so, there is nothing in the structure that, if added 64, will point to cell.i. But of course we are taking the address of the substructure and so we are indeed pointing to cell.i. So a different solution would be to add _each_ var starting with the first one + offset. Which would be simply "reversing" the logic like I did with the patch (it needs some fixing still, as pruning at the end is bogus in it as vars may be still reached from others). The thing that fixes this (30252) bug is that with the original patch we keep the parent var in the solution. With something like Index: tree-ssa-structalias.c =================================================================== --- tree-ssa-structalias.c (revision 125310) +++ tree-ssa-structalias.c (working copy) @@ -708,6 +708,21 @@ solution_set_add (bitmap set, unsigned H bitmap result = BITMAP_ALLOC (&iteration_obstack); unsigned int i; bitmap_iterator bi; + unsigned HOST_WIDE_INT min = -1, max = 0; + + /* Compute set of vars we can reach from set + offset. */ + + EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) + { + if (get_varinfo (i)->offset + offset < min) + min = get_varinfo (i)->offset + offset; + if (get_varinfo (i)->offset + get_varinfo (i)->size + offset > max) + { + max = get_varinfo (i)->offset + get_varinfo (i)->size + offset; + if (max > get_varinfo (i)->fullsize) + max = get_varinfo (i)->fullsize; + } + } EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi) { @@ -715,13 +730,10 @@ solution_set_add (bitmap set, unsigned H less than end. Otherwise, it is globbed to a single variable. */ - if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize) + if (get_varinfo (i)->offset >= min + && get_varinfo (i)->offset < max) { - unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset; - varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset); - if (!v) - continue; - bitmap_set_bit (result, v->id); + bitmap_set_bit (result, i); } else if (get_varinfo (i)->is_artificial_var || get_varinfo (i)->has_union we don't retain it and this bug is not fixed, but the SPEC bug should be. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30252