This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR64822: incorrect folding of bitfield in union on big endian targets
- From: "Thomas Preud'homme" <thomas dot preudhomme at arm dot com>
- To: <gcc-patches at gcc dot gnu dot org>, "Richard Biener" <richard dot guenther at gmail dot com>
- Cc: "Jiong Wang" <Jiong dot Wang at arm dot com>
- Date: Thu, 29 Jan 2015 18:27:36 +0800
- Subject: [PATCH] Fix PR64822: incorrect folding of bitfield in union on big endian targets
- Authentication-results: sourceware.org; auth=none
Hi,
Incorrect folding happen when a bitfield in a union is accessed and the union was initialized via another field. This is a reminiscence of GCC32RM-325 due to sccvn not passing the right size to fold_ctor_reference. sccvn uses TYPE_SIZE which gives the size of the container integer for a bitfield instead of TYPE_PRECISION that gives the actual size occupied by the bitfield. This patch fixes that and modify bitfld-6 so that it catch this issue in addition to the old one.
ChangeLog entries are as follows:
*** gcc/ChangeLog ***
2015-01-28 Thomas Preud'homme <thomas.preudhomme@arm.com>
* tree-ssa-sccvn.c (fully_constant_vn_reference_p): Use TYPE_PRECISION
to compute size of referenced value in the constant case.
*** gcc/testsuite/ChangeLog ***
2015-01-28 Thomas Preud'homme <thomas.preudhomme@arm.com>
* gcc.c-torture/execute/bitfld-6.c: Use 24 bits for bitfield b. Adapt
expected values accordingly.
diff --git a/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c b/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c
index 50927dc..e9a61df 100644
--- a/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c
+++ b/gcc/testsuite/gcc.c-torture/execute/bitfld-6.c
@@ -1,7 +1,7 @@
union U
{
const int a;
- unsigned b : 20;
+ unsigned b : 24;
};
static union U u = { 0x12345678 };
@@ -14,9 +14,9 @@ main (void)
{
#ifdef __BYTE_ORDER__
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- return u.b - 0x45678;
+ return u.b - 0x345678;
#else
- return u.b - 0x12345;
+ return u.b - 0x123456;
#endif
#endif
return 0;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 25c67d0..0f1299a 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1352,7 +1352,7 @@ fully_constant_vn_reference_p (vn_reference_t ref)
|| TYPE_PRECISION (ref->type) % BITS_PER_UNIT == 0))
{
HOST_WIDE_INT off = 0;
- HOST_WIDE_INT size = tree_to_shwi (TYPE_SIZE (ref->type));
+ HOST_WIDE_INT size = TYPE_PRECISION (ref->type);
if (size % BITS_PER_UNIT != 0
|| size > MAX_BITSIZE_MODE_ANY_MODE)
return NULL_TREE;
Tested by doing a native x86_64 bootstrap + testsuite run and building a arm-none-eabi cross-compiler + testsuite run (on QEMU, compiling for Cortex-M3) without any regression.
Is this ok for trunk?
Best regards,
Thomas