http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48764

Richard Guenther <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |ASSIGNED
      Known to work|                            |4.4.4, 4.6.0
           Keywords|                            |wrong-code
   Last reconfirmed|                            |2011.04.26 10:43:12
     Ever Confirmed|0                           |1
            Summary|wrong-code bug in           |[4.5/4.6/4.7 Regression]
                   |gcc-4.5.x, related to       |wrong-code bug in
                   |__restrict                  |gcc-4.5.x, related to
                   |                            |__restrict
   Target Milestone|---                         |4.5.4
      Known to fail|                            |4.5.2

--- Comment #1 from Richard Guenther <rguenth at gcc dot gnu.org> 2011-04-26 
10:43:12 UTC ---
The bug is that we somehow think after inlining

void FooBar::load(Loader&) (struct FooBar * const this, struct Loader & l)
{
...
<bb 2>:
  D.3062_2 = &this_1(D)->c1;
  D.3079_9 = &l_3(D)->buffer;
  this_11 = (struct Buffer * const restrict) D.3079_9;
  D.3083_12 = this_11->p;
  memcpy (D.3062_2, D.3083_12, 1);
  D.3083_13 = this_11->p;
  D.3082_14 = D.3083_13 + 1;
  this_11->p = D.3082_14;
  D.3063_4 = &this_1(D)->c2;
  D.3064_5 = &l_3(D)->D.2415;
  self_15 = (struct Loader &) D.3064_5;
  D.3087_16 = &self_15->buffer;
  this_17 = (struct Buffer * const restrict) D.3087_16;
  D.3091_18 = this_17->p;
  memcpy (D.3063_4, D.3091_18, 1);
  D.3091_19 = this_17->p;
  D.3090_20 = D.3091_19 + 1;
  this_17->p = D.3090_20;
  return;

this_11 and this_17 only point to (different) objects.  The restrict
machinery should be robust against inlining effects because it should
inherhit the arguments points-to set as well.  In this case we have

l_3(D), points-to non-local, points-to vars: { }
self_15, points-to non-local, points-to vars: { }

though, and we explicitly ignore those:

  /* If both pointers are restrict-qualified try to disambiguate
     with restrict information.  */
  if (TYPE_RESTRICT (TREE_TYPE (ptr1))
      && TYPE_RESTRICT (TREE_TYPE (ptr2))
      && !pt_solutions_same_restrict_base (&pi1->pt, &pi2->pt))
    return false;


/* Return true if both points-to solutions PT1 and PT2 for two restrict
   qualified pointers are possibly based on the same pointer.  */

bool
pt_solutions_same_restrict_base (struct pt_solution *pt1,
                                 struct pt_solution *pt2)
{
  /* If we deal with points-to solutions of two restrict qualified
     pointers solely rely on the pointed-to variable bitmap intersection.
     For two pointers that are based on each other the bitmaps will
     intersect.  */
  if (pt1->vars_contains_restrict
      && pt2->vars_contains_restrict)
    {
      gcc_assert (pt1->vars && pt2->vars);
      return bitmap_intersect_p (pt1->vars, pt2->vars);
    }

  return true;
}

because all incoming restrict qualified pointers also point to NONLOCAL
(so restrict would be useless if we don't ignore that fact).

4.4 handles restrict in a completely different way.

4.6 and 4.7 manage to make more must-aliasing appearant which avoids
this issue to manifest in a miscompilation, but the issue itself is
latent.

Reply via email to