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]

i960 and -mstrict-align


On an i960, if I have a structure like this:

struct Foo 
{
   char someBit  : 1;
   char unused_m : 7;
};

it has sizeof==1 and alignof==1.  So far, so good.

However, if I compile with -mno-strict-align, accesses to the fields
are via word accesses, so this example:

void testIt(struct Foo *p, int state)
{
   p->someBit = state;

does

        ld      (g0),g4    <-- word load.
        and     g1,1,g1
        andnot  1,g4,g4
        or      g1,g4,g4
        st      g4,(g0)    <-- word store.

This is going to break if the Foo is at the end of a page, or if it's
adjacent to some other memory owned by another thread, or whatever.

However, if I compile with -mstrict-align, everything is fine:

	ldob	(g0),g4
	ldconst	254,g5
	and	g4,g5,g4
	and	g1,1,g1
	or	g4,g1,g4
	stob	g4,(g0)

Now for the question: why on earth is gcc doing this?

It all seems to be begin at this line in store_fixed_bit_field ():

  if (! SLOW_UNALIGNED_ACCESS (word_mode, struct_align))
    struct_align = BIGGEST_ALIGNMENT;
    
If store_fixed_bit_field () is called with a mem:QI source operand, we
call get_best_mode() with align==BIGGEST_ALIGNMENT.  If
SLOW_BYTE_ACCESS is defined, get_best_mode() searches for a mode
that's as wide as possible, but smaller or equal than BITS_PER_WORD.
And it returns SImode.

Note that this is only true if the source operand is a MEM: if it's a
REG we use the mode of the destination and everything is fine.

AFAICS this will only be triggered with SLOW_BYTE_ACCESS and
!SLOW_UNALIGNED_ACCESS.

A question: is it ever legal to store into a MEM with a mode bigger
than that MEM?

Andrew.

2001-07-03  Andrew Haley  <aph@cambridge.redhat.com>

	* expmed.c (store_fixed_bit_field): Don't use a mode bigger than
	the mode of the memory location.

Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.80
diff -p -2 -c -r1.80 expmed.c
*** expmed.c	2001/05/22 07:40:25	1.80
--- expmed.c	2001/07/03 19:32:38
*************** store_fixed_bit_field (op0, offset, bits
*** 677,684 ****
        /* Get the proper mode to use for this field.  We want a mode that
  	 includes the entire field.  If such a mode would be larger than
! 	 a word, we won't be doing the extraction the normal way.  */
  
        mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
! 			    struct_align, word_mode,
  			    GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
  
--- 677,689 ----
        /* Get the proper mode to use for this field.  We want a mode that
  	 includes the entire field.  If such a mode would be larger than
! 	 a word, we won't be doing the extraction the normal way.  
! 	 We don't want a mode bigger than the destination.  */
  
+       mode = GET_MODE (op0);
        mode = get_best_mode (bitsize, bitpos + offset * BITS_PER_UNIT,
! 			    struct_align, 
! 			    (GET_MODE_BITSIZE (mode) 
! 			     < GET_MODE_BITSIZE (word_mode)
! 			     ? mode : word_mode),
  			    GET_CODE (op0) == MEM && MEM_VOLATILE_P (op0));
  


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