This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[committed] Fix mips64-linux-gnu bootstrap
- From: Richard Sandiford <rsandifo at redhat dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 31 Oct 2004 21:13:49 +0000
- Subject: [committed] Fix mips64-linux-gnu bootstrap
Bootstrap was failing on mips64-linux-gnu after this week's tightening
of the subreg code. We were trying to move something into a TFmode
floating-point register and (because there's no movtf pattern) we were
trying do so in two pieces. Unfortunately, mips_cannot_change_mode_class
would needlessly disallow subregs of TFmode FPRs.
The problem is that MIPS's implementation of CANNOT_CHANGE_MODE_CLASS is
really just a rehashing of the old CLASS_CANNOT_CHANGE_MODE definition.
The latter macro was a constant class, with no way of saying which mode
changes were invalid, but these days we can (and should) be more precise.
The cases are still exactly those described by the old comments.
Tested on mips64-linux-gnu, where it fixes bootstrap and produces
comparable results to the last set I have. Applied to mainline.
Richard
* config/mips/mips.c (mips_cannot_change_mode_class): Use a stricter
mode check.
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.474
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.474 mips.c
*** config/mips/mips.c 25 Oct 2004 06:14:33 -0000 1.474
--- config/mips/mips.c 31 Oct 2004 12:43:55 -0000
*************** mips_callee_copies (CUMULATIVE_ARGS *cum
*** 6837,6871 ****
return mips_abi == ABI_EABI && named;
}
! /* Return the class of registers for which a mode change from FROM to TO
! is invalid.
!
! In little-endian mode, the hi-lo registers are numbered backwards,
! so (subreg:SI (reg:DI hi) 0) gets the high word instead of the low
! word as intended.
!
! Similarly, when using paired floating-point registers, the first
! register holds the low word, regardless of endianness. So in big
! endian mode, (subreg:SI (reg:DF $f0) 0) does not get the high word
! as intended.
!
! Also, loading a 32-bit value into a 64-bit floating-point register
! will not sign-extend the value, despite what LOAD_EXTEND_OP says.
! We can't allow 64-bit float registers to change from a 32-bit
! mode to a 64-bit mode. */
bool
mips_cannot_change_mode_class (enum machine_mode from,
enum machine_mode to, enum reg_class class)
{
! if (GET_MODE_SIZE (from) != GET_MODE_SIZE (to))
{
if (TARGET_BIG_ENDIAN)
! return reg_classes_intersect_p (FP_REGS, class);
! if (TARGET_FLOAT64)
! return reg_classes_intersect_p (HI_AND_FP_REGS, class);
! return reg_classes_intersect_p (HI_REG, class);
}
return false;
}
--- 6837,6880 ----
return mips_abi == ABI_EABI && named;
}
! /* Return true if registers of class CLASS cannot change from mode FROM
! to mode TO. */
bool
mips_cannot_change_mode_class (enum machine_mode from,
enum machine_mode to, enum reg_class class)
{
! if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD
! && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS_PER_WORD)
{
if (TARGET_BIG_ENDIAN)
! {
! /* When a multi-word value is stored in paired floating-point
! registers, the first register always holds the low word.
! We therefore can't allow FPRs to change between single-word
! and multi-word modes. */
! if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
! return true;
! }
! else
! {
! /* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored
! in LO and HI, the high word always comes first. We therefore
! can't allow values stored in HI to change between single-word
! and multi-word modes. */
! if (reg_classes_intersect_p (HI_REG, class))
! return true;
! }
}
+ /* Loading a 32-bit value into a 64-bit floating-point register
+ will not sign-extend the value, despite what LOAD_EXTEND_OP says.
+ We can't allow 64-bit float registers to change from SImode to
+ to a wider mode. */
+ if (TARGET_FLOAT64
+ && from == SImode
+ && GET_MODE_SIZE (to) >= UNITS_PER_WORD
+ && reg_classes_intersect_p (FP_REGS, class))
+ return true;
return false;
}