This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] fold-const: Don't access bit fields with too big mode (PR71310)
- From: Segher Boessenkool <segher at kernel dot crashing dot org>
- To: gcc-patches at gcc dot gnu dot org
- Cc: rguenther at suse dot de, anton at samba dot org, Segher Boessenkool <segher at kernel dot crashing dot org>
- Date: Fri, 10 Jun 2016 18:48:02 +0000
- Subject: [PATCH] fold-const: Don't access bit fields with too big mode (PR71310)
- Authentication-results: sourceware.org; auth=none
Currently, optimize_bit_field_compare reads the bitfield in word_mode
if it can. If the bit field is normally accessed in a smaller mode,
this might be a violation of the memory model, although the "extra"
part of the read is not used. But also, previous stores to the bit
field will have been done in the smaller mode, and then bigger loads
from it cause a LHS problem.
Bootstrapped and regchecked on powerpc64-linux. Is this okay for
trunk?
Segher
2016-06-10 Segher Boessenkool <segher@kernel.crashing.org>
PR middle-end/71310
* fold-const.c (optimize_bit_field_compare): Don't try to use
word_mode unconditionally for reading the bit field, look at
DECL_BIT_FIELD_REPRESENTATIVE instead.
---
gcc/fold-const.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5058746..f067001 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -3903,13 +3903,24 @@ optimize_bit_field_compare (location_t loc, enum tree_code code,
return 0;
}
+ /* Don't use a larger mode for reading the bit field than we will
+ use in other places accessing the bit field. */
+ machine_mode largest_mode = word_mode;
+ if (TREE_CODE (lhs) == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (lhs, 1);
+ tree repr = DECL_BIT_FIELD_REPRESENTATIVE (field);
+ if (repr)
+ largest_mode = DECL_MODE (repr);
+ }
+
/* See if we can find a mode to refer to this field. We should be able to,
but fail if we can't. */
nmode = get_best_mode (lbitsize, lbitpos, 0, 0,
const_p ? TYPE_ALIGN (TREE_TYPE (linner))
: MIN (TYPE_ALIGN (TREE_TYPE (linner)),
TYPE_ALIGN (TREE_TYPE (rinner))),
- word_mode, false);
+ largest_mode, false);
if (nmode == VOIDmode)
return 0;
--
1.9.3