From fa959ce486f4e61e26a48d509e2f9980d35eca1b Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Tue, 9 May 2006 15:40:12 +0000 Subject: [PATCH] config.host (): Set host_extra_gcc_objs and host_xmake_file. (<*-*-linux*>): Don't overwrite host_xmake_file. * gcc.c (static_spec_functions): Add EXTRA_SPEC_FUNCTIONS. * config/i386/i386.h (EXTRA_SPEC_FUNCTIONS): Define. (host_detect_local_cpu): Declare. (CC1_CPU_SPEC): Add -march=native and -mtune=native cases. * config/i386/i386.c (override_options): Handle -mtune=native as -mtune=generic. * config/i386/x-i386: New file. * config/i386/driver-i386.c: New file. * doc/invoke.texi (): Describe cpu-type "native". From-SVN: r113655 --- gcc/ChangeLog | 16 ++++ gcc/config.host | 13 ++- gcc/config/i386/driver-i386.c | 174 ++++++++++++++++++++++++++++++++++ gcc/config/i386/i386.c | 6 +- gcc/config/i386/i386.h | 18 +++- gcc/config/i386/x-i386 | 3 + gcc/doc/invoke.texi | 7 ++ gcc/gcc.c | 3 + 8 files changed, 237 insertions(+), 3 deletions(-) create mode 100644 gcc/config/i386/driver-i386.c create mode 100644 gcc/config/i386/x-i386 diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b7840c4a28f..802de2cec44 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2006-05-09 Michael Matz + + * config.host (): Set + host_extra_gcc_objs and host_xmake_file. + (<*-*-linux*>): Don't overwrite host_xmake_file. + * gcc.c (static_spec_functions): Add EXTRA_SPEC_FUNCTIONS. + * config/i386/i386.h (EXTRA_SPEC_FUNCTIONS): Define. + (host_detect_local_cpu): Declare. + (CC1_CPU_SPEC): Add -march=native and -mtune=native cases. + * config/i386/i386.c (override_options): Handle -mtune=native + as -mtune=generic. + * config/i386/x-i386: New file. + * config/i386/driver-i386.c: New file. + * doc/invoke.texi (): Describe + cpu-type "native". + 2006-05-09 Dirk Mueller Richard Guenther diff --git a/gcc/config.host b/gcc/config.host index f9b39e682f2..b0925a2cab3 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -94,6 +94,17 @@ case ${target} in ;; esac +case ${host} in + i[34567]86-*-* \ + | x86_64-*-* ) + # include the support for -march=native only when not cross compiling + if test x${host} = x${target} ; then + host_extra_gcc_objs="driver-i386.o" + host_xmake_file="${host_xmake_file} i386/x-i386" + fi + ;; +esac + # Machine-specific settings. case ${host} in alpha*-dec-*vms*) @@ -186,7 +197,7 @@ case ${host} in ;; *-*-linux*) out_host_hook_obj=host-linux.o - host_xmake_file=x-linux + host_xmake_file="${host_xmake_file} x-linux" ;; ia64-*-hpux*) use_long_long_for_widest_fast_int=yes diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c new file mode 100644 index 00000000000..f13abd11dc5 --- /dev/null +++ b/gcc/config/i386/driver-i386.c @@ -0,0 +1,174 @@ +/* Subroutines for the gcc driver. + Copyright (C) 2006 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to +the Free Software Foundation, 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. */ + +#include "config.h" +#include "system.h" +#include + +#ifndef CROSS_COMPILE +/* This file shouldn't even be included in a cross compiler, but + let's be sure. */ +extern const char *host_detect_local_cpu (int argc, const char **argv); + +#ifdef GCC_VERSION +#define cpuid(num,a,b,c,d) \ + asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (num)) + +#define bit_CMPXCHG8B (1 << 8) +#define bit_CMOV (1 << 15) +#define bit_MMX (1 << 23) +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +#define bit_SSE3 (1 << 0) +#define bit_CMPXCHG16B (1 << 13) + +#define bit_3DNOW (1 << 31) +#define bit_3DNOWP (1 << 30) +#define bit_LM (1 << 29) + +/* This will be called by the spec parser in gcc.c when it sees + a %:local_cpu_detect(args) construct. Currently it will be called + with either "arch" or "tune" as argument depending on if -march=native + or -mtune=native is to be substituted. + + It returns a string containing new command line parameters to be + put at the place of the above two options, depending on what CPU + this is executed. E.g. "-march=k8" on an AMD64 machine + for -march=native. + + ARGC and ARGV are set depending on the actual arguments given + in the spec. */ +const char *host_detect_local_cpu (int argc, const char **argv) +{ + const char *cpu = "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 is_amd = 0; + unsigned int family = 0; + if (argc < 1 + || (strcmp (argv[0], "arch") + && strcmp (argv[0], "tune"))) + return NULL; + +#ifndef __x86_64__ + /* See if we can use cpuid. */ + asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;" + "pushl %0; popfl; pushfl; popl %0; popfl" + : "=&r" (eax), "=&r" (ebx) + : "i" (0x00200000)); + + if (((eax ^ ebx) & 0x00200000) == 0) + goto done; +#endif + + cpu = "i586"; + + /* Check the highest input value for eax. */ + cpuid (0, eax, ebx, ecx, edx); + max_level = eax; + /* We only look at the first four characters. */ + vendor = ebx; + if (max_level == 0) + goto done; + + cpuid (1, eax, ebx, ecx, edx); + 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); + /* We don't care for extended family. */ + family = (eax >> 8) & ~(1 << 4); + + cpuid (0x80000000, eax, ebx, ecx, edx); + ext_level = eax; + if (ext_level >= 0x80000000) + { + cpuid (0x80000001, eax, ebx, ecx, edx); + has_3dnow = !!(edx & bit_3DNOW); + has_3dnowp = !!(edx & bit_3DNOWP); + has_longmode = !!(edx & bit_LM); + } + + is_amd = vendor == *(unsigned int*)"Auth"; + + if (is_amd) + { + if (has_mmx) + cpu = "k6"; + if (has_3dnow) + cpu = "k6-3"; + if (has_3dnowp) + cpu = "athlon"; + if (has_sse) + cpu = "athlon-4"; + if (has_sse2 || has_longmode) + cpu = "k8"; + } + else + { + if (family == 5) + { + if (has_mmx) + cpu = "pentium-mmx"; + } + else if (has_mmx) + cpu = "pentium2"; + if (has_sse) + cpu = "pentium3"; + if (has_sse2) + { + if (family == 6) + /* It's a pentiumpro with sse2 --> pentium-m */ + cpu = "pentium-m"; + else + /* Would have to look at extended family, but it's at least + an pentium4 core. */ + cpu = "pentium4"; + } + if (has_sse3) + { + if (has_longmode) + cpu = "nocona"; + else + cpu = "prescott"; + } + } + +done: + return concat ("-m", argv[0], "=", cpu, NULL); +} +#else +/* If we aren't compiling with GCC we just provide a minimal + default value. */ +const char *host_detect_local_cpu (int argc, const char **argv) +{ + return concat ("-m", argv[0], "=i386", NULL); +} +#endif +#endif diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index df5a4e68d43..c81dee81152 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1565,7 +1565,11 @@ override_options (void) if (ix86_tune_string) { if (!strcmp (ix86_tune_string, "generic") - || !strcmp (ix86_tune_string, "i686")) + || !strcmp (ix86_tune_string, "i686") + /* As special support for cross compilers we read -mtune=native + as -mtune=generic. With native compilers we won't see the + -mtune=native, as it was changed by the driver. */ + || !strcmp (ix86_tune_string, "native")) { if (TARGET_64BIT) ix86_tune_string = "generic64"; diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b7839138065..a3a1129a5e3 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -273,6 +273,14 @@ extern int x86_prefetch_sse; #define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \ optimization_options ((LEVEL), (SIZE)) +/* -march=native handling only makes sense with a native compiler. */ +#ifndef CROSS_COMPILE +/* In driver-i386.c. */ +extern const char *host_detect_local_cpu (int argc, const char **argv); +#define EXTRA_SPEC_FUNCTIONS \ + { "local_cpu_detect", host_detect_local_cpu }, +#endif + /* Support for configure-time defaults of some command line options. */ #define OPTION_DEFAULT_SPECS \ {"arch", "%{!march=*:-march=%(VALUE)}"}, \ @@ -282,7 +290,7 @@ extern int x86_prefetch_sse; /* Specs for the compiler proper */ #ifndef CC1_CPU_SPEC -#define CC1_CPU_SPEC "\ +#define CC1_CPU_SPEC_1 "\ %{!mtune*: \ %{m386:mtune=i386 \ %n`-m386' is deprecated. Use `-march=i386' or `-mtune=i386' instead.\n} \ @@ -299,6 +307,14 @@ extern int x86_prefetch_sse; %n`-mintel-syntax' is deprecated. Use `-masm=intel' instead.\n} \ %{mno-intel-syntax:-masm=att \ %n`-mno-intel-syntax' is deprecated. Use `-masm=att' instead.\n}" + +#ifdef CROSS_COMPILE +#define CC1_CPU_SPEC CC1_CPU_SPEC_1 +#else +#define CC1_CPU_SPEC CC1_CPU_SPEC_1 \ +"%{march=native:%