This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: RFC: subreg fixing (extract_bit_field or simplify_subreg)
- From: Aldy Hernandez <aldyh at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>, gcc at gcc dot gnu dot org, dje at watson dot ibm dot com
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Wed, 3 Nov 2004 18:25:14 -0400
- Subject: Re: RFC: subreg fixing (extract_bit_field or simplify_subreg)
- References: <20041028175321.GA1438@redhat.com> <20041028180357.GA22513@redhat.com> <20041029002252.GC6118@redhat.com> <20041029041000.GA23787@redhat.com> <20041030002209.GA7005@redhat.com> <20041101175711.GA6264@redhat.com>
On Mon, Nov 01, 2004 at 09:57:11AM -0800, Richard Henderson wrote:
> On Fri, Oct 29, 2004 at 08:22:09PM -0400, Aldy Hernandez wrote:
> > extract_bit_field should be smart enough to do the above magic into a DI,
> > then copy it into the target (DF).
>
> Yes.
Wooo aaah!
This is what I whipped up. It is untested, except on my few testcases.
I wanted to get your input first.
I also fixed convert_move to handle the stupid cases. I was getting
tired of making subregs by hand for obvious cases.
I added a note/question regarding the clobber, which I believe is unecessary,
as I don't see flow deleting my subreg moves. Was this clobber to kludge
over some old flow inability, or did I miss something?
Anywhoo... all pretty obvious. Fixes my problem. No longer creates
invalid subregs.
Aldy
* expr.c (convert_move): Handle mixed float mode moves.
* expmed.c (extract_bit_field): Do not create invalid subregs of
floats.
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.737
diff -c -p -r1.737 expr.c
*** expr.c 28 Oct 2004 03:53:31 -0000 1.737
--- expr.c 3 Nov 2004 22:20:25 -0000
*************** init_expr (void)
*** 317,322 ****
--- 317,326 ----
/* Copy data from FROM to TO, where the machine modes are not the same.
Both modes may be integer, or both may be floating.
+
+ If one mode is an integer and another is a floating point, both
+ must be the same size.
+
UNSIGNEDP should be nonzero if FROM is an unsigned type.
This causes zero-extension instead of sign-extension. */
*************** convert_move (rtx to, rtx from, int unsi
*** 334,341 ****
enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
: (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
!
! gcc_assert (to_real == from_real);
/* If the source and destination are already the same, then there's
nothing to do. */
--- 338,349 ----
enum rtx_code equiv_code = (unsignedp < 0 ? UNKNOWN
: (unsignedp ? ZERO_EXTEND : SIGN_EXTEND));
! if (to_real != from_real)
! {
! gcc_assert (GET_MODE_SIZE (to_mode) == GET_MODE_SIZE (from_mode));
! emit_move_insn (to, gen_rtx_SUBREG (to_mode, from, 0));
! return;
! }
/* If the source and destination are already the same, then there's
nothing to do. */
Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.200
diff -c -p -r1.200 expmed.c
*** expmed.c 21 Oct 2004 10:51:00 -0000 1.200
--- expmed.c 3 Nov 2004 22:20:28 -0000
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1267,1279 ****
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
if (target == 0 || !REG_P (target))
target = gen_reg_rtx (mode);
! /* Indicate for flow that the entire target reg is being set. */
emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
for (i = 0; i < nwords; i++)
{
/* If I is 0, use the low-order word in both field and target;
--- 1267,1292 ----
unsigned int nwords = (bitsize + (BITS_PER_WORD - 1)) / BITS_PER_WORD;
unsigned int i;
+ rtx new_target;
if (target == 0 || !REG_P (target))
target = gen_reg_rtx (mode);
! /* Indicate to flow that the entire target reg is being set. */
emit_insn (gen_rtx_CLOBBER (VOIDmode, target));
+ /* Make sure we do all word manipulations on an integer, thus
+ avoiding creating invalid subregs of floats. */
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ new_target = gen_reg_rtx (int_mode_for_mode (mode));
+ /* ?? Isn't flow smart enough to see that we use the entire
+ register without handholding? I don't think this clobber
+ (or the one above) is needed any longer. */
+ emit_insn (gen_rtx_CLOBBER (VOIDmode, new_target));
+ }
+ else
+ new_target = target;
for (i = 0; i < nwords; i++)
{
/* If I is 0, use the low-order word in both field and target;
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1288,1294 ****
? MAX (0, ((int) bitsize - ((int) i + 1)
* (int) BITS_PER_WORD))
: (int) i * BITS_PER_WORD);
! rtx target_part = operand_subword (target, wordnum, 1, VOIDmode);
rtx result_part
= extract_bit_field (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
--- 1301,1307 ----
? MAX (0, ((int) bitsize - ((int) i + 1)
* (int) BITS_PER_WORD))
: (int) i * BITS_PER_WORD);
! rtx target_part = operand_subword (new_target, wordnum, 1, VOIDmode);
rtx result_part
= extract_bit_field (op0, MIN (BITS_PER_WORD,
bitsize - i * BITS_PER_WORD),
*************** extract_bit_field (rtx str_rtx, unsigned
*** 1300,1305 ****
--- 1313,1320 ----
if (result_part != target_part)
emit_move_insn (target_part, result_part);
}
+ if (new_target != target)
+ convert_move (target, new_target, 0);
if (unsignedp)
{