Dale Johannesen <[EMAIL PROTECTED]> writes:
> The test of f->b comes out as
>
> testl $1048512, 73(%eax)
>
> This is wrong, because 4 bytes starting at 73 goes outside the
> original object and can
> cause a page fault. The change from referencing a word at offset 72
> to offset 73
> happens in make_extraction in combine, and I propose to fix it thus:
>
>
> Index: combine.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/combine.c,v
> retrieving revision 1.502
> diff -u -b -c -3 -p -r1.502 combine.c
> cvs diff: conflicting specifications of output style
> *** combine.c 8 Aug 2005 18:30:09 -0000 1.502
> --- combine.c 25 Aug 2005 17:57:21 -0000
> *************** make_extraction (enum machine_mode mode,
> *** 6484,6491 ****
> && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode))
> offset -= GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (inner_mode);
>
> ! /* If this is a constant position, we can move to the desired byte.
> */
> ! if (pos_rtx == 0)
> {
> offset += pos / BITS_PER_UNIT;
> pos %= GET_MODE_BITSIZE (wanted_inner_mode);
> --- 6484,6493 ----
> && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode))
> offset -= GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (inner_mode);
>
> ! /* If this is a constant position, we can move to the desired byte.
> ! This is unsafe for memory objects; it might result in accesses
> ! outside the original object. */
> ! if (pos_rtx == 0 && !MEM_P (inner))
> {
> offset += pos / BITS_PER_UNIT;
> pos %= GET_MODE_BITSIZE (wanted_inner_mode);
>
>
> Still testing, but I'm a bit concerned this is overkill. Are there
> targets/situations where
> this transformation is useful or even necessary? Comments?
This optimization is going to be desirable when testing a byte value,
especially on a target which can test a byte but not a long, like the
m68k.
However, it's odd that we are doing this when we are extracting a
value that is larger than a byte. And the code looks wrong if the
conditional is true--I would have thought that both offset and pos
should use BITS_PER_UNIT, or both should use GET_MODE_BITSIZE
(wanted_inner_mode).
I think something like this might be more reasonable:
if (pos_rtx == 0)
{
enum machine_mode bfmode = smallest_mode_for_size (len, MODE_INT);
offset += pos / GET_MODE_BITSIZE (bfmode);
pos %= GET_MODE_BITSIZE (bfmode);
}
Ian