rs6000.c (rs6000_cannot_change_mode_class): Do not allow subregs of TDmode in FPRs of smaller size in little-endian.

* config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
	allow subregs of TDmode in FPRs of smaller size in little-endian.
	(rs6000_split_multireg_move): When splitting an access to TDmode
	in FPRs, do not use simplify_gen_subreg.

From-SVN: r205123
This commit is contained in:
Ulrich Weigand 2013-11-20 16:22:57 +00:00 committed by Ulrich Weigand
parent 547101fb67
commit 9abaec9c1c
2 changed files with 47 additions and 0 deletions

View File

@ -1,3 +1,10 @@
2013-11-20 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
* config/rs6000/rs6000.c (rs6000_cannot_change_mode_class): Do not
allow subregs of TDmode in FPRs of smaller size in little-endian.
(rs6000_split_multireg_move): When splitting an access to TDmode
in FPRs, do not use simplify_gen_subreg.
2013-11-20 Joseph Myers <joseph@codesourcery.com>
PR middle-end/21718

View File

@ -16676,6 +16676,13 @@ rs6000_cannot_change_mode_class (enum machine_mode from,
if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode))
return true;
/* TDmode in floating-mode registers must always go into a register
pair with the most significant word in the even-numbered register
to match ISA requirements. In little-endian mode, this does not
match subreg numbering, so we cannot allow subregs. */
if (!BYTES_BIG_ENDIAN && (to == TDmode || from == TDmode))
return true;
if (from_size < 8 || to_size < 8)
return true;
@ -19618,6 +19625,39 @@ rs6000_split_multireg_move (rtx dst, rtx src)
gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
/* TDmode residing in FP registers is special, since the ISA requires that
the lower-numbered word of a register pair is always the most significant
word, even in little-endian mode. This does not match the usual subreg
semantics, so we cannnot use simplify_gen_subreg in those cases. Access
the appropriate constituent registers "by hand" in little-endian mode.
Note we do not need to check for destructive overlap here since TDmode
can only reside in even/odd register pairs. */
if (FP_REGNO_P (reg) && DECIMAL_FLOAT_MODE_P (mode) && !BYTES_BIG_ENDIAN)
{
rtx p_src, p_dst;
int i;
for (i = 0; i < nregs; i++)
{
if (REG_P (src) && FP_REGNO_P (REGNO (src)))
p_src = gen_rtx_REG (reg_mode, REGNO (src) + nregs - 1 - i);
else
p_src = simplify_gen_subreg (reg_mode, src, mode,
i * reg_mode_size);
if (REG_P (dst) && FP_REGNO_P (REGNO (dst)))
p_dst = gen_rtx_REG (reg_mode, REGNO (dst) + nregs - 1 - i);
else
p_dst = simplify_gen_subreg (reg_mode, dst, mode,
i * reg_mode_size);
emit_insn (gen_rtx_SET (VOIDmode, p_dst, p_src));
}
return;
}
if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
{
/* Move register range backwards, if we might have destructive