aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2007-10-19 08:55:02 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2007-10-19 08:55:02 +0000
commitc862c910f6a41f405005037e452fd72736383df7 (patch)
tree4582c7f788b6c946ad8d2368a65298c416fad322
parent5f5fe6d9f7e5680bbf6ebeca21172bc8e3b3454f (diff)
downloadgcc-c862c910f6a41f405005037e452fd72736383df7.zip
gcc-c862c910f6a41f405005037e452fd72736383df7.tar.gz
gcc-c862c910f6a41f405005037e452fd72736383df7.tar.bz2
mips.c (mips_hard_regno_nregs): Put the UNITS_PER_WORD case last.
gcc/ * config/mips/mips.c (mips_hard_regno_nregs): Put the UNITS_PER_WORD case last. (mips_class_max_nregs): Calculate the smallest consituent register size and use that to determine an upper bound on the number of registers. From-SVN: r129478
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/mips/mips.c59
2 files changed, 38 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 8655afa..41e1237 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,13 @@
2007-10-19 Richard Sandiford <rsandifo@nildram.co.uk>
+ * config/mips/mips.c (mips_hard_regno_nregs): Put the UNITS_PER_WORD
+ case last.
+ (mips_class_max_nregs): Calculate the smallest consituent register
+ size and use that to determine an upper bound on the number of
+ registers.
+
+2007-10-19 Richard Sandiford <rsandifo@nildram.co.uk>
+
* config/mips/mips.c (mips16_copy_fpr_return_value): New function,
split out from...
(mips_expand_epilogue): ...here.
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index da9448e..1abee68 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -8805,46 +8805,47 @@ mips_hard_regno_mode_ok_p (unsigned int regno, enum machine_mode mode)
return false;
}
-/* Implement HARD_REGNO_NREGS. The size of FP registers is controlled
- by UNITS_PER_FPREG. The size of FP status registers is always 4, because
- they only hold condition code modes, and CCmode is always considered to
- be 4 bytes wide. All other registers are word sized. */
+/* Implement HARD_REGNO_NREGS. */
unsigned int
mips_hard_regno_nregs (int regno, enum machine_mode mode)
{
if (ST_REG_P (regno))
- return ((GET_MODE_SIZE (mode) + 3) / 4);
- else if (! FP_REG_P (regno))
- return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
- else
- return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
-}
-
-/* Implement CLASS_MAX_NREGS.
+ /* The size of FP status registers is always 4, because they only hold
+ CCmode values, and CCmode is always considered to be 4 bytes wide. */
+ return (GET_MODE_SIZE (mode) + 3) / 4;
- - UNITS_PER_FPREG controls the number of registers needed by FP_REGS.
+ if (FP_REG_P (regno))
+ return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
- - ST_REGS are always hold CCmode values, and CCmode values are
- considered to be 4 bytes wide.
+ /* All other registers are word-sized. */
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
- All other register classes are covered by UNITS_PER_WORD. Note that
- this is true even for unions of integer and float registers when the
- latter are smaller than the former. The only supported combination
- in which case this occurs is -mgp64 -msingle-float, which has 64-bit
- words but 32-bit float registers. A word-based calculation is correct
- in that case since -msingle-float disallows multi-FPR values. */
+/* Implement CLASS_MAX_NREGS, taking the maximum of the cases
+ in mips_hard_regno_nregs. */
int
-mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
- enum machine_mode mode)
+mips_class_max_nregs (enum reg_class class, enum machine_mode mode)
{
- if (class == ST_REGS)
- return (GET_MODE_SIZE (mode) + 3) / 4;
- else if (class == FP_REGS)
- return (GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG;
- else
- return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+ int size;
+ HARD_REG_SET left;
+
+ size = 0x8000;
+ COPY_HARD_REG_SET (left, reg_class_contents[(int) class]);
+ if (hard_reg_set_intersect_p (left, reg_class_contents[(int) ST_REGS]))
+ {
+ size = MIN (size, 4);
+ AND_COMPL_HARD_REG_SET (left, reg_class_contents[(int) ST_REGS]);
+ }
+ if (hard_reg_set_intersect_p (left, reg_class_contents[(int) FP_REGS]))
+ {
+ size = MIN (size, UNITS_PER_FPREG);
+ AND_COMPL_HARD_REG_SET (left, reg_class_contents[(int) FP_REGS]);
+ }
+ if (!hard_reg_set_empty_p (left))
+ size = MIN (size, UNITS_PER_WORD);
+ return (GET_MODE_SIZE (mode) + size - 1) / size;
}
/* Return true if registers of class CLASS cannot change from mode FROM