From 8e1606d2850617963337d6ff6ee559653d05f55b Mon Sep 17 00:00:00 2001 From: davem Date: Mon, 21 Nov 2011 21:50:58 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181599 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 ++++++ gcc/config/sparc/sparc-protos.h | 2 ++ gcc/config/sparc/sparc.c | 65 +++++++++++++++++++++++++++++++++++++++++ gcc/config/sparc/sparc.h | 18 ++---------- 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 + * 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 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. */ -- 2.7.4