summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config.host13
-rw-r--r--gcc/config/i386/driver-i386.c174
-rw-r--r--gcc/config/i386/i386.c6
-rw-r--r--gcc/config/i386/i386.h18
-rw-r--r--gcc/config/i386/x-i3863
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/gcc.c3
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 }
};