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:
parent
547101fb67
commit
9abaec9c1c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue