From e5fe4319e726b2b6baf4a31e42faa446eb6d00b4 Mon Sep 17 00:00:00 2001
From: Joey Ye <joey.ye@arm.com>
Date: Mon, 21 Nov 2011 02:16:12 +0000
Subject: [PATCH] expr.c (expand_expr_real_1): Correctly handle strict volatile
 bitfield loads smaller than mode size.

2011-11-20  Joey Ye  <joey.ye@arm.com>

	* expr.c (expand_expr_real_1): Correctly handle strict volatile
	bitfield loads smaller than mode size.

testsuite:

	* gcc.dg/volatile-bitfields-1.c: New.

From-SVN: r181549
---
 gcc/ChangeLog                               |  5 +++++
 gcc/expr.c                                  | 11 +++++++---
 gcc/testsuite/ChangeLog                     |  4 ++++
 gcc/testsuite/gcc.dg/volatile-bitfields-1.c | 23 +++++++++++++++++++++
 4 files changed, 40 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/volatile-bitfields-1.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6a14c5419ce4..590dba822e27 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2011-11-20  Joey Ye  <joey.ye@arm.com>
+
+	* expr.c (expand_expr_real_1): Correctly handle strict volatile
+	bitfield loads smaller than mode size.
+
 2011-11-20  Richard Henderson  <rth@redhat.com>
 
 	* config/mips/mips.c (mips_init_libfuncs): Call init_sync_libfuncs.
diff --git a/gcc/expr.c b/gcc/expr.c
index 84cfe5c23ee2..8d3a0f671a8a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -9740,11 +9740,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
 		&& modifier != EXPAND_CONST_ADDRESS
 		&& modifier != EXPAND_INITIALIZER)
 	    /* If the field is volatile, we always want an aligned
-	       access.  Only do this if the access is not already naturally
+	       access.  Do this in following two situations:
+	       1. the access is not already naturally
 	       aligned, otherwise "normal" (non-bitfield) volatile fields
-	       become non-addressable.  */
+	       become non-addressable.
+	       2. the bitsize is narrower than the access size. Need
+	       to extract bitfields from the access.  */
 	    || (volatilep && flag_strict_volatile_bitfields > 0
-		&& (bitpos % GET_MODE_ALIGNMENT (mode) != 0))
+		&& (bitpos % GET_MODE_ALIGNMENT (mode) != 0 
+		    || (mode1 != BLKmode
+		        && bitsize < GET_MODE_SIZE (mode1) * BITS_PER_UNIT)))
 	    /* If the field isn't aligned enough to fetch as a memref,
 	       fetch it as a bit field.  */
 	    || (mode1 != BLKmode
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 58a3ff0aaf68..5c1fb0077d6d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-20  Joey Ye  <joey.ye@arm.com>
+
+	* gcc.dg/volatile-bitfields-1.c: New.
+
 2011-11-20  Jason Merrill  <jason@redhat.com>
 
 	PR c++/48322
diff --git a/gcc/testsuite/gcc.dg/volatile-bitfields-1.c b/gcc/testsuite/gcc.dg/volatile-bitfields-1.c
new file mode 100644
index 000000000000..6adda27fea4c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/volatile-bitfields-1.c
@@ -0,0 +1,23 @@
+/* { dg-options "-fstrict-volatile-bitfields" } */
+/* { dg-do run } */
+
+extern int puts(const char *);
+extern void abort(void) __attribute__((noreturn));
+
+typedef struct {
+  volatile unsigned short a:8, b:8;
+} BitStruct;
+
+BitStruct bits = {1, 2};
+
+void check(int i, int j)
+{
+  if (i != 1 || j != 2) puts("FAIL"), abort();
+}
+
+int main ()
+{
+  check(bits.a, bits.b);
+
+  return 0;
+}
-- 
GitLab