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]

[PATCH] Fix i386-sse-6.c (take 2)


On Sat, Feb 14, 2004 at 04:33:37AM -0500, Jakub Jelinek wrote:
> On Sat, Feb 14, 2004 at 07:27:36AM +0100, Eric Botcazou wrote:
> > > 2004-02-10  Jakub Jelinek  <jakub@redhat.com>
> > >
> > > 	* gcc.dg/i386-cpuid.h (bit_CMOV): Define.
> > > 	* gcc.dg/i386-sse-6.c (main): Pass if CPU has no vector support or
> > > 	cmov.
> > 
> > You didn't commit it, did you?
> 
> That test has lots of other bugs, so I'm working on it ATM.

This patch seems to fix things on both PIII and AMD64.
Had to split the test into 3, because if it is compiled with -msse2, it
obviously cannot run on machines which don't have sse2 (argument setup will
use SSE2 insns, so on say MMX+SSE machines it will abort).
Ok for trunk/3.4?

2004-02-14  Jakub Jelinek  <jakub@redhat.com>

	* gcc.dg/i386-cpuid.h (bit_CMOV): Define.
	(i386_cpuid): No need to test if cpuid is available on AMD64.
	Fix assembly, so that it works onboth i386 and AMD64.
	* gcc.dg/i386-sse-6.c: Include stdio.h, stdlib.h and string.h.
	(vecInLong): Fix s[] member type to unsigned int.
	(main): Pass if CPU has no MMX, SSE, SSE2 or CMOV support.
	Remove unused variable.
	(dump64_64): Remove unused variable.
	(check): Add return stmt.
	* gcc.dg/i386-sse-7.c: New test.
	* gcc.dg/i386-mmx-4.c: New test.

--- gcc/testsuite/gcc.dg/i386-cpuid.h.jj	2004-01-09 02:01:50.000000000 +0100
+++ gcc/testsuite/gcc.dg/i386-cpuid.h	2004-02-14 10:17:37.000000000 +0100
@@ -2,6 +2,7 @@
    Used by 20020523-2.c and i386-sse-6.c, and possibly others.  */
 /* Plagarized from 20020523-2.c.  */
 
+#define bit_CMOV (1 << 15)
 #define bit_MMX (1 << 23)
 #define bit_SSE (1 << 25)
 #define bit_SSE2 (1 << 26)
@@ -17,27 +18,39 @@ i386_cpuid (void)
 {
   int fl1, fl2;
 
-  /* See if we can use cpuid.  */
+#ifndef __x86_64__
+  /* See if we can use cpuid.  On AMD64 we always can.  */
   __asm__ ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
 	   "pushl %0; popfl; pushfl; popl %0; popfl"
 	   : "=&r" (fl1), "=&r" (fl2)
 	   : "i" (0x00200000));
   if (((fl1 ^ fl2) & 0x00200000) == 0)
     return (0);
+#endif
 
   /* Host supports cpuid.  See if cpuid gives capabilities, try
      CPUID(0).  Preserve %ebx and %ecx; cpuid insn clobbers these, we
      don't need their CPUID values here, and %ebx may be the PIC
      register.  */
-  __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx"
+#ifdef __x86_64__
+  __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx"
+	   : "=a" (fl1) : "0" (0) : "rdx", "cc");
+#else
+  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
 	   : "=a" (fl1) : "0" (0) : "edx", "cc");
+#endif
   if (fl1 == 0)
     return (0);
 
   /* Invoke CPUID(1), return %edx; caller can examine bits to
      determine what's supported.  */
-  __asm__ ("push %%ecx ; push %%ebx ; cpuid ; pop %%ebx ; pop %%ecx" : "=d" (fl2) : "a" (1) : "cc");
+#ifdef __x86_64__
+  __asm__ ("pushq %%rcx; pushq %%rbx; cpuid; popq %%rbx; popq %%rcx"
+	   : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
+#else
+  __asm__ ("pushl %%ecx; pushl %%ebx; cpuid; popl %%ebx; popl %%ecx"
+	   : "=d" (fl2), "=a" (fl1) : "1" (1) : "cc");
+#endif
 
   return fl2;
 }
