re PR rtl-optimization/55388 (ICE in int_mode_for_mode at stor-layout.c:423)
authorEric Botcazou <ebotcazou@adacore.com>
Fri, 23 Nov 2012 16:00:26 +0000 (16:00 +0000)
committerEric Botcazou <ebotcazou@gcc.gnu.org>
Fri, 23 Nov 2012 16:00:26 +0000 (16:00 +0000)
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
gcc/alias.c
gcc/emit-rtl.c
gcc/expmed.c

index 283abe0764c94007f54ba4e2bf9037786b1903de..b1a9d32a3e02f2359cb55a947c38735ce6f5c788 100644 (file)
@@ -1,3 +1,11 @@
+2012-11-23  Eric Botcazou  <ebotcazou@adacore.com>
+
+       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  <vmakarov@redhat.com>
 
        * lra.c (lra): Move init_reg_info and expand_reg_info calls before
index 2ef13cc755b05dbc4c8d49fd6f9591634d4ffebe..21daa5fdb4f2520f96009fb4a59181d03311c46f 100644 (file)
@@ -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.  */
index 27464dab09e0a4dafaaace5d6c6fc3c170b3e5c6..836ff2f50256e03482936af54ebec225e6d0c7dc 100644 (file)
@@ -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)
index 11f15507247cbafde919acc9fe13ad1b08422e8e..fc29ac41d72998d31ef76dab6439bb07e0ae0347 100644 (file)
@@ -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,