This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Patch to fix unaligned access in float->union assignment


This patch fixes an unaligned access at -O1 when storing an
SFmode MEM into a DImode union.  It seemed to be caused by this
change to store_bit_field:

*************** store_bit_field (str_rtx, bitsize, bitnu
*** 519,530 ****
       corresponding size.  This can occur on a machine with 64 bit registers
       that uses SFmode for float.  This can also occur for unaligned float
       structure fields.  */
!   if (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT)
!     {
!       if (GET_CODE (value) != REG)
!       value = copy_to_reg (value);
!       value = gen_rtx_SUBREG (word_mode, value, 0);
!     }
  
    /* Now OFFSET is nonzero only if OP0 is memory
       and is therefore always measured in bytes.  */
--- 524,532 ----
       corresponding size.  This can occur on a machine with 64 bit registers
       that uses SFmode for float.  This can also occur for unaligned float
       structure fields.  */
!   if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
!       && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
!     value = gen_lowpart (word_mode, value);
  
    /* Now OFFSET is nonzero only if OP0 is memory
       and is therefore always measured in bytes.  */

which was made to handle CONCATs.  The function used to force
the MEM into a register and then access it using a paradoxical
DImode subreg.  Now it adjusts the MEM to DImode instead.

Is it OK to reinstate the copy_to_reg() for MEMs, or is
the bug elsewhere?

Tested on sh64-elf, no regressions.  Fixes the attached test case.

Richard


	* expmed.c (store_bit_field): Move memory values into registers
	before obtaining their word_mode lowpart.

Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.125
diff -c -d -p -F^[(a-zA-Z0-9_^#] -r1.125 expmed.c
*** expmed.c	31 Oct 2002 20:43:07 -0000	1.125
--- expmed.c	15 Nov 2002 16:20:24 -0000
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 535,541 ****
       structure fields.  */
    if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
        && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
!     value = gen_lowpart (word_mode, value);
  
    /* Now OFFSET is nonzero only if OP0 is memory
       and is therefore always measured in bytes.  */
--- 535,545 ----
       structure fields.  */
    if (GET_MODE_CLASS (GET_MODE (value)) != MODE_INT
        && GET_MODE_CLASS (GET_MODE (value)) != MODE_PARTIAL_INT)
!     {
!       if (GET_CODE (value) == MEM)
! 	value = copy_to_reg (value);
!       value = gen_lowpart (word_mode, value);
!     }
  
    /* Now OFFSET is nonzero only if OP0 is memory
       and is therefore always measured in bytes.  */
*** /dev/null	Tue Nov 14 21:44:43 2000
--- testsuite/gcc.c-torture/execute/20021112-1.c	Fri Nov 15 16:19:38 2002
***************
*** 0 ****
--- 1,18 ----
+ union u { float f; double d; };
+ float f[2] = { 1.0f, 2.0f };
+ 
+ union u foo (float *pf)
+ {
+   union u u;
+   u.f = *pf;
+   return u;
+ }
+ 
+ int main ()
+ {
+   if (foo (&f[0]).f != 1.0f)
+     abort ();
+   if (foo (&f[1]).f != 2.0f)
+     abort ();
+   exit (0);
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]