diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/expr.c | 2 | ||||
-rw-r--r-- | gcc/expr.h | 4 | ||||
-rw-r--r-- | gcc/fold-const.c | 17 |
4 files changed, 22 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0077b8..40e60a3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ 2016-06-14 Richard Biener <rguenther@suse.de> + PR middle-end/71310 + PR bootstrap/71510 + * expr.h (get_bit_range): Declare. + * expr.c (get_bit_range): Export. + * fold-const.c (optimize_bit_field_compare): Use get_bit_range and + word_mode again to constrain the bitfield access. + +2016-06-14 Richard Biener <rguenther@suse.de> + PR tree-optimization/71521 * tree-vrp.c (extract_range_from_binary_expr_1): Guard division int_const_binop against zero divisor. @@ -4795,7 +4795,7 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, If the access does not need to be restricted, 0 is returned in both *BITSTART and *BITEND. */ -static void +void get_bit_range (unsigned HOST_WIDE_INT *bitstart, unsigned HOST_WIDE_INT *bitend, tree exp, @@ -242,6 +242,10 @@ extern rtx push_block (rtx, int, int); extern bool emit_push_insn (rtx, machine_mode, tree, rtx, unsigned int, int, rtx, int, rtx, rtx, int, rtx, bool); +/* Extract the accessible bit-range from a COMPONENT_REF. */ +extern void get_bit_range (unsigned HOST_WIDE_INT *, unsigned HOST_WIDE_INT *, + tree, HOST_WIDE_INT *, tree *); + /* Expand an assignment that stores the value of FROM into TO. */ extern void expand_assignment (tree, tree, bool); diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 26c1435..3b9500d 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3902,24 +3902,23 @@ 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; + /* Honor the C++ memory model and mimic what RTL expansion does. */ + unsigned HOST_WIDE_INT bitstart = 0; + unsigned HOST_WIDE_INT bitend = 0; 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); + get_bit_range (&bitstart, &bitend, lhs, &lbitpos, &offset); + if (offset != NULL_TREE) + return 0; } /* 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, + nmode = get_best_mode (lbitsize, lbitpos, bitstart, bitend, const_p ? TYPE_ALIGN (TREE_TYPE (linner)) : MIN (TYPE_ALIGN (TREE_TYPE (linner)), TYPE_ALIGN (TREE_TYPE (rinner))), - largest_mode, false); + word_mode, false); if (nmode == VOIDmode) return 0; |