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

--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>:

https://gcc.gnu.org/g:c69325a5db450dbac198f76f1162734af05a1061

commit r11-4867-gc69325a5db450dbac198f76f1162734af05a1061
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Tue Nov 10 11:17:46 2020 +0100

    sccvn: Fix up push_partial_def little-endian bitfield handling [PR97764]

    This patch fixes a thinko in the left-endian push_partial_def path.
    As the testcase shows, we have 3 bitfields in the struct,
    bitoff  bitsize
    0       3
    3       28
    31      1
    the corresponding read is the byte at offset 3 (i.e. 24 bits)
    and push_partial_def first handles the full store ({}) to all bits
    and then is processing the store to the middle bitfield with value of -1.
    Here are the interesting spots:
      pd.offset -= offseti;
    this adjusts the pd to { -21, 28 }, the (for little-endian lowest) 21
    bits aren't interesting to us, we only care about the upper 7.
              len = native_encode_expr (pd.rhs, this_buffer, bufsize,
                                        MAX (0, -pd.offset) / BITS_PER_UNIT);
    native_encode_expr has the offset parameter in bytes and we tell it
    that we aren't interested in the first (lowest) two bytes of the number.
    It encodes 0xff, 0xff with len == 2 then.
          HOST_WIDE_INT size = pd.size;
          if (pd.offset < 0)
            size -= ROUND_DOWN (-pd.offset, BITS_PER_UNIT);
    we get 28 - 16, i.e. 12 - the 16 is subtracting those 2 bytes that we
    omitted in native_encode_expr.
              size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
    needed_len is how many bytes the read at most needs, and that is 1,
    so we get size 8 and copy all 8 bits (i.e. a single byte plus nothing)
    from the native_encode_expr filled this_buffer; this incorrectly sets
    the byte to 0xff when we want 0x7f.  The above line is correct for the
    pd.offset >= 0 case when we don't skip anything, but for the pd.offset < 0
    case we need to subtract also the remainder of the bits we aren't
interested
    in (the code shifts the bytes by that number of bits).
    If it weren't for the big-endian path, we could as well do
          if (pd.offset < 0)
            size += pd.offset;
    but the big-endian path needs it differently.
    With the following patch, amnt is 3 and we subtract from 12 the (8 - 3)
    bits and thus get the 7 which is the value we want.

    2020-11-10  Jakub Jelinek  <ja...@redhat.com>

            PR tree-optimization/97764
            * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): For
            little-endian stores with negative pd.offset, subtract
            BITS_PER_UNIT - amnt from size if amnt is non-zero.

            * gcc.c-torture/execute/pr97764.c: New test.

Reply via email to