From ee88e690a27cfbe3cbb2216e50dec455754bc9a2 Mon Sep 17 00:00:00 2001 From: Eric Botcazou Date: Fri, 23 Nov 2012 16:00:26 +0000 Subject: [PATCH] re PR rtl-optimization/55388 (ICE in int_mode_for_mode at stor-layout.c:423) PR rtl-optimization/55388 * alias.c (nonoverlapping_component_refs_p): Handle bitfields. * emit-rtl.c (adjust_address_1): Deal with VOIDmode early. * expmed.c (store_bit_field): Turn the call to adjust_address into a call to adjust_bitfield_address_size. From-SVN: r193760 --- gcc/ChangeLog | 8 ++++++++ gcc/alias.c | 19 ++++++++++++++----- gcc/emit-rtl.c | 4 ++++ gcc/expmed.c | 5 +++-- 4 files changed, 29 insertions(+), 7 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 283abe0764c..b1a9d32a3e0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2012-11-23 Eric Botcazou + + PR rtl-optimization/55388 + * alias.c (nonoverlapping_component_refs_p): Handle bitfields. + * emit-rtl.c (adjust_address_1): Deal with VOIDmode early. + * expmed.c (store_bit_field): Turn the call to adjust_address + into a call to adjust_bitfield_address_size. + 2012-11-23 Vladimir Makarov * lra.c (lra): Move init_reg_info and expand_reg_info calls before diff --git a/gcc/alias.c b/gcc/alias.c index 2ef13cc755b..21daa5fdb4f 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -2236,11 +2236,20 @@ nonoverlapping_component_refs_p (const_rtx rtlx, const_rtx rtly) return false; found: - /* If we're left with accessing different fields of a structure, - then no overlap. */ - if (TREE_CODE (typex) == RECORD_TYPE - && fieldx != fieldy) - return true; + /* If we're left with accessing different fields of a structure, then no + possible overlap, unless they are both true bitfields, i.e. bitfields + for which the size isn't a multiple of the (memory) unit. */ + if (TREE_CODE (typex) == RECORD_TYPE && fieldx != fieldy) + { + if (!DECL_BIT_FIELD (fieldx) || !DECL_BIT_FIELD (fieldy)) + return true; + + if ((tree_low_cst (DECL_SIZE (fieldx), 1) % BITS_PER_UNIT) == 0 + || (tree_low_cst (DECL_SIZE (fieldy), 1) % BITS_PER_UNIT) == 0) + return true; + + return false; + } /* The comparison on the current field failed. If we're accessing a very nested structure, look at the next outer level. */ diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 27464dab09e..836ff2f5025 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -2072,6 +2072,10 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset, = targetm.addr_space.pointer_mode (attrs.addrspace); #endif + /* VOIDmode means no mode change for change_address_1. */ + if (mode == VOIDmode) + mode = GET_MODE (memref); + /* Take the size of non-BLKmode accesses from the mode. */ defattrs = mode_mem_attrs[(int) mode]; if (defattrs->size_known_p) diff --git a/gcc/expmed.c b/gcc/expmed.c index 11f15507247..fc29ac41d72 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -869,19 +869,20 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, if (MEM_P (str_rtx) && bitregion_start > 0) { enum machine_mode bestmode; - unsigned HOST_WIDE_INT offset; + HOST_WIDE_INT offset, size; gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0); offset = bitregion_start / BITS_PER_UNIT; bitnum -= bitregion_start; + size = (bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT; bitregion_end -= bitregion_start; bitregion_start = 0; bestmode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, MEM_ALIGN (str_rtx), VOIDmode, MEM_VOLATILE_P (str_rtx)); - str_rtx = adjust_address (str_rtx, bestmode, offset); + str_rtx = adjust_bitfield_address_size (str_rtx, bestmode, offset, size); } if (!store_bit_field_1 (str_rtx, bitsize, bitnum,