From: Jakub Jelinek Date: Tue, 28 Feb 2017 22:39:11 +0000 (+0100) Subject: re PR tree-optimization/79737 (wrong code at -O2 and -O3 on x86_64-linux-gnu (in... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ad1de65225fc1ac05fe6b05b6198dc50a51e4935;p=gcc.git re PR tree-optimization/79737 (wrong code at -O2 and -O3 on x86_64-linux-gnu (in both 32-bit and 64-bit modes)) PR tree-optimization/79737 * gimple-ssa-store-merging.c (encode_tree_to_bitpos): If bitlen is a multiple of BITS_PER_UNIT and !BYTES_BIG_ENDIAN, clear tmpbuf[byte_size - 1]. Call natice_encode_expr with byte_size - 1 instead of byte_size. Formatting fix. (shift_bytes_in_array_right): Formatting fix. * gcc.c-torture/execute/pr79737-1.c: New test. * gcc.c-torture/execute/pr79737-2.c: New test. From-SVN: r245795 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 51cb8abc1d2..dc29c09fd90 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2017-02-28 Jakub Jelinek + + PR tree-optimization/79737 + * gimple-ssa-store-merging.c (encode_tree_to_bitpos): If bitlen is + a multiple of BITS_PER_UNIT and !BYTES_BIG_ENDIAN, clear + tmpbuf[byte_size - 1]. Call natice_encode_expr with byte_size - 1 + instead of byte_size. Formatting fix. + (shift_bytes_in_array_right): Formatting fix. + 2017-02-28 Eric Botcazou PR target/79749 diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c index c59fdcbdf38..17ac94ab2a7 100644 --- a/gcc/gimple-ssa-store-merging.c +++ b/gcc/gimple-ssa-store-merging.c @@ -253,9 +253,9 @@ shift_bytes_in_array_right (unsigned char *ptr, unsigned int sz, unsigned prev_carry_over = carry_over; carry_over = ptr[i] & carry_mask; - carry_over <<= (unsigned char) BITS_PER_UNIT - amnt; - ptr[i] >>= amnt; - ptr[i] |= prev_carry_over; + carry_over <<= (unsigned char) BITS_PER_UNIT - amnt; + ptr[i] >>= amnt; + ptr[i] |= prev_carry_over; } } @@ -352,8 +352,9 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos, { unsigned int first_byte = bitpos / BITS_PER_UNIT; tree tmp_int = expr; - bool sub_byte_op_p = (bitlen % BITS_PER_UNIT) || (bitpos % BITS_PER_UNIT) - || mode_for_size (bitlen, MODE_INT, 0) == BLKmode; + bool sub_byte_op_p = ((bitlen % BITS_PER_UNIT) + || (bitpos % BITS_PER_UNIT) + || mode_for_size (bitlen, MODE_INT, 0) == BLKmode); if (!sub_byte_op_p) return (native_encode_expr (tmp_int, ptr + first_byte, total_bytes, 0) @@ -407,7 +408,7 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos, memset (tmpbuf, '\0', byte_size); /* The store detection code should only have allowed constants that are accepted by native_encode_expr. */ - if (native_encode_expr (expr, tmpbuf, byte_size, 0) == 0) + if (native_encode_expr (expr, tmpbuf, byte_size - 1, 0) == 0) gcc_unreachable (); /* The native_encode_expr machinery uses TYPE_MODE to determine how many @@ -418,25 +419,27 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos, contain a sign bit due to sign-extension). */ unsigned int padding = byte_size - ROUND_UP (bitlen, BITS_PER_UNIT) / BITS_PER_UNIT - 1; - if (padding != 0 - || bitlen % BITS_PER_UNIT != 0) + /* On big-endian the padding is at the 'front' so just skip the initial + bytes. */ + if (BYTES_BIG_ENDIAN) + tmpbuf += padding; + + byte_size -= padding; + + if (bitlen % BITS_PER_UNIT != 0) { - /* On big-endian the padding is at the 'front' so just skip the initial - bytes. */ if (BYTES_BIG_ENDIAN) - tmpbuf += padding; - - byte_size -= padding; - if (bitlen % BITS_PER_UNIT != 0) - { - if (BYTES_BIG_ENDIAN) - clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1, - BITS_PER_UNIT - (bitlen % BITS_PER_UNIT)); - else - clear_bit_region (tmpbuf, bitlen, - byte_size * BITS_PER_UNIT - bitlen); - } + clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1, + BITS_PER_UNIT - (bitlen % BITS_PER_UNIT)); + else + clear_bit_region (tmpbuf, bitlen, + byte_size * BITS_PER_UNIT - bitlen); } + /* Left shifting relies on the last byte being clear if bitlen is + a multiple of BITS_PER_UNIT, which might not be clear if + there are padding bytes. */ + else if (!BYTES_BIG_ENDIAN) + tmpbuf[byte_size - 1] = '\0'; /* Clear the bit region in PTR where the bits from TMPBUF will be inserted into. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4aab63a4e5d..483e9030905 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2017-02-28 Jakub Jelinek + + PR tree-optimization/79737 + * gcc.c-torture/execute/pr79737-1.c: New test. + * gcc.c-torture/execute/pr79737-2.c: New test. + 2017-02-28 Eric Botcazou * gcc.target/sparc/20170228-1.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79737-1.c b/gcc/testsuite/gcc.c-torture/execute/pr79737-1.c new file mode 100644 index 00000000000..05e392c116d --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr79737-1.c @@ -0,0 +1,37 @@ +/* PR tree-optimization/79737 */ + +#pragma pack(1) +struct S +{ + int b:18; + int c:1; + int d:24; + int e:15; + int f:14; +} i; +int g, j, k; +static struct S h; + +void +foo () +{ + for (j = 0; j < 6; j++) + k = 0; + for (; k < 3; k++) + { + struct S m = { 5, 0, -5, 9, 5 }; + h = m; + if (g) + i = m; + h.e = 0; + } +} + +int +main () +{ + foo (); + if (h.e != 0) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr79737-2.c b/gcc/testsuite/gcc.c-torture/execute/pr79737-2.c new file mode 100644 index 00000000000..37b991e1505 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr79737-2.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/79737 */ + +#pragma pack(1) +struct S +{ + int b:18; + int c:1; + int d:24; + int e:15; + int f:14; +} i, j; + +void +foo () +{ + i.e = 0; + i.b = 5; + i.c = 0; + i.d = -5; + i.f = 5; +} + +void +bar () +{ + j.b = 5; + j.c = 0; + j.d = -5; + j.e = 0; + j.f = 5; +} + +int +main () +{ + foo (); + bar (); + asm volatile ("" : : : "memory"); + if (i.b != j.b || i.c != j.c || i.d != j.d || i.e != j.e || i.f != j.f) + __builtin_abort (); +}