Patchwork Fix PR rtl-optimization/55388

login
register
mail settings
Submitter Eric Botcazou
Date Nov. 23, 2012, 3:56 p.m.
Message ID <4985237.qq2rRsS0gk@polaris>
Download mbox | patch
Permalink /patch/201360/
State New
Headers show

Comments

Eric Botcazou - Nov. 23, 2012, 3:56 p.m.
This is the recent bootstrap failure on SPARC/Linux --with-cpu=ultrasparc in 
release mode: cp/decl.c:copy_type_enum is miscompiled at -O2 after
  http://gcc.gnu.org/ml/gcc-cvs/2012-11/msg00546.html

The patch has enabled the use of MEM_EXPR for bitfields.  This was possible 
thanks to earlier changes in the bitfield handling machinery in expmed.c,
except that I forgot to change the call to adjust_address in store_bit_field 
so, when an access of size 2 is turned into an access of size 4 in there, the 
MEM_EXPR isn't dropped as expected.  Fixing this is sufficient to restore 
bootstrap, but there is a latent issue in nonoverlapping_component_refs_p 
which now needs to deal with bitfields.

Bootstrapped/regtested on SPARC and x86-64/Linux, applied on the mainline.


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.

Patch

Index: alias.c
===================================================================
--- alias.c	(revision 193720)
+++ alias.c	(working copy)
@@ -2236,11 +2236,20 @@  nonoverlapping_component_refs_p (const_r
       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: emit-rtl.c
===================================================================
--- emit-rtl.c	(revision 193720)
+++ emit-rtl.c	(working copy)
@@ -2072,6 +2072,10 @@  adjust_address_1 (rtx memref, enum machi
     = 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: expmed.c
===================================================================
--- expmed.c	(revision 193720)
+++ expmed.c	(working copy)
@@ -869,19 +869,20 @@  store_bit_field (rtx str_rtx, unsigned H
   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,