diff options
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config.host | 13 | ||||
-rw-r--r-- | gcc/config/i386/driver-i386.c | 174 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 6 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 18 | ||||
-rw-r--r-- | gcc/config/i386/x-i386 | 3 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 7 | ||||
-rw-r--r-- | gcc/gcc.c | 3 |
8 files changed, 237 insertions, 3 deletions
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 <matz@suse.de> + + * config.host (<i[34567]86-*-*, x86_64-*-*>): 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 (<i386 and x86-64 Options>): Describe + cpu-type "native". + 2006-05-09 Dirk Mueller <dmueller@suse.de> Richard Guenther <rguenther@suse.de> 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 <stdlib.h> + +#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:%<march=native %:local_cpu_detect(arch)} \ +%{mtune=native:%<mtune=native %:local_cpu_detect(tune)}" +#endif #endif /* Target CPU builtins. */ diff --git a/gcc/config/i386/x-i386 b/gcc/config/i386/x-i386 new file mode 100644 index 00000000000..2c35e5b5aed --- /dev/null +++ b/gcc/config/i386/x-i386 @@ -0,0 +1,3 @@ +driver-i386.o : $(srcdir)/config/i386/driver-i386.c \ + $(CONFIG_H) $(SYSTEM_H) + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 71c69255210..bf1fe7cf87c 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -9176,6 +9176,13 @@ indicates the instruction set the compiler can use, and there is no generic instruction set applicable to all processors. In contrast, @option{-mtune} indicates the processor (or, in this case, collection of processors) for which the code is optimized. +@item native +This selects the CPU to tune for at compilation time by determining +the processor type of the compiling machine. Using @option{-mtune=native} +will produce code optimized for the local machine under the constraints +of the selected instruction set. Using @option{-march=native} will +enable all instruction subsets supported by the local machine (hence +the result might not run on different machines). @item i386 Original Intel's i386 CPU@. @item i486 diff --git a/gcc/gcc.c b/gcc/gcc.c index 4b628ef4384..7e5733cc75a 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -1601,6 +1601,9 @@ static const struct spec_function static_spec_functions[] = { "replace-outfile", replace_outfile_spec_function }, { "version-compare", version_compare_spec_function }, { "include", include_spec_function }, +#ifdef EXTRA_SPEC_FUNCTIONS + EXTRA_SPEC_FUNCTIONS +#endif { 0, 0 } }; |