https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93982

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |---

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I don't really think this is fixed.
Besides the bogus hunk mentioned above (either do it unconditionally, or not at
all, what it does isn't even a good heuristics, the pointer type on the MEM_REF
first operand really is irrelevant both for the VN reasons and for because user
can as the testcase shows use other pointer types too, I'd say the
count_nonzero_bytes function isn't well designed.
The problem is that it doesn't differentiate between whether the EXP it is
looking at are the bytes that are being stored, or is a pointer which points to
those bytes.  Each of those cases needs to be treated significantly
differently.
When not counting count_nonzero_bytes called recursively or from the other
count_nonzero_bytes, I see it called from handle_store twice, each time the
argument is the gimple_assign_rhs1 (store), i.e. either the constant that is
being stored (e.g. INTEGER_CST), or e.g. a MEM_REF and similarly in
handle_integral_assign where it is called with the MEM_REF that is being
loaded.
Now, count_nonzero_bytes starts with get_stridx (exp) call.  This makes no
sense, that doesn't give you anything related to the bytes being stored, but to
bytes pointed by exp.
Then it goes through into the ADDR_EXPR case and just uses its operand.
Now, with the PR93829 change it at least sets nbytes to something, but
shouldn't e.g. the get_stridx call be done only if nbytes is non-zero?  A clean
design would be to have separate functions, one that handles the length of the
exp bytes itself and another one that handles the case where exp points to
those bytes.  Otherwise, you just need to hope zero sized objects (such as
MEM_REFs) won't appear anywhere etc.
E.g. in
void
foo (char *p)
{
  char buf[16];
  __builtin_memcpy (buf, "abcde", 6);
  *(char **) p = &buf[0];
...
}
case get_stridx (exp) returns > 0, even when it is in any way relevant to the
store.
The native_encode_expr call should be guarded, the usual check is
CHAR_BIT == 8 && BITS_PER_UNIT == 8.
And the formatting is off, e.g. the hunk mentioned in #c3 is misindented as
whole,
          const value_range_equiv *vr
            = CONST_CAST (class vr_values *, rvals)
            ->get_value_range (si->nonzero_chars);
should have been something like:
          const value_range_equiv *vr
            = (CONST_CAST (class vr_values *, rvals)
               ->get_value_range (si->nonzero_chars));
or better
          vr_values *r = CONT_CAST (vr_values *, rvals);
          const value_range_equiv *vr = r->get_value_range (si->nonzero_chars);

Reply via email to