aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2017-02-28 23:39:11 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2017-02-28 23:39:11 +0100
commitad1de65225fc1ac05fe6b05b6198dc50a51e4935 (patch)
treeff4ffb92de5c47b0d5e963ed565075997888b190
parent7efb3707f267d5d47c4e0c929fa269adf32b11bc (diff)
downloadgcc-ad1de65225fc1ac05fe6b05b6198dc50a51e4935.zip
gcc-ad1de65225fc1ac05fe6b05b6198dc50a51e4935.tar.gz
gcc-ad1de65225fc1ac05fe6b05b6198dc50a51e4935.tar.bz2
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/gimple-ssa-store-merging.c47
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr79737-1.c37
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr79737-2.c41
5 files changed, 118 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 51cb8ab..dc29c09 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,12 @@
+2017-02-28 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <ebotcazou@adacore.com>
PR target/79749
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index c59fdcb..17ac94a 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 4aab63a..483e903 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-02-28 Jakub Jelinek <jakub@redhat.com>
+
+ 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 <ebotcazou@adacore.com>
* 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 0000000..05e392c
--- /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 0000000..37b991e
--- /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 ();
+}