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]

Re: PATCH: PR target/30040: -mtune=native is wrong on Core 2 Duo and Core Duo


On Fri, Dec 01, 2006 at 01:17:05PM -0800, H. J. Lu wrote:
> -mtune=native and -march=native may be different. Both Core Duo and
> Prescott have the same arch. But they need different -mtune.
> 
> I rewrote processor detection in config/i386/driver-i386.c. For
> Pentium-M and Core Duo, -mtune=native will default to -mtune=generic.
> 
> Gcc 4.2 will need a different patch since there is no -mtune=core2.
> 
> 

I updated it to better handle unknown processor family.


H.J.
----
2006-12-01  H.J. Lu  <hongjiu.lu@intel.com>

	PR target/30040
	* config/i386/driver-i386.c: Include "coretypes.h" and "tm.h".
	(bit_SSSE3): New.
	(host_detect_local_cpu): Check -mtune= vs. -march=. Rewrite
	processor detection.

	* config/i386/i386.h (CC1_CPU_SPEC): Add -mtune=native for
	-march=native if there is no -mtune=*.

--- gcc/config/i386/driver-i386.c.native	2006-11-18 06:26:01.000000000 -0800
+++ gcc/config/i386/driver-i386.c	2006-12-01 13:51:37.000000000 -0800
@@ -20,6 +20,8 @@ Boston, MA 02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include <stdlib.h>
 
 const char *host_detect_local_cpu (int argc, const char **argv);
