[PATCH][ARM] -m{cpu,tune,arch}=native

Richard Earnshaw rearnsha@arm.com
Fri Sep 9 12:48:00 GMT 2011


On 06/09/11 14:35, Andrew Stubbs wrote:
> This update adds many more "magic numbers" for various ARM CPUs, and 
> also ensures that the implementer is ARM (as opposed to Marvell, etc.). 
> The list is far from comprehensive, but it should cover many (but by no 
> means all) of the cores in current use and it would not be hard to add 
> support for other implementers and CPU names in future.
> 
> It has been suggested that this patch should use auxv rather than 
> /proc/cpuinfo. Does anybody here have any insight/preferences?
> 
> Is the patch OK?
> 
> Andrew
> 
> 
> tune-native.patch
> 
> 
> 2011-08-27  Andrew Stubbs  <ams@codesourcery.com>
> 
> 	gcc/
> 	* config.host (arm*-*-linux*): Add driver-arm.o and x-arm.
> 	* config/arm/arm.opt: Add 'native' processor_type and
> 	arm_arch enum values.
> 	* config/arm/arm.h (host_detect_local_cpu): New prototype.
> 	(EXTRA_SPEC_FUNCTIONS): New define.
> 	(MCPU_MTUNE_NATIVE_SPECS): New define.
> 	(DRIVER_SELF_SPECS): New define.
> 	* config/arm/driver-arm.c: New file.
> 	* config/arm/x-arm: New file.
> 	* doc/invoke.texi (ARM Options): Document -mcpu=native,
> 	-mtune=native and -march=native.
> 

The part number field is meaningless outside of the context of a a
specific vendor -- only taken as a pair can they refer to a specific
part.  So why is the vendor field hard-coded rather than factored into
the table of parts.

Maybe it would be better to have a table of tables, with the top-level
table being indexed by vendor id.  Something like

struct vendor_cpu {
  const char *part_no;
  const char *arch_name;
  const char *cpu_name;
};

struct all_cpus {
  const char *vendor_no;
  const struct vendor_cpu *vendor_parts;
}

struct vendor_cpu vendor_arm[] = { ... }

Now your code will allow easy addition of third-party cores.

R.

