[PATCH] sccvn: Fix up push_partial_def little-endian bitfield handling [PR97764]
Richard Biener
rguenther@suse.de
Tue Nov 10 10:01:28 GMT 2020
On Tue, 10 Nov 2020, Jakub Jelinek wrote:
> Hi!
>
> 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.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/10?
OK.
Thanks,
Richard.
> 2020-11-10 Jakub Jelinek <jakub@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.
>
> --- gcc/tree-ssa-sccvn.c.jj 2020-11-06 20:31:34.298252809 +0100
> +++ gcc/tree-ssa-sccvn.c 2020-11-09 14:45:00.454445644 +0100
> @@ -2039,12 +2039,12 @@ vn_walk_cb_data::push_partial_def (pd_da
> }
> else
> {
> - size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
> if (pd.offset >= 0)
> {
> /* LSB of this_buffer[0] byte should be at pd.offset bits
> in buffer. */
> unsigned int msk;
> + size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
> amnt = pd.offset % BITS_PER_UNIT;
> if (amnt)
> shift_bytes_in_array_left (this_buffer, len + 1, amnt);
> @@ -2074,6 +2074,9 @@ vn_walk_cb_data::push_partial_def (pd_da
> {
> amnt = (unsigned HOST_WIDE_INT) pd.offset % BITS_PER_UNIT;
> if (amnt)
> + size -= BITS_PER_UNIT - amnt;
> + size = MIN (size, (HOST_WIDE_INT) needed_len * BITS_PER_UNIT);
> + if (amnt)
> shift_bytes_in_array_left (this_buffer, len + 1, amnt);
> }
> memcpy (p, this_buffer + (amnt != 0), size / BITS_PER_UNIT);
> --- gcc/testsuite/gcc.c-torture/execute/pr97764.c.jj 2020-11-09 14:36:20.974258322 +0100
> +++ gcc/testsuite/gcc.c-torture/execute/pr97764.c 2020-11-09 14:36:56.108865088 +0100
> @@ -0,0 +1,14 @@
> +/* PR tree-optimization/97764 */
> +/* { dg-require-effective-target int32plus } */
> +
> +struct S { int b : 3; int c : 28; int d : 1; };
> +
> +int
> +main ()
> +{
> + struct S e = {};
> + e.c = -1;
> + if (e.d)
> + __builtin_abort ();
> + return 0;
> +}
>
> Jakub
>
>
--
Richard Biener <rguenther@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imend
More information about the Gcc-patches
mailing list