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

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
That case is for the
  if (idx > 0)
    {
      si = get_strinfo (idx);
...
    }
block in there, and si != NULL && si->length != NULL_TREE && TREE_CODE
(si->length) == INTEGER_CST is what you are looking for (together with
gimple_assign_rhs1 (stmt) being non-zero INTEGER_CST.  You'd just verify that
si->length is bigger than 0 and if so, set si->dont_invalidate = true;

But the thing is that unless it is p[0] = 'X'; store, the si in that case is
say for p + 6 address rather than p + 1, so while it would keep strlen (&p[6])
valid, it would happily invalidate strlen (&p[1]) or strlen (p).  So, you need
to mark not to invalidate also the related string lengths if any.  This could
be done
say by adjust_related_strinfos (loc, si, size_zero_node); or
more efficiently by just:
strinfo si2 = verify_related_strinfos (si);
while (si2)
  {
    strinfo nsi = si2;
    si2->dont_invalidate = true;
    if (si2->next == 0)
      break;
    nsi = get_strinfo (si2->next);
    if (nsi == NULL
        || nsi->first != si2->first
        || nsi->prev != si->idx)
      return;
    si2 = nsi;
  }
or so - the store in this case shouldn't overwrite a zero byte (otherwise
length would be unknown or zero), so it doesn't need to invalidate any of the
related cached string lengths.  verify_related_strinfos and the extra
verification similar to what e.g. adjust_related_strinfos does is there because
of the lazy updation, when walking the chains one has to verify some chain
element hasn't been invalidated since the chain has been created.
*->dont_invalidate is the only kind of store into strinfo structure that is
valid even without unshare_strinfo, it is just a hint for the next
maybe_invalidate.

Reply via email to