This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Your change to function.c
- To: "David S. Miller" <davem at dm dot cobaltmicro dot com>, law at cygnus dot com
- Subject: Re: Your change to function.c
- From: Richard Henderson <rth at cygnus dot com>
- Date: Tue, 6 Oct 1998 00:48:04 -0700
- Cc: rth at cygnus dot com, mark at markmitchell dot com, egcs-patches at cygnus dot com
- References: <5352.907599255@hurl.cygnus.com> <199810060512.WAA09623@dm.cobaltmicro.com>
- Reply-To: Richard Henderson <rth at cygnus dot com>
On Mon, Oct 05, 1998 at 10:12:44PM -0700, David S. Miller wrote:
> Look at what purge_addressof_1 looks at when this is compiled. It
> look at something resembling:
>
> (insn 18 15 19 (set (reg:QI 110)
> (mem:QI (addressof:SI (reg:SF 108) 107) 0)) -1 (nil)
> (nil))
>
> And this is the source of the problem cases on big endian.
This is a red herring, since if big-endian were really the issue,
you'd have the same problem with (reg:SI 108).
Oddly, and much more significantly, is that when I'd looked at
some of these things on the Alpha, I saw that a wrapping
(subreg:SI (reg:SF) 0)
had been added for me, and so assumed the bit operations knew
how to handle all of this. Seems I was wrong.
Consider the following. Note that I'll still want to do a check
in purge_addressof_1 to make sure we're not XFmode or some nonsense
like that. Note that the abort for pun == BLKmode could be
changed to allocate a bit of stack.
Assuming you've no problems with this scheme in general, I'll
clean up those loose ends.
r~
* expmed.c (store_bit_field): Pun non-integral storage modes.
(extract_bit_field): Likewise.
Index: expmed.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expmed.c,v
retrieving revision 1.20
diff -c -p -d -r1.20 expmed.c
*** expmed.c 1998/09/23 16:24:09 1.20
--- expmed.c 1998/10/06 07:30:53
*************** store_bit_field (str_rtx, bitsize, bitnu
*** 261,266 ****
--- 261,295 ----
op0 = SUBREG_REG (op0);
}
+ switch (GET_MODE_CLASS (GET_MODE (op0)))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ {
+ enum machine_mode pun;
+ pun = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op0)), MODE_INT, 0);
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, pun, NULL_RTX);
+ else if (pun != BLKmode)
+ op0 = gen_lowpart (pun, op0);
+ else
+ abort ();
+ break;
+ }
+
+ case MODE_RANDOM:
+ if (GET_MODE (op0) == BLKmode)
+ break;
+ case MODE_CC:
+ default:
+ abort();
+ }
+
/* If OP0 is a register, BITPOS must count within a word.
But as we have it, it counts within whatever size OP0 now has.
On a bigendian machine, these are not the same, so convert. */
*************** extract_bit_field (str_rtx, bitsize, bit
*** 955,960 ****
--- 984,1018 ----
op0 = SUBREG_REG (op0);
}
+ switch (GET_MODE_CLASS (GET_MODE (op0)))
+ {
+ case MODE_INT:
+ case MODE_PARTIAL_INT:
+ break;
+
+ case MODE_COMPLEX_INT:
+ case MODE_COMPLEX_FLOAT:
+ case MODE_FLOAT:
+ {
+ enum machine_mode pun;
+ pun = mode_for_size (GET_MODE_BITSIZE (GET_MODE (op0)), MODE_INT, 0);
+ if (GET_CODE (op0) == MEM)
+ op0 = change_address (op0, pun, NULL_RTX);
+ else if (pun != BLKmode)
+ op0 = gen_lowpart (pun, op0);
+ else
+ abort ();
+ break;
+ }
+
+ case MODE_RANDOM:
+ if (GET_MODE (op0) == BLKmode)
+ break;
+ case MODE_CC:
+ default:
+ abort();
+ }
+
/* ??? We currently assume TARGET is at least as big as BITSIZE.
If that's wrong, the solution is to test for it and set TARGET to 0
if needed. */
*************** extract_bit_field (str_rtx, bitsize, bit
*** 973,979 ****
So too extracting a subword value in
the least significant part of the register. */
! if (((GET_CODE (op0) == REG
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op0))))
|| (GET_CODE (op0) == MEM
--- 1031,1037 ----
So too extracting a subword value in
the least significant part of the register. */
! if (((GET_CODE (op0) != MEM
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
GET_MODE_BITSIZE (GET_MODE (op0))))
|| (GET_CODE (op0) == MEM
*************** extract_bit_field (str_rtx, bitsize, bit
*** 996,1002 ****
if (mode1 != GET_MODE (op0))
{
! if (GET_CODE (op0) == REG)
op0 = gen_rtx_SUBREG (mode1, op0, offset);
else
op0 = change_address (op0, mode1,
--- 1054,1060 ----
if (mode1 != GET_MODE (op0))
{
! if (GET_CODE (op0) != MEM)
op0 = gen_rtx_SUBREG (mode1, op0, offset);
else
op0 = change_address (op0, mode1,
*************** extract_bit_field (str_rtx, bitsize, bit
*** 1088,1099 ****
/* OFFSET is the number of words or bytes (UNIT says which)
from STR_RTX to the first word or byte containing part of the field. */
! if (GET_CODE (op0) == REG)
{
if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
! op0 = gen_rtx_SUBREG (TYPE_MODE (type_for_size (BITS_PER_WORD, 0)),
! op0, offset);
offset = 0;
}
else
--- 1146,1157 ----
/* OFFSET is the number of words or bytes (UNIT says which)
from STR_RTX to the first word or byte containing part of the field. */
! if (GET_CODE (op0) != MEM)
{
if (offset != 0
|| GET_MODE_SIZE (GET_MODE (op0)) > UNITS_PER_WORD)
! op0 = gen_rtx_SUBREG (mode_for_size (BITS_PER_WORD, MODE_INT, 0),
! op0, offset);
offset = 0;
}
else