aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2007-09-30 22:50:02 +0000
committerRichard Sandiford <rsandifo@nildram.co.uk>2007-09-30 22:50:02 +0000
commitdc984169fe240e8f5498e701471b2e5f5b79671c (patch)
tree872f69f3d734d6f77088296a0efc0dfa8d489b1d /gcc
parentc8d9f104f1a995b109c5cd70e7794436e8bfdb05 (diff)
gcc/
* config/mips/mips.c (mips_split_64bit_move): Use gen_rtx_REG_offset rather than gen_lowpart to change a register from DImode to DFmode. (mips_cannot_change_mode_class): Only allow FPRs to change mode if both FROM and TO are integer modes that are no bigger than 4 bytes. (mips_mode_ok_for_mov_fmt_p): New function. (mips_preferred_reload_class): Use it instead of FLOAT_MODE_P. (mips_secondary_reload_class): Tweak formatting and comments. Use reg_class_subset_p instead of direct comparisons with classes. Only allow direct FPR<->FPR moves for modes that satisfy mips_mode_ok_for_mov_fmt_p. Only allow loads and stores for 4- and 8-byte types. Handle reloads in which X is an FPR. * config/mips/mips.md (*movdi_gp32_fp64): Remove f<-f alternative. (*movdi_64bit): Likewise. (*movsi_internal): Likewise. (*movhi_internal): Likewise. (*movqi_internal): Likewise. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@128894 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog19
-rw-r--r--gcc/config/mips/mips.c217
-rw-r--r--gcc/config/mips/mips.md42
3 files changed, 141 insertions, 137 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index eef9e94799b..5c1fdc0566c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,22 @@
+2007-09-30 Richard Sandiford <rsandifo@nildram.co.uk>
+
+ * config/mips/mips.c (mips_split_64bit_move): Use gen_rtx_REG_offset
+ rather than gen_lowpart to change a register from DImode to DFmode.
+ (mips_cannot_change_mode_class): Only allow FPRs to change mode if
+ both FROM and TO are integer modes that are no bigger than 4 bytes.
+ (mips_mode_ok_for_mov_fmt_p): New function.
+ (mips_preferred_reload_class): Use it instead of FLOAT_MODE_P.
+ (mips_secondary_reload_class): Tweak formatting and comments.
+ Use reg_class_subset_p instead of direct comparisons with
+ classes. Only allow direct FPR<->FPR moves for modes that
+ satisfy mips_mode_ok_for_mov_fmt_p. Only allow loads and stores
+ for 4- and 8-byte types. Handle reloads in which X is an FPR.
+ * config/mips/mips.md (*movdi_gp32_fp64): Remove f<-f alternative.
+ (*movdi_64bit): Likewise.
+ (*movsi_internal): Likewise.
+ (*movhi_internal): Likewise.
+ (*movqi_internal): Likewise.
+
2007-09-30 Diego Novillo <dnovillo@google.com>
PR 33593
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index dbb7149b86e..6ac976abe6e 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3547,7 +3547,8 @@ mips_split_64bit_move (rtx dest, rtx src)
/* Loading an FPR from memory or from GPRs. */
if (ISA_HAS_MXHC1)
{
- dest = gen_lowpart (DFmode, dest);
+ if (GET_MODE (dest) != DFmode)
+ dest = gen_rtx_REG_offset (dest, DFmode, REGNO (dest), 0);
emit_insn (gen_load_df_low (dest, mips_subword (src, 0)));
emit_insn (gen_mthc1 (dest, mips_subword (src, 1),
copy_rtx (dest)));
@@ -3565,7 +3566,8 @@ mips_split_64bit_move (rtx dest, rtx src)
/* Storing an FPR into memory or GPRs. */
if (ISA_HAS_MXHC1)
{
- src = gen_lowpart (DFmode, src);
+ if (GET_MODE (src) != DFmode)
+ src = gen_rtx_REG_offset (src, DFmode, REGNO (src), 0);
mips_emit_move (mips_subword (dest, 0), mips_subword (src, 0));
emit_insn (gen_mfhc1 (mips_subword (dest, 1), src));
}
@@ -9314,44 +9316,38 @@ mips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
to mode TO. */
bool
-mips_cannot_change_mode_class (enum machine_mode from,
- enum machine_mode to, enum reg_class class)
+mips_cannot_change_mode_class (enum machine_mode from ATTRIBUTE_UNUSED,
+ enum machine_mode to ATTRIBUTE_UNUSED,
+ 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 (MAX_FPRS_PER_FMT > 1 && reg_classes_intersect_p (FP_REGS, class))
- return true;
- }
- }
+ /* There are several problems with changing the modes of values
+ in floating-point registers:
- /* gcc assumes that each word of a multiword register can be accessed
- individually using SUBREGs. This is not true for floating-point
- registers if they are bigger than a word. */
- if (UNITS_PER_FPREG > UNITS_PER_WORD
- && GET_MODE_SIZE (from) > UNITS_PER_WORD
- && GET_MODE_SIZE (to) < UNITS_PER_FPREG
- && reg_classes_intersect_p (FP_REGS, class))
- return true;
+ - 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 on big-endian targets.
- /* 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_64BIT
- && TARGET_FLOAT64
- && from == SImode
- && GET_MODE_SIZE (to) >= UNITS_PER_WORD
- && reg_classes_intersect_p (FP_REGS, class))
- return true;
+ - GCC assumes that each word of a multiword register can be accessed
+ individually using SUBREGs. This is not true for floating-point
+ registers if they are bigger than a word.
- return false;
+ - 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 FPRs to change from SImode to to a wider mode on
+ 64-bit targets.
+
+ - If the FPU has already interpreted a value in one format, we must
+ not ask it to treat the value as having a different format.
+
+ We therefore only allow changes between 4-byte and smaller integer
+ values, all of which have the "W" format as far as the FPU is
+ concerned. */
+ return (reg_classes_intersect_p (FP_REGS, class)
+ && (GET_MODE_CLASS (from) != MODE_INT
+ || GET_MODE_CLASS (to) != MODE_INT
+ || GET_MODE_SIZE (from) > 4
+ || GET_MODE_SIZE (to) > 4));
}
/* Return true if X should not be moved directly into register $25.
@@ -9367,6 +9363,27 @@ mips_dangerous_for_la25_p (rtx x)
&& mips_global_symbol_p (x));
}
+/* Return true if moves in mode MODE can use the FPU's mov.fmt instruction. */
+
+static bool
+mips_mode_ok_for_mov_fmt_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case SFmode:
+ return TARGET_HARD_FLOAT;
+
+ case DFmode:
+ return TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT;
+
+ case V2SFmode:
+ return TARGET_HARD_FLOAT && TARGET_PAIRED_SINGLE_FLOAT;
+
+ default:
+ return false;
+ }
+}
+
/* Implement PREFERRED_RELOAD_CLASS. */
enum reg_class
@@ -9375,9 +9392,8 @@ mips_preferred_reload_class (rtx x, enum reg_class class)
if (mips_dangerous_for_la25_p (x) && reg_class_subset_p (LEA_REGS, class))
return LEA_REGS;
- if (TARGET_HARD_FLOAT
- && FLOAT_MODE_P (GET_MODE (x))
- && reg_class_subset_p (FP_REGS, class))
+ if (reg_class_subset_p (FP_REGS, class)
+ && mips_mode_ok_for_mov_fmt_p (GET_MODE (x)))
return FP_REGS;
if (reg_class_subset_p (GR_REGS, class))
@@ -9399,110 +9415,81 @@ enum reg_class
mips_secondary_reload_class (enum reg_class class,
enum machine_mode mode, rtx x, int in_p)
{
- enum reg_class gr_regs = TARGET_MIPS16 ? M16_REGS : GR_REGS;
- int regno = -1;
- int gp_reg_p;
-
- if (REG_P (x)|| GET_CODE (x) == SUBREG)
- regno = true_regnum (x);
-
- gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
+ int regno;
+ /* If X is a constant that cannot be loaded into $25, it must be loaded
+ into some other GPR. No other register class allows a direct move. */
if (mips_dangerous_for_la25_p (x))
+ return reg_class_subset_p (class, LEA_REGS) ? NO_REGS : LEA_REGS;
+
+ regno = true_regnum (x);
+ if (TARGET_MIPS16)
{
- gr_regs = LEA_REGS;
- if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], 25))
- return gr_regs;
+ /* In MIPS16 mode, every move must involve a member of M16_REGS. */
+ if (!reg_class_subset_p (class, M16_REGS) && !M16_REG_P (regno))
+ return M16_REGS;
+
+ /* We can't really copy to HI or LO at all in MIPS16 mode. */
+ if (in_p ? reg_classes_intersect_p (class, ACC_REGS) : ACC_REG_P (regno))
+ return M16_REGS;
+
+ return NO_REGS;
}
- /* Copying from HI or LO to anywhere other than a general register
- requires a general register.
- This rule applies to both the original HI/LO pair and the new
- DSP accumulators. */
+ /* Copying from accumulator registers to anywhere other than a general
+ register requires a temporary general register. */
if (reg_class_subset_p (class, ACC_REGS))
- {
- if (TARGET_MIPS16 && in_p)
- {
- /* We can't really copy to HI or LO at all in mips16 mode. */
- return M16_REGS;
- }
- return gp_reg_p ? NO_REGS : gr_regs;
- }
+ return GP_REG_P (regno) ? NO_REGS : GR_REGS;
if (ACC_REG_P (regno))
- {
- if (TARGET_MIPS16 && ! in_p)
- {
- /* We can't really copy to HI or LO at all in mips16 mode. */
- return M16_REGS;
- }
- return class == gr_regs ? NO_REGS : gr_regs;
- }
+ return reg_class_subset_p (class, GR_REGS) ? NO_REGS : GR_REGS;
/* We can only copy a value to a condition code register from a
floating point register, and even then we require a scratch
floating point register. We can only copy a value out of a
condition code register into a general register. */
- if (class == ST_REGS)
+ if (reg_class_subset_p (class, ST_REGS))
{
if (in_p)
return FP_REGS;
- return gp_reg_p ? NO_REGS : gr_regs;
+ return GP_REG_P (regno) ? NO_REGS : GR_REGS;
}
if (ST_REG_P (regno))
{
- if (! in_p)
+ if (!in_p)
return FP_REGS;
- return class == gr_regs ? NO_REGS : gr_regs;
+ return reg_class_subset_p (class, GR_REGS) ? NO_REGS : GR_REGS;
}
- if (class == FP_REGS)
+ if (reg_class_subset_p (class, FP_REGS))
{
- if (MEM_P (x))
- {
- /* In this case we can use lwc1, swc1, ldc1 or sdc1. */
- return NO_REGS;
- }
- else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- /* We can use the l.s and l.d macros to load floating-point
- constants. ??? For l.s, we could probably get better
- code by returning GR_REGS here. */
- return NO_REGS;
- }
- else if (gp_reg_p || x == CONST0_RTX (mode))
- {
- /* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */
- return NO_REGS;
- }
- else if (FP_REG_P (regno))
- {
- /* In this case we can use mov.s or mov.d. */
- return NO_REGS;
- }
- else
- {
- /* Otherwise, we need to reload through an integer register. */
- return gr_regs;
- }
- }
+ if (MEM_P (x)
+ && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8))
+ /* In this case we can use lwc1, swc1, ldc1 or sdc1. We'll use
+ pairs of lwc1s and swc1s if ldc1 and sdc1 are not supported. */
+ return NO_REGS;
- /* In mips16 mode, going between memory and anything but M16_REGS
- requires an M16_REG. */
- if (TARGET_MIPS16)
- {
- if (class != M16_REGS && class != M16_NA_REGS)
+ if (GP_REG_P (regno) || x == CONST0_RTX (mode))
+ /* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */
+ return NO_REGS;
+
+ if (mips_mode_ok_for_mov_fmt_p (mode))
{
- if (gp_reg_p)
+ if (CONSTANT_P (x))
+ /* We can force the constants to memory and use lwc1
+ and ldc1. As above, we will use pairs of lwc1s if
+ ldc1 is not supported. */
return NO_REGS;
- return M16_REGS;
- }
- if (! gp_reg_p)
- {
- if (class == M16_REGS || class == M16_NA_REGS)
+
+ if (FP_REG_P (regno))
+ /* In this case we can use mov.fmt. */
return NO_REGS;
- return M16_REGS;
}
+
+ /* Otherwise, we need to reload through an integer register. */
+ return GR_REGS;
}
+ if (FP_REG_P (regno))
+ return reg_class_subset_p (class, GR_REGS) ? NO_REGS : GR_REGS;
return NO_REGS;
}
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index d687223c382..890cc706590 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -3399,15 +3399,15 @@
(set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
(define_insn "*movdi_gp32_fp64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*f,*d,*m")
- (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*f,*J*d,*m,*f,*f"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*f,*f,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*J*d,*m,*f,*f"))]
"!TARGET_64BIT && TARGET_FLOAT64 && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "type" "multi,multi,load,store,mthilo,mfhilo,fmove,mtc,fpload,mfc,fpstore")
+ [(set_attr "type" "multi,multi,load,store,mthilo,mfhilo,mtc,fpload,mfc,fpstore")
(set_attr "mode" "DI")
- (set_attr "length" "8,16,*,*,8,8,4,8,*,8,*")])
+ (set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
(define_insn "*movdi_32bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
@@ -3421,15 +3421,15 @@
(set_attr "length" "8,8,8,8,12,*,*,8")])
(define_insn "*movdi_64bit"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m")
- (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))]
"TARGET_64BIT && !TARGET_MIPS16
&& (register_operand (operands[0], DImode)
|| reg_or_0_operand (operands[1], DImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "type" "move,const,const,load,store,fmove,mtc,fpload,mfc,fpstore,mthilo,mtc,load,mfc,store")
+ [(set_attr "type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mthilo,mtc,load,mfc,store")
(set_attr "mode" "DI")
- (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")])
+ (set_attr "length" "4,*,*,*,*,4,*,4,*,4,8,*,8,*")])
(define_insn "*movdi_64bit_mips16"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m")
@@ -3518,15 +3518,15 @@
;; in FP registers (off by default, use -mdebugh to enable).
(define_insn "*movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
- (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
{ return mips_output_move (operands[0], operands[1]); }
- [(set_attr "type" "move,const,const,load,store,fmove,mtc,fpload,mfc,fpstore,mfc,mtc,mthilo,mfhilo,mtc,load,mfc,store")
+ [(set_attr "type" "move,const,const,load,store,mtc,fpload,mfc,fpstore,mfc,mtc,mthilo,mfhilo,mtc,load,mfc,store")
(set_attr "mode" "SI")
- (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")])
+ (set_attr "length" "4,*,*,*,*,4,*,4,*,4,4,4,4,4,*,4,*")])
(define_insn "*movsi_mips16"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,d,m")
@@ -3727,8 +3727,8 @@
})
(define_insn "*movhi_internal"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
- (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*x")
+ (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*d"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], HImode)
|| reg_or_0_operand (operands[1], HImode))"
@@ -3739,11 +3739,10 @@
sh\t%z1,%0
mfc1\t%0,%1
mtc1\t%1,%0
- mov.s\t%0,%1
mt%0\t%1"
- [(set_attr "type" "move,arith,load,store,mfc,mtc,fmove,mthilo")
+ [(set_attr "type" "move,arith,load,store,mfc,mtc,mthilo")
(set_attr "mode" "HI")
- (set_attr "length" "4,4,*,*,4,4,4,4")])
+ (set_attr "length" "4,4,*,*,4,4,4")])
(define_insn "*movhi_mips16"
[(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")
@@ -3834,8 +3833,8 @@
})
(define_insn "*movqi_internal"
- [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
- (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*x")
+ (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*d"))]
"!TARGET_MIPS16
&& (register_operand (operands[0], QImode)
|| reg_or_0_operand (operands[1], QImode))"
@@ -3846,11 +3845,10 @@
sb\t%z1,%0
mfc1\t%0,%1
mtc1\t%1,%0
- mov.s\t%0,%1
mt%0\t%1"
- [(set_attr "type" "move,arith,load,store,mfc,mtc,fmove,mthilo")
+ [(set_attr "type" "move,arith,load,store,mfc,mtc,mthilo")
(set_attr "mode" "QI")
- (set_attr "length" "4,4,*,*,4,4,4,4")])
+ (set_attr "length" "4,4,*,*,4,4,4")])
(define_insn "*movqi_mips16"
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")