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]

store_bit_field vs aligned memory


Given a structure like

	struct f { short a; short b; int c; };
	extern struct f f;

We were emitting a store to f.b via insv (an arbitrary bitfield
insertion) instead of via movhi.  This loses information about
the known alignment of `f'; some of which might be recoverable
via REGNO_POINTER_ALIGN, but why throw it away in the first place?

Getting this wrong on a target that knows how to synthesize unaligned
memory references results in mindbogglingly sub-optimial code.

It looks like the old code intended to turn naturally aligned
memory references into direct stores, but just got the logic wrong.
Interestingly, it looks like it's been wrong for a long time,
but I don't remember seeing this kind of gross output before...

Tested on alphaev4.


r~


        * expmed.c (store_bit_field): Consider naturally aligned
        memory for direct reference.

Index: expmed.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/expmed.c,v
retrieving revision 1.63
diff -c -p -d -r1.63 expmed.c
*** expmed.c	2000/08/12 22:45:05	1.63
--- expmed.c	2000/09/15 11:05:11
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 297,315 ****
    if (flag_force_mem)
      value = force_not_mem (value);
  
!   if ((GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
!        || (GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode)
! 	   && GET_MODE_SIZE (fieldmode) != 0))
!       && (GET_CODE (op0) != MEM
! 	  || ! SLOW_UNALIGNED_ACCESS (fieldmode, align)
! 	  || (offset * BITS_PER_UNIT % bitsize == 0
! 	      && align % GET_MODE_BITSIZE (fieldmode) == 0))
!       && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0)
!       && bitsize == GET_MODE_BITSIZE (fieldmode))
      {
-       /* Storing in a full-word or multi-word field in a register
- 	 can be done with just SUBREG.  Also, storing in the entire object
- 	 can be done with just SUBREG.  */
        if (GET_MODE (op0) != fieldmode)
  	{
  	  if (GET_CODE (op0) == SUBREG)
--- 297,318 ----
    if (flag_force_mem)
      value = force_not_mem (value);
  
!   /* If the target is a register, overwriting the entire object, or storing
!      a full-word or multi-word field can be done with just a SUBREG.
! 
!      If the target is memory, storing any naturally aligned field can be
!      done with a simple store.  For targets that support fast unaligned
!      memory, any naturally sized, unit aligned field can be done directly.  */
!      
!   if (bitsize == GET_MODE_BITSIZE (fieldmode)
!       && (GET_MODE_SIZE (fieldmode) >= UNITS_PER_WORD
! 	  || GET_MODE_SIZE (GET_MODE (op0)) == GET_MODE_SIZE (fieldmode)
! 	  || (GET_CODE (op0) == MEM
! 	      && (! SLOW_UNALIGNED_ACCESS (fieldmode, align)
! 		  || (offset * BITS_PER_UNIT % bitsize == 0
! 		      && align % GET_MODE_BITSIZE (fieldmode) == 0))))
!       && (BYTES_BIG_ENDIAN ? bitpos + bitsize == unit : bitpos == 0))
      {
        if (GET_MODE (op0) != fieldmode)
  	{
  	  if (GET_CODE (op0) == SUBREG)

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