aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-11-21 21:50:58 +0000
committerDavid S. Miller <davem@gcc.gnu.org>2011-11-21 13:50:58 -0800
commit98ccb32db43c4f2782ca59cd4e0d9ab1b4d37fab (patch)
treee83a97dd65882dcecbef6e3ce93db0030de097b3
parente57a3447f7117ade80869bbcfeb8f8abc3af346a (diff)
downloadgcc-98ccb32db43c4f2782ca59cd4e0d9ab1b4d37fab.zip
gcc-98ccb32db43c4f2782ca59cd4e0d9ab1b4d37fab.tar.gz
gcc-98ccb32db43c4f2782ca59cd4e0d9ab1b4d37fab.tar.bz2
Correct sparc's REGMODE_NATURAL_SIZE and MODES_TIEABLE_P wrt. vector modes.
* config/sparc/sparc.c (sparc_regmode_natural_size): New function implementing REGMODE_NATURAL_SIZE taking into consideration vector modes. (sparc_modes_tieable_p): Similarly for MODES_TIEABLE_P. * config/sparc/sparc-protos.h (sparc_regmode_natural_size, sparc_modes_tieable_p): Declare. * gcc/config/sparc/sparc.h (REGMODE_NATURAL_SIZE, MODES_TIEABLE_P): Use new helper functions. From-SVN: r181599
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/sparc/sparc-protos.h2
-rw-r--r--gcc/config/sparc/sparc.c65
-rw-r--r--gcc/config/sparc/sparc.h18
4 files changed, 78 insertions, 16 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 854b00e..d45424f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
2011-11-21 David S. Miller <davem@davemloft.net>
+ * config/sparc/sparc.c (sparc_regmode_natural_size): New function
+ implementing REGMODE_NATURAL_SIZE taking into consideration vector
+ modes.
+ (sparc_modes_tieable_p): Similarly for MODES_TIEABLE_P.
+ * config/sparc/sparc-protos.h (sparc_regmode_natural_size,
+ sparc_modes_tieable_p): Declare.
+ * gcc/config/sparc/sparc.h (REGMODE_NATURAL_SIZE,
+ MODES_TIEABLE_P): Use new helper functions.
+
Revert
2011-11-16 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index ccf20b1..10fa5ed 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -109,6 +109,8 @@ extern void sparc_expand_vector_init (rtx, rtx);
extern void sparc_expand_vec_perm_bmask(enum machine_mode, rtx);
extern bool sparc_expand_conditional_move (enum machine_mode, rtx *);
extern void sparc_expand_vcond (enum machine_mode, rtx *, int, int);
+unsigned int sparc_regmode_natural_size (enum machine_mode);
+bool sparc_modes_tieable_p (enum machine_mode, enum machine_mode);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 55759a0..b315698 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -11616,4 +11616,69 @@ sparc_expand_vcond (enum machine_mode mode, rtx *operands, int ccode, int fcode)
emit_insn (gen_rtx_SET (VOIDmode, operands[0], bshuf));
}
+/* On sparc, any mode which naturally allocates into the float
+ registers should return 4 here. */
+
+unsigned int
+sparc_regmode_natural_size (enum machine_mode mode)
+{
+ int size = UNITS_PER_WORD;
+
+ if (TARGET_ARCH64)
+ {
+ enum mode_class mclass = GET_MODE_CLASS (mode);
+
+ if (mclass == MODE_FLOAT || mclass == MODE_VECTOR_INT)
+ size = 4;
+ }
+
+ return size;
+}
+
+/* Return TRUE if it is a good idea to tie two pseudo registers
+ when one has mode MODE1 and one has mode MODE2.
+ If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
+ for any hard reg, then this must be FALSE for correct output.
+
+ For V9 we have to deal with the fact that only the lower 32 floating
+ point registers are 32-bit addressable. */
+
+bool
+sparc_modes_tieable_p (enum machine_mode mode1, enum machine_mode mode2)
+{
+ enum mode_class mclass1, mclass2;
+ unsigned short size1, size2;
+
+ if (mode1 == mode2)
+ return true;
+
+ mclass1 = GET_MODE_CLASS (mode1);
+ mclass2 = GET_MODE_CLASS (mode2);
+ if (mclass1 != mclass2)
+ return false;
+
+ if (! TARGET_V9)
+ return true;
+
+ /* Classes are the same and we are V9 so we have to deal with upper
+ vs. lower floating point registers. If one of the modes is a
+ 4-byte mode, and the other is not, we have to mark them as not
+ tieable because only the lower 32 floating point register are
+ addressable 32-bits at a time.
+
+ We can't just test explicitly for SFmode, otherwise we won't
+ cover the vector mode cases properly. */
+
+ if (mclass1 != MODE_FLOAT && mclass1 != MODE_VECTOR_INT)
+ return true;
+
+ size1 = GET_MODE_SIZE (mode1);
+ size2 = GET_MODE_SIZE (mode2);
+ if ((size1 > 4 && size2 == 4)
+ || (size2 > 4 && size1 == 4))
+ return false;
+
+ return true;
+}
+
#include "gt-sparc.h"
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index e8707f5..32f8c10 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -716,8 +716,7 @@ extern enum cmodel sparc_cmodel;
/* Due to the ARCH64 discrepancy above we must override this next
macro too. */
-#define REGMODE_NATURAL_SIZE(MODE) \
- ((TARGET_ARCH64 && FLOAT_MODE_P (MODE)) ? 4 : UNITS_PER_WORD)
+#define REGMODE_NATURAL_SIZE(MODE) sparc_regmode_natural_size (MODE)
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
See sparc.c for how we initialize this. */
@@ -735,20 +734,7 @@ extern int sparc_mode_class[];
register window instruction in the prologue. */
#define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
-/* Value is 1 if it is a good idea to tie two pseudo registers
- when one has mode MODE1 and one has mode MODE2.
- If HARD_REGNO_MODE_OK could produce different values for MODE1 and MODE2,
- for any hard reg, then this must be 0 for correct output.
-
- For V9: SFmode can't be combined with other float modes, because they can't
- be allocated to the %d registers. Also, DFmode won't fit in odd %f
- registers, but SFmode will. */
-#define MODES_TIEABLE_P(MODE1, MODE2) \
- ((MODE1) == (MODE2) \
- || (GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
- && (! TARGET_V9 \
- || (GET_MODE_CLASS (MODE1) != MODE_FLOAT \
- || (MODE1 != SFmode && MODE2 != SFmode)))))
+#define MODES_TIEABLE_P(MODE1, MODE2) sparc_modes_tieable_p (MODE1, MODE2)
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */