This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[SPARC] Fix PR target/56890


To my great surprise, this PR shows that the SPARC back-end allows QImode and 
HImode values to live in FP registers, but can neither load nor move them.
This can result in an unrecognizable move insn between FP registers or an 
illegal fdtox instruction in 64-bit mode as shown by the submitted testcases.

The attached patch changes that and yields no regressions both in 32-bit and 
64-bit modes.  Any objections to applying it to all active branches?


2013-04-14  Eric Botcazou  <ebotcazou@adacore.com>

	PR target/56890
	* config/sparc/sparc.c (enum sparc_mode_class): Add H_MODE value.
	(S_MODES): Set H_MODE bit.
	(SF_MODES): Set only S_MODE and SF_MODE bits.
	(DF_MODES): Set SF_MODES and only D_MODE and DF_MODE bits.
	(sparc_init_modes) <MODE_INT>: Set H_MODE bit for sub-word modes.
	<MODE_VECTOR_INT>: Do not set SF_MODE for sub-word modes.
	<MODE_FLOAT>: Likewise.


2013-04-14  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.dg/pr56890-1.c: New test.
	* gcc.dg/pr56890-2.c: Likewise.


-- 
Eric Botcazou
Index: config/sparc/sparc.c
===================================================================
--- config/sparc/sparc.c	(revision 197926)
+++ config/sparc/sparc.c	(working copy)
@@ -4467,13 +4467,14 @@ mem_min_alignment (rtx mem, int desired)
    mapped into one sparc_mode_class mode.  */
 
 enum sparc_mode_class {
-  S_MODE, D_MODE, T_MODE, O_MODE,
+  H_MODE, S_MODE, D_MODE, T_MODE, O_MODE,
   SF_MODE, DF_MODE, TF_MODE, OF_MODE,
   CC_MODE, CCFP_MODE
 };
 
 /* Modes for single-word and smaller quantities.  */
-#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
+#define S_MODES \
+  ((1 << (int) H_MODE) | (1 << (int) S_MODE) | (1 << (int) SF_MODE))
 
 /* Modes for double-word and smaller quantities.  */
 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
@@ -4484,13 +4485,11 @@ enum sparc_mode_class {
 /* Modes for 8-word and smaller quantities.  */
 #define O_MODES (T_MODES | (1 << (int) O_MODE) | (1 << (int) OF_MODE))
 
-/* Modes for single-float quantities.  We must allow any single word or
-   smaller quantity.  This is because the fix/float conversion instructions
-   take integer inputs/outputs from the float registers.  */
-#define SF_MODES (S_MODES)
+/* Modes for single-float quantities.  */
+#define SF_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
 
 /* Modes for double-float and smaller quantities.  */
-#define DF_MODES (D_MODES)
+#define DF_MODES (SF_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
 
 /* Modes for quad-float and smaller quantities.  */
 #define TF_MODES (DF_MODES | (1 << (int) TF_MODE))
@@ -4586,7 +4585,9 @@ sparc_init_modes (void)
 	case MODE_INT:
 	case MODE_PARTIAL_INT:
 	case MODE_COMPLEX_INT:
-	  if (GET_MODE_SIZE (i) <= 4)
+	  if (GET_MODE_SIZE (i) < 4)
+	    sparc_mode_class[i] = 1 << (int) H_MODE;
+	  else if (GET_MODE_SIZE (i) == 4)
 	    sparc_mode_class[i] = 1 << (int) S_MODE;
 	  else if (GET_MODE_SIZE (i) == 8)
 	    sparc_mode_class[i] = 1 << (int) D_MODE;
@@ -4598,14 +4599,16 @@ sparc_init_modes (void)
 	    sparc_mode_class[i] = 0;
 	  break;
 	case MODE_VECTOR_INT:
-	  if (GET_MODE_SIZE (i) <= 4)
-	    sparc_mode_class[i] = 1 << (int)SF_MODE;
+	  if (GET_MODE_SIZE (i) == 4)
+	    sparc_mode_class[i] = 1 << (int) SF_MODE;
 	  else if (GET_MODE_SIZE (i) == 8)
-	    sparc_mode_class[i] = 1 << (int)DF_MODE;
+	    sparc_mode_class[i] = 1 << (int) DF_MODE;
+	  else
+	    sparc_mode_class[i] = 0;
 	  break;
 	case MODE_FLOAT:
 	case MODE_COMPLEX_FLOAT:
-	  if (GET_MODE_SIZE (i) <= 4)
+	  if (GET_MODE_SIZE (i) == 4)
 	    sparc_mode_class[i] = 1 << (int) SF_MODE;
 	  else if (GET_MODE_SIZE (i) == 8)
 	    sparc_mode_class[i] = 1 << (int) DF_MODE;
/* PR target/56890 */
/* Reported by Rainer Jung <rainer.jung@kippdata.de> */

/* { dg-do assemble } */
/* { dg-options "-O2" } */

unsigned int buggy(unsigned int min, unsigned int max)
{
    if (max < 16384) {
        unsigned short num16 = 0;
        num16 = min + (long) ((double) (max - min + 1.0) * (num16 / (65535 + 1.0)));
        return num16;
    }
    return 0;
}
/* PR target/56890 */
/* Reported by Rainer Jung <rainer.jung@kippdata.de> */

/* { dg-do assemble } */
/* { dg-options "-O" } */

unsigned int buggy(unsigned int min, unsigned int max)
{
    unsigned int number;
    if (max < 16384) {
        unsigned short num16;
        num16 = min + (long) ((double) (max - min + 1.0) * (num16 / (65535 + 1.0)));
        return num16;
    }
    else {
        (number) = min + (long) ((double) (max - min + 1.0) * (number / (4294967295U + 1.0)));
    }
    return number;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]