> --- a/gcc/config.host
> +++ b/gcc/config.host
> @@ -100,6 +100,14 @@ case ${host} in
>  esac
>  
>  case ${host} in
> +  arm*-*-linux*)
> +    case ${target} in
> +      arm*-*-*)
> +	host_extra_gcc_objs="driver-arm.o"
> +	host_xmake_file="${host_xmake_file} arm/x-arm"
> +	;;
> +    esac
> +    ;;
>    alpha*-*-linux* | alpha*-dec-osf*)
>      case ${target} in
>        alpha*-*-linux* | alpha*-dec-osf*)
> --- a/gcc/config/arm/arm.h
> +++ b/gcc/config/arm/arm.h
> @@ -2223,4 +2223,21 @@ extern int making_const_table;
>     instruction.  */
>  #define MAX_LDM_STM_OPS 4
>  
> +/* -mcpu=native handling only makes sense with compiler running on
> +   an ARM chip.  */
> +#if defined(__arm__)
> +extern const char *host_detect_local_cpu (int argc, const char **argv);
> +# define EXTRA_SPEC_FUNCTIONS						\
> +  { "local_cpu_detect", host_detect_local_cpu },
> +
> +# define MCPU_MTUNE_NATIVE_SPECS					\
> +   " %{march=native:%<march=native %:local_cpu_detect(arch)}"		\
> +   " %{mcpu=native:%<mcpu=native %:local_cpu_detect(cpu)}"		\
> +   " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}"
> +#else
> +# define MCPU_MTUNE_NATIVE_SPECS ""
> +#endif
> +
> +#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS
> +
>  #endif /* ! GCC_ARM_H */
> --- a/gcc/config/arm/arm.opt
> +++ b/gcc/config/arm/arm.opt
> @@ -80,6 +80,11 @@ march=
>  Target RejectNegative Joined Enum(arm_arch) Var(arm_arch_option)
>  Specify the name of the target architecture
>  
> +; Other arm_arch values are loaded from arm-tables.opt
> +; but that is a generated file and this is an odd-one-out.
> +EnumValue
> +Enum(arm_arch) String(native) Value(-1) DriverOnly
> +
>  marm
>  Target Report RejectNegative InverseMask(THUMB)
>  Generate code in 32 bit ARM state.
> @@ -233,6 +238,11 @@ mtune=
>  Target RejectNegative Joined Enum(processor_type) Var(arm_tune_option) Init(arm_none)
>  Tune code for the given processor
>  
> +; Other processor_type values are loaded from arm-tables.opt
> +; but that is a generated file and this is an odd-one-out.
> +EnumValue
> +Enum(processor_type) String(native) Value(-1) DriverOnly
> +
>  mwords-little-endian
>  Target Report RejectNegative Mask(LITTLE_WORDS)
>  Assume big endian bytes, little endian words.  This option is deprecated.
> --- /dev/null
> +++ b/gcc/config/arm/driver-arm.c
> @@ -0,0 +1,108 @@
> +/* Subroutines for the gcc driver.
> +   Copyright (C) 2011 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"
> +
> +static struct {
> +  const char *part_no;
> +  const char *arch_name;
> +  const char *cpu_name;
> +} cpu_table[] = {
> +    {"0x926", "armv5te", "arm926ej-s"},
> +    {"0xa26", "armv5te", "arm1026ej-s"},
> +    {"0xb02", "armv6k", "mpcore"},
> +    {"0xb36", "armv6j", "arm1136j-s"},
> +    {"0xb56", "armv6t2", "arm1156t2-s"},
> +    {"0xb76", "armv6zk", "arm1176jz-s"},
> +    {"0xc05", "armv7-a", "cortex-a5"},
> +    {"0xc08", "armv7-a", "cortex-a8"},
> +    {"0xc09", "armv7-a", "cortex-a9"},
> +    {"0xc0f", "armv7-a", "cortex-a15"},
> +    {"0xc14", "armv7-r", "cortex-r4"},
> +    {"0xc15", "armv7-r", "cortex-r5"},
> +    {"0xc20", "armv6-m", "cortex-m0"},
> +    {"0xc21", "armv6-m", "cortex-m1"},
> +    {"0xc23", "armv7-m", "cortex-m3"},
> +    {"0xc24", "armv7e-m", "cortex-m4"},
> +    {NULL, NULL, NULL}
> +};
> +
> +/* 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", "cpu" or "tune" as argument depending on if
> +   -march=native, -mcpu=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=armv7-a" on a Cortex-A8 for
> +   -march=native.  If the routine can't detect a known processor,
> +   the -march or -mtune option is discarded.
> +
> +   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 *val = NULL;
> +  char buf[128];
> +  FILE *f;
> +  bool arch;
> +
> +  if (argc < 1)
> +    return NULL;
> +
> +  arch = strcmp (argv[0], "arch") == 0;
> +  if (!arch && strcmp (argv[0], "cpu") != 0 && strcmp (argv[0], "tune"))
> +    return NULL;
> +
> +  f = fopen ("/proc/cpuinfo", "r");
> +  if (f == NULL)
> +    return NULL;
> +
> +  while (fgets (buf, sizeof (buf), f) != NULL)
> +    {
> +      /* Ensure that CPU implementer is ARM (0x41).  */
> +      if (strncmp (buf, "CPU implementer", sizeof ("CPU implementer") - 1) == 0
> +	  && strstr (buf, "0x41") == NULL)
> +	return NULL;
> +
> +      /* Detect arch/cpu.  */
> +      if (strncmp (buf, "CPU part", sizeof ("CPU part") - 1) == 0)
> +	{
> +	  int i;
> +	  for (i = 0; cpu_table[i].part_no != NULL; i++)
> +	    if (strstr (buf, cpu_table[i].part_no) != NULL)
> +	      {
> +		val = arch ? cpu_table[i].arch_name : cpu_table[i].cpu_name;
> +		break;
> +	      }
> +	  break;
> +	}
> +    }
> +
> +  fclose (f);
> +
> +  if (val == NULL)
> +    return NULL;
> +
> +  return concat ("-m", argv[0], "=", val, NULL);
> +}
> --- /dev/null
> +++ b/gcc/config/arm/x-arm
> @@ -0,0 +1,3 @@
> +driver-arm.o: $(srcdir)/config/arm/driver-arm.c \
> +  $(CONFIG_H) $(SYSTEM_H)
> +	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -10319,6 +10319,11 @@ assembly code.  Permissible names are: @samp{arm2}, @samp{arm250},
>  @samp{fa526}, @samp{fa626},
>  @samp{fa606te}, @samp{fa626te}, @samp{fmp626}, @samp{fa726te}.
>  
> +@option{-mcpu=native} causes the compiler to auto-detect the CPU
> +of the build computer.  At present, this feature is only supported on
> +Linux, and not all architectures are recognised.  If the auto-detect is
> +unsuccessful the option has no effect.
> +
>  @item -mtune=@var{name}
>  @opindex mtune
>  This option is very similar to the @option{-mcpu=} option, except that
> @@ -10330,6 +10335,11 @@ will generate based on the CPU specified by a @option{-mcpu=} option.
>  For some ARM implementations better performance can be obtained by using
>  this option.
>  
> +@option{-mtune=native} causes the compiler to auto-detect the CPU
> +of the build computer.  At present, this feature is only supported on
> +Linux, and not all architectures are recognised.  If the auto-detect is
> +unsuccessful the option has no effect.
> +
>  @item -march=@var{name}
>  @opindex march
>  This specifies the name of the target ARM architecture.  GCC uses this
> @@ -10343,6 +10353,11 @@ of the @option{-mcpu=} option.  Permissible names are: @samp{armv2},
>  @samp{armv7}, @samp{armv7-a}, @samp{armv7-r}, @samp{armv7-m},
>  @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
>  
> +@option{-march=native} causes the compiler to auto-detect the architecture
> +of the build computer.  At present, this feature is only supported on
> +Linux, and not all architectures are recognised.  If the auto-detect is
> +unsuccessful the option has no effect.
> +
>  @item -mfpu=@var{name}
>  @itemx -mfpe=@var{number}
>  @itemx -mfp=@var{number}



More information about the Gcc-patches mailing list