This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: PATCH: PR target/30040: -mtune=native is wrong on Core 2 Duo and Core Duo
On Sat, Dec 02, 2006 at 10:44:14AM -0700, Roger Sayle wrote:
>
> Hi HJ,
>
> On Fri, 1 Dec 2006, H. J. Lu wrote:
> > 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=*.
>
> This is OK for mainline. Thanks.
>
I checked it in. I added
* config/i386/x-i386 (driver-i386.o): Also depend on $(TM_H)
coretypes.h.
for make depedency. Here is the backported patch for 4.2. Tested on
Linux/x86 and Linux/x86-64.
Thanks.
H.J.
----
2006-12-02 H.J. Lu <hongjiu.lu@intel.com>
Backport from mainline:
2006-12-02 H.J. Lu <hongjiu.lu@intel.com>
PR target/30040
* config/i386/driver-i386.c: Include "coretypes.h" and "tm.h".
(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=*.
* config/i386/x-i386 (driver-i386.o): Also depend on $(TM_H)
coretypes.h.
--- gcc/config/i386/driver-i386.c.native 2006-11-18 06:26:01.000000000 -0800
+++ gcc/config/i386/driver-i386.c 2006-12-02 08:17:02.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);
@@ -57,19 +59,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_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 +90,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,6 +101,7 @@ 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);
@@ -117,44 +125,147 @@ 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_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;
}
- else if (has_mmx)
- cpu = "pentium2";
- if (has_sse)
- cpu = "pentium3";
- if (has_sse2)
+ }
+
+ 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 (arch)
{
- if (family == 6)
- /* It's a pentiumpro with sse2 --> pentium-m */
- cpu = "pentium-m";
+ if (has_sse3)
+ {
+ if (has_longmode)
+ {
+ /* It is Core 2 Duo. */
+ cpu = "nocona";
+ }
+ else
+ {
+ /* 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
- /* Would have to look at extended family, but it's at least
- an pentium4 core. */
- cpu = "pentium4";
+ {
+ /* Default to Pentium Pro. */
+ cpu = "pentiumpro";
+ }
+ }
+ else
+ {
+ /* For -mtune, we default to -mtune=generic. */
+ cpu = "generic";
}
+ 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 +276,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-02 08:17:02.000000000 -0800
+++ gcc/config/i386/i386.h 2006-12-02 08:17:02.000000000 -0800
@@ -318,7 +318,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
--- gcc/config/i386/x-i386.native 2006-11-18 06:26:01.000000000 -0800
+++ gcc/config/i386/x-i386 2006-12-02 08:49:18.000000000 -0800
@@ -1,3 +1,3 @@
driver-i386.o : $(srcdir)/config/i386/driver-i386.c \
- $(CONFIG_H) $(SYSTEM_H)
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<