]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Correct sparc's REGMODE_NATURAL_SIZE and MODES_TIEABLE_P wrt. vector modes.
authorDavid S. Miller <davem@davemloft.net>
Mon, 21 Nov 2011 21:50:58 +0000 (21:50 +0000)
committerDavid S. Miller <davem@gcc.gnu.org>
Mon, 21 Nov 2011 21:50:58 +0000 (13:50 -0800)
* 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

gcc/ChangeLog
gcc/config/sparc/sparc-protos.h
gcc/config/sparc/sparc.c
gcc/config/sparc/sparc.h

index 854b00ec7d371e3a36219f17f3df487f617e45d8..d45424f8637b8de7500db5f05ef93bc523b15a8f 100644 (file)
@@ -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>
 
index ccf20b1bcaa27c2a798b37229ec264779bc56f92..10fa5edbb66111ad3c904eb7057e860fd2219745 100644 (file)
@@ -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__ */
index 55759a03bd1fc6c453aadfac1edff3f580d3eea6..b315698bc94e97cd75e14853e2ce02d227472fbb 100644 (file)
@@ -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"
index e8707f505772384094eff021f275845789213c0b..32f8c1074aee0d5bbc61749c077b32cc7536008a 100644 (file)
@@ -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.  */