------- 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

Reply via email to