i960 and -mstrict-align
Andrew Haley
aph@cambridge.redhat.com
Tue Jul 3 12:44:00 GMT 2001
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));
More information about the Gcc-patches
mailing list