* [RFC] PowerPC processor and cache detection
@ 2007-08-06 20:45 David Edelsohn
2007-08-06 20:59 ` Andrew Pinski
2007-08-07 14:35 ` Michael Matz
0 siblings, 2 replies; 3+ messages in thread
From: David Edelsohn @ 2007-08-06 20:45 UTC (permalink / raw)
To: gcc-patches
The appended patch implements -mcpu=native detecting the processor
and cache on AIX, Darwin and Linux. Unfortunately, PPC Linux does not
communicate any cache information, so it only selects the processor.
I am not sure whether to protect the Linux code with __ELF__ or
with __linux.
David
* config/rs6000/x-rs6000: New file.
* config/rs6000/darwin.h (CC1_SPEC): Add cc1_cpu.
* config/rs6000/rs6000.h (EXTRA_SPECS): Add cc1_cpu.
(EXTRA_SPEC_FUNCTIONS): Define.
(HAVE_LOCAL_CPU_DETECT): Define.
(CC1_CPU_SPEC): Define.
* config/rs6000/driver-rs6000.c: New file.
* config/rs6000/aix.h (CC1_SPEC): Define.
* config/rs6000/sysv4.h (CC1_SPEC): Add cc1_cpu.
* config.host: Add x-rs6000 to host_xmake_file if host and target
are rs6000 or powerpc.
Index: x-rs6000
===================================================================
--- x-rs6000 (revision 0)
+++ x-rs6000 (revision 0)
@@ -0,0 +1,3 @@
+driver-rs6000.o : $(srcdir)/config/rs6000/driver-rs6000.c \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
Index: darwin.h
===================================================================
--- darwin.h (revision 127241)
+++ darwin.h (working copy)
@@ -90,6 +90,7 @@
the kernel or some such. */
#define CC1_SPEC "\
+ %(cc1_cpu) \
%{g: %{!fno-eliminate-unused-debug-symbols: -feliminate-unused-debug-symbols }} \
%{static: %{Zdynamic: %e conflicting code gen style switches are used}}\
%{!mmacosx-version-min=*:-mmacosx-version-min=%(darwin_minversion)} \
Index: rs6000.h
===================================================================
--- rs6000.h (revision 127241)
+++ rs6000.h (working copy)
@@ -135,8 +135,26 @@
{ "cpp_default", CPP_DEFAULT_SPEC }, \
{ "asm_cpu", ASM_CPU_SPEC }, \
{ "asm_default", ASM_DEFAULT_SPEC }, \
+ { "cc1_cpu", CC1_CPU_SPEC }, \
SUBTARGET_EXTRA_SPECS
+/* -mcpu=native handling only makes sense with compiler running on
+ an PowerPC chip. If changing this condition, also change
+ the condition in driver-rs6000.c. */
+#if defined(__powerpc__) || defined(__POWERPC__) || defined(_AIX)
+/* In driver-rs6000.c. */
+extern const char *host_detect_local_cpu (int argc, const char **argv);
+#define EXTRA_SPEC_FUNCTIONS \
+ { "local_cpu_detect", host_detect_local_cpu },
+#define HAVE_LOCAL_CPU_DETECT
+#endif
+
+#if !defined (CC1_CPU_SPEC) && defined (HAVE_LOCAL_CPU_DETECT)
+#define CC1_CPU_SPEC \
+"%{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)} \
+ %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
+#endif
+
/* Architecture type. */
/* Define TARGET_MFCRF if the target assembler does not support the
Index: driver-rs6000.c
===================================================================
--- driver-rs6000.c (revision 0)
+++ driver-rs6000.c (revision 0)
@@ -0,0 +1,388 @@
+/* Subroutines for the gcc driver.
+ Copyright (C) 2007 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 3, 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 COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include <stdlib.h>
+
+#ifdef _AIX
+# include <sys/systemcfg.h>
+#endif
+
+#ifdef __ELF__
+# include <elf.h>
+#endif
+
+#ifdef __APPLE__
+# include <sys/types.h>
+# include <sys/sysctl.h>
+#endif
+
+const char *host_detect_local_cpu (int argc, const char **argv);
+
+#ifdef GCC_VERSION
+
+/* Returns parameters that describe L1_ASSOC associative cache of size
+ L1_SIZEKB with lines of size L1_LINE. */
+
+static char *
+describe_cache (unsigned l1_sizekb, unsigned l1_line,
+ unsigned l1_assoc ATTRIBUTE_UNUSED, unsigned l2_sizekb)
+{
+ char l1size[1000], line[1000], l2size;
+
+ /* At the moment, gcc middle-end does not use the information about the
+ associativity of the cache. */
+
+ sprintf (l1size, "--param l1-cache-size=%u", l1_sizekb);
+ sprintf (line, "--param l1-cache-line-size=%u", l1_line);
+ sprintf (l2size, "--param l2-cache-size=%u", l2_sizekb);
+
+ return concat (l1size, " ", line, " ", l2size, " ", NULL);
+}
+
+#ifdef __APPLE__
+
+/* Returns the description of caches on Linux. */
+
+static char *
+detect_caches_darwin (void)
+{
+ unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+ size_t len = 4;
+ static int l1_line_name[2] = { CTL_HW, HW_CACHELINE };
+ static int l1_size_name[2] = { CTL_HW, HW_L1DCACHESIZE };
+ static int l2_size_name[2] = { CTL_HW, HW_L2CACHESIZE };
+
+ sysctl (l1_size_name, 2, &l1_sizekb, &len, NULL, 0);
+ sysctl (l1_line_name, 2, &l1_line, &len, NULL, 0);
+ sysctl (l2_size_name, 2, &l2_sizekb, &len, NULL, 0);
+ l1_assoc = 0;
+
+ return describe_cache (l1_sizekb / 1024, l1_line, l1_assoc,
+ l2_sizekb / 1024);
+}
+
+static char *
+detect_processor_darwin (void)
+{
+ unsigned int proc;
+ size_t len = 4;
+
+ sysctlbyname ("hw.cpusubtype", &proc, &len, NULL, 0);
+
+ if (len > 0)
+ switch (proc)
+ {
+ case 1:
+ return "601";
+ case 2:
+ return "602";
+ case 3:
+ return "603";
+ case 4:
+ case 5:
+ return "603e";
+ case 6:
+ return "604";
+ case 7:
+ return "604e";
+ case 8:
+ return "620";
+ case 9:
+ return "750";
+ case 10:
+ return "7400";
+ case 11:
+ return "7450";
+ case 100:
+ return "970";
+ default:
+ gcc_unreachable ();
+ }
+
+ return "powerpc";
+}
+
+#endif
+
+#ifdef __ELF__
+
+/* Returns AT_PLATFORM if present, otherwise generic PowerPC. */
+
+static char *
+elf_platform (void)
+{
+ int fd;
+
+ fd = open ("/proc/self/auxv", O_RDONLY);
+
+ if (fd != -1)
+ {
+ char buf[1024];
+ Elf32_auxv_t *av;
+ ssize_t n;
+
+ n = read (fd, buf, sizeof (buf));
+ close (fd);
+
+ if (n > 0)
+ {
+ for (av = (Elf32_auxv_t *) buf; av->a_type != AT_NULL; ++av)
+ switch (av->a_type)
+ {
+ case AT_PLATFORM:
+ return (char *) av->a_un.a_val;
+
+ default:
+ break;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* Returns AT_PLATFORM if present, otherwise generic 32. */
+
+static int
+elf_dcachebsize (void)
+{
+ int fd;
+
+ fd = open ("/proc/self/auxv", O_RDONLY);
+
+ if (fd != -1)
+ {
+ char buf[1024];
+ Elf32_auxv_t *av;
+ ssize_t n;
+
+ n = read (fd, buf, sizeof (buf));
+ close (fd);
+
+ if (n > 0)
+ {
+ for (av = (Elf32_auxv_t *) buf; av->a_type != AT_NULL; ++av)
+ switch (av->a_type)
+ {
+ case AT_DCACHEBSIZE:
+ return av->a_un.a_val;
+
+ default:
+ break;
+ }
+ }
+ }
+ return 32;
+}
+
+/* Returns the description of caches on Linux. */
+
+static char *
+detect_caches_linux (void)
+{
+ unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+ char *platform;
+
+ platform = elf_platform ();
+
+ if (platform != NULL)
+ {
+ l1_line = 128;
+
+ if (platform[5] == '6')
+ /* POWER6 and POWER6x */
+ l1_sizekb = 64;
+ else
+ l1_sizekb = 32;
+ }
+ else
+ {
+ l1_line = elf_dcachebsize ();
+ l1_sizekb = 32;
+ }
+
+ l1_assoc = 0;
+ l2_sizekb = 512;
+
+ return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
+}
+
+static char *
+detect_processor_linux (void)
+{
+ char *platform;
+
+ platform = elf_platform ();
+
+ if (platform != NULL)
+ return platform;
+ else
+ return "powerpc";
+}
+
+#endif /* __ELF__ */
+
+#ifdef _AIX
+/* Returns the description of caches on AIX. */
+
+static char *
+detect_caches_aix (void)
+{
+ unsigned l1_sizekb, l1_line, l1_assoc, l2_sizekb;
+
+ l1_line = _system_configuration.dcache_line;
+ l1_sizekb = _system_configuration.dcache_size / 1024;
+ l1_assoc = _system_configuration.dcache_asc;
+ l2_sizekb = _system_configuration.L2_cache_size / 1024;
+
+ return describe_cache (l1_sizekb, l1_line, l1_assoc, l2_sizekb);
+}
+
+
+/* Returns the processor implementation on AIX. */
+
+static char *
+detect_processor_aix (void)
+{
+ switch (_system_configuration.implementation)
+ {
+ case POWER_RS1:
+ return "rios1";
+
+ case POWER_RSC:
+ return "rsc";
+
+ case POWER_RS2:
+ return "rios2";
+
+ case POWER_601:
+ return "601";
+
+ case POWER_603:
+ return "603";
+
+ case POWER_604:
+ return "604";
+
+ case POWER_620:
+ return "620";
+
+ case POWER_630:
+ return "630";
+
+ case POWER_A35:
+ case POWER_RS64II:
+ case POWER_RS64III:
+ return "rs64";
+
+ case POWER_4:
+ return "power4";
+
+ case POWER_5:
+ if (_system_configuration.version == PV_5)
+ return "power5";
+ else
+ return "power5+";
+
+ case POWER_6:
+ return "power6";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+#endif /* _AIX */
+
+
+/* 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.
+
+ 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 = NULL;
+ const char *cache = "";
+ const char *options = "";
+ bool arch;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "cpu") == 0;
+ if (!arch && strcmp (argv[0], "tune"))
+ return NULL;
+
+#if defined (_AIX)
+ cache = detect_caches_aix ();
+#elif defined (__APPLE__)
+ cache = detect_caches_darwin ();
+#elif defined (__ELF__)
+ /* cache = detect_caches_linux (); */
+#else
+#error unsupported OS
+#endif
+
+#if defined (_AIX)
+ cpu = detect_processor_aix ();
+#elif defined (__APPLE__)
+ cpu = detect_processor_darwin ();
+#elif defined (__ELF__)
+ cpu = detect_processor_linux ();
+#else
+#error unsupported OS
+#endif
+
+ return concat (cache, "-m", argv[0], "=", cpu, " ", options, NULL);
+}
+
+#else /* GCC_VERSION */
+
+/* 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)
+{
+ const char *cpu;
+ bool arch;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "cpu") == 0;
+ if (!arch && strcmp (argv[0], "tune"))
+ return NULL;
+
+ if (arch)
+ cpu = "powerpc";
+
+ return concat ("-m", argv[0], "=", cpu, NULL);
+}
+
+#endif /* GCC_VERSION */
+
Index: aix.h
===================================================================
--- aix.h (revision 127241)
+++ aix.h (working copy)
@@ -109,6 +109,8 @@
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
%{ansi: -D_ANSI_C_SOURCE}"
+#define CC1_SPEC "%(cc1_cpu)"
+
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC ""
Index: sysv4.h
===================================================================
--- sysv4.h (revision 127241)
+++ sysv4.h (working copy)
@@ -607,7 +607,7 @@
#endif
/* Pass -G xxx to the compiler and set correct endian mode. */
-#define CC1_SPEC "%{G*} \
+#define CC1_SPEC "%{G*} %(cc1_cpu) \
%{mlittle|mlittle-endian: %(cc1_endian_little); \
mbig |mbig-endian : %(cc1_endian_big); \
mcall-aixdesc | \
Index: config.host
===================================================================
--- config.host (revision 127165)
+++ config.host (working copy)
@@ -106,6 +106,19 @@
;;
esac
+case ${host} in
+ rs6000-*-* \
+ | powerpc*-*-* )
+ case ${target} in
+ rs6000-*-* \
+ | powerpc*-*-* )
+ host_extra_gcc_objs="driver-rs6000.o"
+ host_xmake_file="${host_xmake_file} rs6000/x-rs6000"
+ ;;
+ esac
+ ;;
+esac
+
# Machine-specific settings.
case ${host} in
alpha*-dec-*vms*)
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] PowerPC processor and cache detection
2007-08-06 20:45 [RFC] PowerPC processor and cache detection David Edelsohn
@ 2007-08-06 20:59 ` Andrew Pinski
2007-08-07 14:35 ` Michael Matz
1 sibling, 0 replies; 3+ messages in thread
From: Andrew Pinski @ 2007-08-06 20:59 UTC (permalink / raw)
To: David Edelsohn; +Cc: gcc-patches
On 8/6/07, David Edelsohn <dje@watson.ibm.com> wrote:
> The appended patch implements -mcpu=native detecting the processor
> and cache on AIX, Darwin and Linux. Unfortunately, PPC Linux does not
> communicate any cache information, so it only selects the processor.
>
> I am not sure whether to protect the Linux code with __ELF__ or
> with __linux.
>
> +#ifdef GCC_VERSION
Even though I know this is copied from driver-i386.c, it is wrong (PR
32787 records that bug). GCC_VERSION is always defined via
ansidecl.h:
#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif /* GCC_VERSION */
It would be better if you did:
#if GCC_VERSION >= 0
Thanks,
Andrew Pinski
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC] PowerPC processor and cache detection
2007-08-06 20:45 [RFC] PowerPC processor and cache detection David Edelsohn
2007-08-06 20:59 ` Andrew Pinski
@ 2007-08-07 14:35 ` Michael Matz
1 sibling, 0 replies; 3+ messages in thread
From: Michael Matz @ 2007-08-07 14:35 UTC (permalink / raw)
To: David Edelsohn; +Cc: gcc-patches
Hi,
On Mon, 6 Aug 2007, David Edelsohn wrote:
> I am not sure whether to protect the Linux code with __ELF__ or
> with __linux.
I think __linux, as /proc/self/auxv is a linux'ism, not something to do
with ELF.
Ciao,
Michael.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2007-08-07 14:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-08-06 20:45 [RFC] PowerPC processor and cache detection David Edelsohn
2007-08-06 20:59 ` Andrew Pinski
2007-08-07 14:35 ` Michael Matz
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).