@@ -37,6 +39,7 @@ const char *host_detect_local_cpu (int a
 #define bit_SSE2 (1 << 26)
 
 #define bit_SSE3 (1 << 0)
+#define bit_SSSE3 (1 << 9)
 #define bit_CMPXCHG16B (1 << 13)
 
 #define bit_3DNOW (1 << 31)
@@ -57,19 +60,24 @@ const char *host_detect_local_cpu (int a
    in the spec.  */
 const char *host_detect_local_cpu (int argc, const char **argv)
 {
-  const char *cpu = "i386";
+  const char *cpu = NULL;
+  enum processor_type processor = PROCESSOR_I386;
   unsigned int eax, ebx, ecx, edx;
   unsigned int max_level;
   unsigned int vendor;
   unsigned int ext_level;
   unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0;
-  unsigned char has_sse2 = 0, has_sse3 = 0, has_cmov = 0;
-  unsigned char has_longmode = 0;
+  unsigned char has_sse2 = 0, has_sse3 = 0, has_ssse3 = 0, has_cmov = 0;
+  unsigned char has_longmode = 0, has_cmpxchg8b = 0;
   unsigned char is_amd = 0;
   unsigned int family = 0;
-  if (argc < 1
-      || (strcmp (argv[0], "arch")
-	  && strcmp (argv[0], "tune")))
+  bool arch;
+
+  if (argc < 1)
+    return NULL;
+
+  arch = strcmp (argv[0], "arch") == 0;
+  if (!arch && strcmp (argv[0], "tune"))
     return NULL;
 
 #ifndef __x86_64__
@@ -83,7 +91,7 @@ const char *host_detect_local_cpu (int a
     goto done;
 #endif
 
-  cpu = "i586";
+  processor = PROCESSOR_PENTIUM;
 
   /* Check the highest input value for eax.  */
   cpuid (0, eax, ebx, ecx, edx);
@@ -94,11 +102,13 @@ const char *host_detect_local_cpu (int a
     goto done;
 
   cpuid (1, eax, ebx, ecx, edx);
+  has_cmpxchg8b = !!(edx & bit_CMPXCHG8B);
   has_cmov = !!(edx & bit_CMOV);
   has_mmx = !!(edx & bit_MMX);
   has_sse = !!(edx & bit_SSE);
   has_sse2 = !!(edx & bit_SSE2);
   has_sse3 = !!(ecx & bit_SSE3);
+  has_ssse3 = !!(ecx & bit_SSSE3);
   /* We don't care for extended family.  */
   family = (eax >> 8) & ~(1 << 4);
 
@@ -117,44 +127,152 @@ const char *host_detect_local_cpu (int a
   if (is_amd)
     {
       if (has_mmx)
-        cpu = "k6";
-      if (has_3dnow)
-        cpu = "k6-3";
+	processor = PROCESSOR_K6;
       if (has_3dnowp)
-        cpu = "athlon";
-      if (has_sse)
-	cpu = "athlon-4";
+	processor = PROCESSOR_ATHLON;
       if (has_sse2 || has_longmode)
-        cpu = "k8";
+	processor = PROCESSOR_K8;
     }
   else
     {
-      if (family == 5)
-        {
-          if (has_mmx)
-            cpu = "pentium-mmx";
+      switch (family)
+	{
+	case 5:
+	  /* Default is PROCESSOR_PENTIUM.  */
+	  break;
+	case 6:
+	  processor = PROCESSOR_PENTIUMPRO;
+	  break;
+	case 15:
+	  processor = PROCESSOR_PENTIUM4;
+	  break;
+	default:
+	  /* We have no idea.  Use something reasonable.  */
+	  if (arch)
+	    {
+	      if (has_ssse3)
+		cpu = "core2";
+	      else if (has_sse3)
+		{
+		  if (has_longmode)
+		    cpu = "nocona";
+		  else
+		    cpu = "prescott";
+		}
+	      else if (has_sse2)
+		cpu = "pentium4";
+	      else if (has_cmov)
+		cpu = "pentiumpro";
+	      else if (has_mmx)
+		cpu = "pentium-mmx";
+	      else if (has_cmpxchg8b)
+		cpu = "pentium";
+	      else
+		cpu = "i386";
+	    }
+	  else
+	    cpu = "generic";
+	  goto done;
+	  break;
+	}
+    }
+
+  switch (processor)
+    {
+    case PROCESSOR_I386:
+      cpu = "i386";
+      break;
+    case PROCESSOR_I486:
+      cpu = "i486";
+      break;
+    case PROCESSOR_PENTIUM:
+      if (has_mmx)
+	cpu = "pentium-mmx";
+      else
+	cpu = "pentium";
+      break;
+    case PROCESSOR_PENTIUMPRO:
+      if (has_longmode)
+	{
+	  /* It is Core 2 Duo.  */
+	  cpu = "core2";
 	}
-      else if (has_mmx)
-        cpu = "pentium2";
-      if (has_sse)
-        cpu = "pentium3";
-      if (has_sse2)
+      else
 	{
-	  if (family == 6)
-	    /* It's a pentiumpro with sse2 --> pentium-m */
-            cpu = "pentium-m";
+	  if (arch)
+	    {
+	      if (has_sse3)
+		{
+		  /* It is Core Duo.  */
+		  cpu = "prescott";
+		}
+	      else if (has_sse2)
+		{
+		  /* It is Pentium M.  */
+		  cpu = "pentium4";
+		}
+	      else if (has_sse)
+		{
+		  /* It is Pentium III.  */
+		  cpu = "pentium3";
+		}
+	      else if (has_mmx)
+		{
+		  /* It is Pentium II.  */
+		  cpu = "pentium2";
+		}
+	      else
+		{
+		  /* Default to Pentium Pro.  */
+		  cpu = "pentiumpro";
+		}
+	    }
 	  else
-	    /* Would have to look at extended family, but it's at least
-	       an pentium4 core.  */
-	    cpu = "pentium4";
+	    {
+	      /* For -mtune, we default to -mtune=generic.  */
+	      cpu = "generic";
+	    }
 	}
+      break;
+    case PROCESSOR_GEODE:
+      cpu = "geode";
+      break;
+    case PROCESSOR_K6:
+      if (has_3dnow)
+        cpu = "k6-3";
+      else
+	cpu = "k6";
+      break;
+    case PROCESSOR_ATHLON:
+      if (has_sse)
+	cpu = "athlon-4";
+      else
+	cpu = "athlon";
+      break;
+    case PROCESSOR_PENTIUM4:
       if (has_sse3)
-        {
+	{
 	  if (has_longmode)
 	    cpu = "nocona";
-	  else 
-            cpu = "prescott";
+	  else
+	    cpu = "prescott";
 	}
+      else
+	cpu = "pentium4";
+      break;
+    case PROCESSOR_K8:
+      cpu = "k8";
+      break;
+    case PROCESSOR_NOCONA:
+      cpu = "nocona";
+      break;
+    case PROCESSOR_GENERIC32:
+    case PROCESSOR_GENERIC64:
+      cpu = "generic";
+      break;
+    default:
+      abort ();
+      break;
     }
 
 done:
@@ -165,6 +283,25 @@ done:
    default value.  */
 const char *host_detect_local_cpu (int argc, const char **argv)
 {
-  return concat ("-m", argv[0], "=i386", NULL);
+  const char *cpu;
+  bool arch;
+
+  if (argc < 1)
+    return NULL;
+
+  arch = strcmp (argv[0], "arch") == 0;
+  if (!arch && strcmp (argv[0], "tune"))
+    return NULL;
+  
+  if (arch)
+    {
+      /* FIXME: i386 is wrong for 64bit compiler.  How can we tell if
+	 we are generating 64bit or 32bit code?  */
+      cpu = "i386";
+    }
+  else
+    cpu = "generic";
+
+  return concat ("-m", argv[0], "=", cpu, NULL);
 }
 #endif /* GCC_VERSION */
--- gcc/config/i386/i386.h.native	2006-12-01 07:07:44.000000000 -0800
+++ gcc/config/i386/i386.h	2006-12-01 12:46:01.000000000 -0800
@@ -356,7 +356,8 @@ extern const char *host_detect_local_cpu
 #define CC1_CPU_SPEC CC1_CPU_SPEC_1
 #else
 #define CC1_CPU_SPEC CC1_CPU_SPEC_1 \
-"%{march=native:%<march=native %:local_cpu_detect(arch)} \
+"%{march=native:%<march=native %:local_cpu_detect(arch) \
+  %{!mtune=*:%<mtune=native %:local_cpu_detect(tune)}} \
 %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
 #endif
 #endif


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