diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2013-11-20 16:22:57 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@gcc.gnu.org> | 2013-11-20 16:22:57 +0000 |
commit | 9abaec9c1ce6de2035637ba50e57f64dcdf5f22f (patch) | |
tree | e0e73a67068d231ddcf242ff608a6e33d9fb6bd6 /gcc | |
parent | 547101fb67fb77fb069acd04669e18f6d4684c9f (diff) | |
download | gcc-9abaec9c1ce6de2035637ba50e57f64dcdf5f22f.zip gcc-9abaec9c1ce6de2035637ba50e57f64dcdf5f22f.tar.gz gcc-9abaec9c1ce6de2035637ba50e57f64dcdf5f22f.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 40 |
2 files changed, 47 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2ffc36a..32a7522 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 4c6a529..bd4e894 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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 |