This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Reload bug
oops, I stripped the patch too much last time.
I am attaching full one. It fixes the 3.2 testcases I have...
Does it appear to make sense to you?
Will have to test it on big endian machine too...
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.249.2.10.2.2
diff -c -3 -p -r1.249.2.10.2.2 emit-rtl.c
*** emit-rtl.c 3 Feb 2003 18:01:37 -0000 1.249.2.10.2.2
--- emit-rtl.c 11 Apr 2003 18:25:46 -0000
*************** subreg_hard_regno (x, check_mode)
*** 799,805 ****
abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
!
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
--- 799,809 ----
abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
! #ifdef ENABLE_CHECKING
! if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
! SUBREG_BYTE (x), mode))
! abort ();
! #endif
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
Index: reload.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload.c,v
retrieving revision 1.178.2.4.2.4
diff -c -3 -p -r1.178.2.4.2.4 reload.c
*** reload.c 24 Oct 2002 08:59:49 -0000 1.178.2.4.2.4
--- reload.c 11 Apr 2003 18:25:48 -0000
*************** reload_inner_reg_of_subreg (x, mode, out
*** 817,822 ****
--- 817,829 ----
|| REGNO (inner) >= FIRST_PSEUDO_REGISTER)
return 0;
+ if (!subreg_offset_representable_p
+ (REGNO (SUBREG_REG (x)),
+ GET_MODE (SUBREG_REG (x)),
+ SUBREG_BYTE (x),
+ GET_MODE (x)))
+ return 1;
+
/* If INNER is not ok for MODE, then INNER will need reloading. */
if (! HARD_REGNO_MODE_OK (subreg_regno (x), mode))
return 1;
*************** find_reloads (insn, replace, ind_levels,
*** 2856,2861 ****
--- 2863,2874 ----
if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
+ if (!subreg_offset_representable_p
+ (REGNO (SUBREG_REG (operand)),
+ GET_MODE (SUBREG_REG (operand)),
+ SUBREG_BYTE (operand),
+ GET_MODE (operand)))
+ force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
*************** find_reloads (insn, replace, ind_levels,
*** 2911,2936 ****
)
#endif
)
- /* This following hunk of code should no longer be
- needed at all with SUBREG_BYTE. If you need this
- code back, please explain to me why so I can
- fix the real problem. -DaveM */
- #if 0
- /* Subreg of a hard reg which can't handle the subreg's mode
- or which would handle that mode in the wrong number of
- registers for subregging to work. */
- || (GET_CODE (operand) == REG
- && REGNO (operand) < FIRST_PSEUDO_REGISTER
- && ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
- && (GET_MODE_SIZE (GET_MODE (operand))
- > UNITS_PER_WORD)
- && ((GET_MODE_SIZE (GET_MODE (operand))
- / UNITS_PER_WORD)
- != HARD_REGNO_NREGS (REGNO (operand),
- GET_MODE (operand))))
- || ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
- operand_mode[i])))
- #endif
)
force_reload = 1;
}
--- 2924,2929 ----
Index: rtlanal.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/rtlanal.c,v
retrieving revision 1.126.2.2.4.1
diff -c -3 -p -r1.126.2.2.4.1 rtlanal.c
*** rtlanal.c 9 Jan 2003 13:18:41 -0000 1.126.2.2.4.1
--- rtlanal.c 11 Apr 2003 18:25:48 -0000
*************** subreg_regno_offset (xregno, xmode, offs
*** 3045,3050 ****
--- 3045,3121 ----
return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
}
+ /* This function returns true when the offset is representable via
+ subreg_offset in the given regno.
+ xregno - A regno of an inner hard subreg_reg (or what will become one).
+ xmode - The mode of xregno.
+ offset - The byte offset.
+ ymode - The mode of a top level SUBREG (or what may become one).
+ RETURN - The regno offset which would be used. */
+ bool
+ subreg_offset_representable_p (xregno, xmode, offset, ymode)
+ unsigned int xregno;
+ enum machine_mode xmode;
+ unsigned int offset;
+ enum machine_mode ymode;
+ {
+ int nregs_xmode, nregs_ymode;
+ int mode_multiple, nregs_multiple;
+ int y_offset;
+
+ if (xregno >= FIRST_PSEUDO_REGISTER)
+ abort ();
+
+ nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
+ nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
+
+ /* paradoxical subregs are always valid. */
+ if (offset == 0
+ && nregs_ymode > nregs_xmode
+ && (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
+ ? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
+ return true;
+
+ /* Lowpart subregs are always valid. */
+ if (offset == subreg_lowpart_offset (ymode, xmode))
+ return true;
+
+ #ifdef ENABLE_CHECKING
+ /* This should always pass, otherwise we don't know how to verify the
+ constraint.
+
+ These conditions may be relaxed but subreg_offset would need to be
+ redesigned. */
+ if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
+ || GET_MODE_SIZE (ymode) % nregs_ymode
+ || mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode,
+ MODE_INT, 0) == VOIDmode
+ || nregs_xmode % nregs_ymode)
+ abort ();
+ #endif
+
+ /* The XMODE value can be seen as an vector of NREGS_XMODE
+ values. The subreg must represent an lowpart of given field.
+ Compute what field it is. */
+ offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode)
+ / nregs_ymode,
+ MODE_INT, 0), xmode);
+
+ /* size of ymode must not be greater than the size of xmode. */
+ mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
+ if (mode_multiple == 0)
+ abort ();
+
+ y_offset = offset / GET_MODE_SIZE (ymode);
+ nregs_multiple = nregs_xmode / nregs_ymode;
+ #ifdef ENABLE_CHECKING
+ if (offset % GET_MODE_SIZE (ymode)
+ || mode_multiple % nregs_multiple)
+ abort ();
+ #endif
+ return (!(y_offset % (mode_multiple / nregs_multiple)));
+ }
+
/* Return the final regno that a subreg expression refers to. */
unsigned int
subreg_regno (x)