-
--- gcc/testsuite/gcc.dg/i386-sse-6.c.jj	2004-01-09 02:01:50.000000000 +0100
+++ gcc/testsuite/gcc.dg/i386-sse-6.c	2004-02-14 10:47:59.000000000 +0100
@@ -1,6 +1,9 @@
 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
 /* { dg-options "-O2 -msse2" } */
 #include <xmmintrin.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 #include "i386-cpuid.h"
 
 #ifndef NOINLINE
@@ -11,7 +14,7 @@
 
 typedef union {
   __m128i v;
-  unsigned long s[4];
+  unsigned int s[4];
   unsigned short int t[8];
   unsigned long long u[2];
   unsigned char c[16];
@@ -98,12 +101,13 @@ const char *reference_sse2[] = {
 
 int main()
 {
-  unsigned long *p;
   unsigned long cpu_facilities;
 
   cpu_facilities = i386_cpuid ();
 
-  if (!cpu_facilities)	/* If host has no vector support, pass.  */
+  if ((cpu_facilities & (bit_MMX | bit_SSE | bit_SSE2 | bit_CMOV))
+      != (bit_MMX | bit_SSE | bit_SSE2 | bit_CMOV))
+    /* If host has no vector support, pass.  */
     exit (0);
 
   a128.s[0] = 0x01234567;
@@ -381,7 +385,6 @@ dump64_32 (char *buf, char *name, vecInW
 void
 dump64_64 (char *buf, char *name, vecInWord x)
 {
-  int i;
   char *p = buf + strlen (buf);
 
   sprintf (p, "%s ", name);
@@ -502,4 +505,5 @@ check (const char *input, const char *re
   *p_comparison = '\0';
   strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
   errors += new_errors;
+  return 0;
 }
--- gcc/testsuite/gcc.dg/i386-sse-7.c.jj	2004-02-14 10:40:15.000000000 +0100
+++ gcc/testsuite/gcc.dg/i386-sse-7.c	2004-02-14 10:48:03.000000000 +0100
@@ -0,0 +1,274 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -msse" } */
+#include <xmmintrin.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "i386-cpuid.h"
+
+#ifndef NOINLINE
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+#define SHIFT (4)
+
+typedef union {
+  __m64 v;
+  unsigned char c[8];
+  unsigned short int s[4];
+  unsigned long long t;
+  unsigned int u[2];
+}vecInWord;
+
+void mmx_tests (void) NOINLINE;
+void sse_tests (void) NOINLINE;
+void dump64_16 (char *, char *, vecInWord);
+void dump64_32 (char *, char *, vecInWord);
+void dump64_64 (char *, char *, vecInWord);
+int check (const char *, const char *[]);
+
+char buf[8000];
+char comparison[8000];
+static int errors = 0;
+
+vecInWord a64, b64, c64, d64, e64;
+__m64 m64_16, s64, m64_32, m64_64;
+
+const char *reference_mmx[] = {
+  "_mm_srai_pi16 0012 0012 0012 0012 \n",
+  "_mm_sra_pi16 0012 0012 0012 0012 \n",
+  "_mm_srai_pi32 00123456 00123456 \n",
+  "_mm_sra_pi32 00123456 00123456 \n",
+  "_mm_srli_pi16 0012 0012 0012 0012 \n",
+  "_mm_srl_pi16 0012 0012 0012 0012 \n",
+  "_mm_srli_pi32 00123456 00123456 \n",
+  "_mm_srl_pi32 00123456 00123456 \n",
+  "_mm_srli_si64 00123456789abcde\n",
+  "_mm_srl_si64 00123456789abcde\n",
+  "_mm_slli_pi16 1230 1230 1230 1230 \n",
+  "_mm_sll_pi16 1230 1230 1230 1230 \n",
+  "_mm_slli_pi32 12345670 12345670 \n",
+  "_mm_sll_pi32 12345670 12345670 \n",
+  "_mm_slli_si64 123456789abcdef0\n",
+  "_mm_sll_si64 123456789abcdef0\n",
+  ""
+};
+
+const char *reference_sse[] = {
+  "_mm_shuffle_pi16 0123 4567 89ab cdef \n",
+  ""
+};
+
+int main()
+{
+  unsigned long cpu_facilities;
+
+  cpu_facilities = i386_cpuid ();
+
+  if ((cpu_facilities & (bit_MMX | bit_SSE | bit_CMOV))
+      != (bit_MMX | bit_SSE | bit_CMOV))
+    /* If host has no vector support, pass.  */
+    exit (0);
+
+  d64.u[0]  = 0x01234567;
+  d64.u[1]  = 0x01234567;
+
+  m64_32 = d64.v;
+
+  e64.t  = 0x0123456789abcdefULL;
+
+  m64_64 = e64.v;
+
+  a64.s[0] = 0x0123;
+  a64.s[1] = 0x0123;
+  a64.s[2] = 0x0123;
+  a64.s[3] = 0x0123;
+
+  m64_16 = a64.v;
+
+  b64.s[0] = SHIFT;
+  b64.s[1] = 0;
+  b64.s[2] = 0;
+  b64.s[3] = 0;
+
+  s64 = b64.v;
+
+  if (cpu_facilities & bit_MMX)
+    {
+      mmx_tests();
+      check (buf, reference_mmx);
+#ifdef DEBUG
+      printf ("mmx testing:\n");
+      printf (buf);
+      printf ("\ncomparison:\n");
+      printf (comparison);
+#endif
+      buf[0] = '\0';
+    }
+
+  if (cpu_facilities & bit_SSE)
+    {
+      sse_tests();
+      check (buf, reference_sse);
+#ifdef DEBUG
+      printf ("sse testing:\n");
+      printf (buf);
+      printf ("\ncomparison:\n");
+      printf (comparison);
+#endif
+      buf[0] = '\0';
+    }
+
+  if (errors != 0)
+    abort ();
+  exit (0);
+}
+
+void NOINLINE
+mmx_tests (void)
+{
+  /* psraw */
+  c64.v = _mm_srai_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_srai_pi16", c64);
+  c64.v  = _mm_sra_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_sra_pi16", c64);
+
+  /* psrad */
+  c64.v  = _mm_srai_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_srai_pi32", c64);
+  c64.v = _mm_sra_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_sra_pi32", c64);
+
+  /* psrlw */
+  c64.v = _mm_srli_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_srli_pi16", c64);
+  c64.v = _mm_srl_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_srl_pi16", c64);
+
+  /* psrld */
+  c64.v = _mm_srli_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_srli_pi32", c64);
+  c64.v = _mm_srl_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_srl_pi32", c64);
+
+  /* psrlq */
+  c64.v = _mm_srli_si64 (m64_64, SHIFT);
+  dump64_64 (buf, "_mm_srli_si64", c64);
+  c64.v = _mm_srl_si64 (m64_64, s64);
+  dump64_64 (buf, "_mm_srl_si64", c64);
+
+  /* psllw */
+  c64.v = _mm_slli_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_slli_pi16", c64);
+  c64.v = _mm_sll_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_sll_pi16", c64);
+
+  /* pslld */
+  c64.v = _mm_slli_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_slli_pi32", c64);
+  c64.v = _mm_sll_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_sll_pi32", c64);
+
+  /* psllq */
+  c64.v = _mm_slli_si64 (m64_64, SHIFT);
+  dump64_64 (buf, "_mm_slli_si64", c64);
+  c64.v = _mm_sll_si64 (m64_64, s64);
+  dump64_64 (buf, "_mm_sll_si64", c64);
+}
+
+void NOINLINE
+sse_tests (void)
+{
+  /* pshufw */
+  c64.v = _mm_shuffle_pi16 (m64_64, 0x1b);
+  dump64_16 (buf, "_mm_shuffle_pi16", c64);
+}
+
+void
+dump64_16 (char *buf, char *name, vecInWord x)
+{
+  int i;
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  for (i=0; i<4; i++)
+    {
+      sprintf (p, "%4.4x ", x.s[i]);
+      p += strlen (p);
+    }
+  strcat (p, "\n");
+}
+
+void
+dump64_32 (char *buf, char *name, vecInWord x)
+{
+  int i;
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  for (i=0; i<2; i++)
+    {
+      sprintf (p, "%8.8x ", x.u[i]);
+      p += strlen (p);
+    }
+  strcat (p, "\n");
+}
+
+void
+dump64_64 (char *buf, char *name, vecInWord x)
+{
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  sprintf (p, "%16.16llx\n", x.t);
+}
+
+int
+check (const char *input, const char *reference[])
+{
+  int broken, i, j, len;
+  const char *p_input;
+  char *p_comparison;
+  int new_errors = 0;
+
+  p_comparison = &comparison[0];
+  p_input = input;
+
+  for (i = 0; *reference[i] != '\0'; i++)
+    {
+      broken = 0;
+      len = strlen (reference[i]);
+      for (j = 0; j < len; j++)
+	{
+	  /* Ignore the terminating NUL characters at the end of every string in 'reference[]'.  */
+	  if (!broken && *p_input != reference[i][j])
+	    {
+	      *p_comparison = '\0';
+	      strcat (p_comparison, " >>> ");
+	      p_comparison += strlen (p_comparison);
+	      new_errors++;
+	      broken = 1;
+	    }
+	  *p_comparison = *p_input;
+	  p_comparison++;
+	  p_input++;
+	}
+      if (broken)
+	{
+	  *p_comparison = '\0';
+	  strcat (p_comparison, "expected:\n");
+	  strcat (p_comparison, reference[i]);
+	  p_comparison += strlen (p_comparison);
+	}
+    }
+  *p_comparison = '\0';
+  strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
+  errors += new_errors;
+  return 0;
+}
--- gcc/testsuite/gcc.dg/i386-mmx-4.c.jj	2004-02-14 10:43:13.000000000 +0100
+++ gcc/testsuite/gcc.dg/i386-mmx-4.c	2004-02-14 10:48:12.000000000 +0100
@@ -0,0 +1,246 @@
+/* { dg-do run { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -mmmx" } */
+#include <mmintrin.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "i386-cpuid.h"
+
+#ifndef NOINLINE
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+#define SHIFT (4)
+
+typedef union {
+  __m64 v;
+  unsigned char c[8];
+  unsigned short int s[4];
+  unsigned long long t;
+  unsigned int u[2];
+}vecInWord;
+
+void mmx_tests (void) NOINLINE;
+void sse_tests (void) NOINLINE;
+void dump64_16 (char *, char *, vecInWord);
+void dump64_32 (char *, char *, vecInWord);
+void dump64_64 (char *, char *, vecInWord);
+int check (const char *, const char *[]);
+
+char buf[8000];
+char comparison[8000];
+static int errors = 0;
+
+vecInWord a64, b64, c64, d64, e64;
+__m64 m64_16, s64, m64_32, m64_64;
+
+const char *reference_mmx[] = {
+  "_mm_srai_pi16 0012 0012 0012 0012 \n",
+  "_mm_sra_pi16 0012 0012 0012 0012 \n",
+  "_mm_srai_pi32 00123456 00123456 \n",
+  "_mm_sra_pi32 00123456 00123456 \n",
+  "_mm_srli_pi16 0012 0012 0012 0012 \n",
+  "_mm_srl_pi16 0012 0012 0012 0012 \n",
+  "_mm_srli_pi32 00123456 00123456 \n",
+  "_mm_srl_pi32 00123456 00123456 \n",
+  "_mm_srli_si64 00123456789abcde\n",
+  "_mm_srl_si64 00123456789abcde\n",
+  "_mm_slli_pi16 1230 1230 1230 1230 \n",
+  "_mm_sll_pi16 1230 1230 1230 1230 \n",
+  "_mm_slli_pi32 12345670 12345670 \n",
+  "_mm_sll_pi32 12345670 12345670 \n",
+  "_mm_slli_si64 123456789abcdef0\n",
+  "_mm_sll_si64 123456789abcdef0\n",
+  ""
+};
+
+int main()
+{
+  unsigned long cpu_facilities;
+
+  cpu_facilities = i386_cpuid ();
+
+  if ((cpu_facilities & bit_MMX) == 0)
+    exit (0);
+
+  d64.u[0]  = 0x01234567;
+  d64.u[1]  = 0x01234567;
+
+  m64_32 = d64.v;
+
+  e64.t  = 0x0123456789abcdefULL;
+
+  m64_64 = e64.v;
+
+  a64.s[0] = 0x0123;
+  a64.s[1] = 0x0123;
+  a64.s[2] = 0x0123;
+  a64.s[3] = 0x0123;
+
+  m64_16 = a64.v;
+
+  b64.s[0] = SHIFT;
+  b64.s[1] = 0;
+  b64.s[2] = 0;
+  b64.s[3] = 0;
+
+  s64 = b64.v;
+
+  if (cpu_facilities & bit_MMX)
+    {
+      mmx_tests();
+      check (buf, reference_mmx);
+#ifdef DEBUG
+      printf ("mmx testing:\n");
+      printf (buf);
+      printf ("\ncomparison:\n");
+      printf (comparison);
+#endif
+      buf[0] = '\0';
+    }
+
+  if (errors != 0)
+    abort ();
+  exit (0);
+}
+
+void NOINLINE
+mmx_tests (void)
+{
+  /* psraw */
+  c64.v = _mm_srai_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_srai_pi16", c64);
+  c64.v  = _mm_sra_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_sra_pi16", c64);
+
+  /* psrad */
+  c64.v  = _mm_srai_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_srai_pi32", c64);
+  c64.v = _mm_sra_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_sra_pi32", c64);
+
+  /* psrlw */
+  c64.v = _mm_srli_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_srli_pi16", c64);
+  c64.v = _mm_srl_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_srl_pi16", c64);
+
+  /* psrld */
+  c64.v = _mm_srli_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_srli_pi32", c64);
+  c64.v = _mm_srl_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_srl_pi32", c64);
+
+  /* psrlq */
+  c64.v = _mm_srli_si64 (m64_64, SHIFT);
+  dump64_64 (buf, "_mm_srli_si64", c64);
+  c64.v = _mm_srl_si64 (m64_64, s64);
+  dump64_64 (buf, "_mm_srl_si64", c64);
+
+  /* psllw */
+  c64.v = _mm_slli_pi16 (m64_16, SHIFT);
+  dump64_16 (buf, "_mm_slli_pi16", c64);
+  c64.v = _mm_sll_pi16 (m64_16, s64);
+  dump64_16 (buf, "_mm_sll_pi16", c64);
+
+  /* pslld */
+  c64.v = _mm_slli_pi32 (m64_32, SHIFT);
+  dump64_32 (buf, "_mm_slli_pi32", c64);
+  c64.v = _mm_sll_pi32 (m64_32, s64);
+  dump64_32 (buf, "_mm_sll_pi32", c64);
+
+  /* psllq */
+  c64.v = _mm_slli_si64 (m64_64, SHIFT);
+  dump64_64 (buf, "_mm_slli_si64", c64);
+  c64.v = _mm_sll_si64 (m64_64, s64);
+  dump64_64 (buf, "_mm_sll_si64", c64);
+}
+
+void
+dump64_16 (char *buf, char *name, vecInWord x)
+{
+  int i;
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  for (i=0; i<4; i++)
+    {
+      sprintf (p, "%4.4x ", x.s[i]);
+      p += strlen (p);
+    }
+  strcat (p, "\n");
+}
+
+void
+dump64_32 (char *buf, char *name, vecInWord x)
+{
+  int i;
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  for (i=0; i<2; i++)
+    {
+      sprintf (p, "%8.8x ", x.u[i]);
+      p += strlen (p);
+    }
+  strcat (p, "\n");
+}
+
+void
+dump64_64 (char *buf, char *name, vecInWord x)
+{
+  char *p = buf + strlen (buf);
+
+  sprintf (p, "%s ", name);
+  p += strlen (p);
+
+  sprintf (p, "%16.16llx\n", x.t);
+}
+
+int
+check (const char *input, const char *reference[])
+{
+  int broken, i, j, len;
+  const char *p_input;
+  char *p_comparison;
+  int new_errors = 0;
+
+  p_comparison = &comparison[0];
+  p_input = input;
+
+  for (i = 0; *reference[i] != '\0'; i++)
+    {
+      broken = 0;
+      len = strlen (reference[i]);
+      for (j = 0; j < len; j++)
+	{
+	  /* Ignore the terminating NUL characters at the end of every string in 'reference[]'.  */
+	  if (!broken && *p_input != reference[i][j])
+	    {
+	      *p_comparison = '\0';
+	      strcat (p_comparison, " >>> ");
+	      p_comparison += strlen (p_comparison);
+	      new_errors++;
+	      broken = 1;
+	    }
+	  *p_comparison = *p_input;
+	  p_comparison++;
+	  p_input++;
+	}
+      if (broken)
+	{
+	  *p_comparison = '\0';
+	  strcat (p_comparison, "expected:\n");
+	  strcat (p_comparison, reference[i]);
+	  p_comparison += strlen (p_comparison);
+	}
+    }
+  *p_comparison = '\0';
+  strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
+  errors += new_errors;
+  return 0;
+}

	Jakub


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