Subject:Support for Runtime CPU type detection via builtins

Hi,

   I have uploaded a new patch to only have two builtins :

* __builtin_cpu_is ("<CPUNAME>")
* __builtin_cpu_supports ("<FEATURE>")

apart from the cpu init builtin, __builtin_cpu_init.

List of CPU names :

* "amd"
* "intel"
* "atom"
* "core2"
* "corei7"
* "nehalem"
* "westmere"
* "sandybridge"
* "amdfam10h"
* "barcelona"
* "shanghai"
* "istanbul"
* "bdver1"
* "bdver2"

List of CPU features :

* "cmov"
* "mmx"
* "popcnt"
* "sse"
* "sse2"
* "sse3"
* "ssse3"
* "sse4.1"
* "sse4.2"

As an example, to check if CPU is corei7, call __builtin_cpu_is ("corei7")

Comments?
Thanks.

On Mon, Mar 12, 2012 at 4:16 AM, Richard Guenther
<richard.guent...@gmail.com> wrote:
> On Thu, Mar 8, 2012 at 9:35 PM, Xinliang David Li <davi...@google.com> wrote:
>> On Wed, Mar 7, 2012 at 5:51 AM, Richard Guenther
>> <richard.guent...@gmail.com> wrote:
>>> On Wed, Mar 7, 2012 at 1:49 AM, Sriraman Tallam <tmsri...@google.com> wrote:
>>>> Patch for CPU detection at run-time.
>>>> ===================================
>>>>
>>>> Patch for CPU detection at run-time, to be used in dispatching of
>>>> multi-versioned functions.   Please see this discussion:
>>>> http://gcc.gnu.org/ml/gcc-patches/2011-08/msg01355.html
>>>> when this patch for reviewed the last time.
>>>>
>>>> For more detailed description:
>>>> http://gcc.gnu.org/ml/gcc/2012-03/msg00074.html
>>>>
>>>> One of the main concerns was about making CPU detection initialization a
>>>> constructor. The main point raised was about constructor ordering. I have
>>>> added a priority value to the CPU detection constructor to make it very 
>>>> high
>>>> priority so that it is guaranteed to fire before every constructor without
>>>> an explicitly marked priority value of 101.  However, IFUNC initializers
>>>> will still fire before this constructor, so the cpu initialization routine
>>>> has to be explicitly called in such initializers for which I have added a
>>>> builtin: __builtin_cpu_init ().
>>>>
>>>> This patch adds the following new builtins:
>>>>
>>>> * __builtin_cpu_init
>>>> * __builtin_cpu_supports_cmov
>>>> * __builtin_cpu_supports_mmx
>>>> * __builtin_cpu_supports_popcount
>>>> * __builtin_cpu_supports_sse
>>>> * __builtin_cpu_supports_sse2
>>>> * __builtin_cpu_supports_sse3
>>>> * __builtin_cpu_supports_ssse3
>>>> * __builtin_cpu_supports_sse4_1
>>>> * __builtin_cpu_supports_sse4_2
>>>> * __builtin_cpu_is_amd
>>>> * __builtin_cpu_is_intel_atom
>>>> * __builtin_cpu_is_intel_core2
>>>> * __builtin_cpu_is_intel
>>>> * __builtin_cpu_is_intel_corei7
>>>> * __builtin_cpu_is_intel_corei7_nehalem
>>>> * __builtin_cpu_is_intel_corei7_westmere
>>>> * __builtin_cpu_is_intel_corei7_sandybridge
>>>> * __builtin_cpu_is_amdfam10
>>>> * __builtin_cpu_is_amdfam10_barcelona
>>>> * __builtin_cpu_is_amdfam10_shanghai
>>>> * __builtin_cpu_is_amdfam10_istanbul
>>>> * __builtin_cpu_is_amdfam15_bdver1
>>>> * __builtin_cpu_is_amdfam15_bdver2
>>>
>>> I think the non-feature detection functions are not necessary at all.
>>
>> They are useful if compiler needs to do auto versioning based on cpu model.
>>
>>> Builtin functions are not exactly cheap, nor is the scheme you invent
>>> backward/forward compatible.  Instead, why not add a single builtin
>>> function, __builtin_cpu_supports(const char *), and decode from
>>> a comma-separated list of features?  Unknown features are simply
>>> "not present".  So I can write code with only a single configure check,
>>
>> This is a good idea.
>>
>> __builtin_is_cpu (const char* );
>> __builtin_cpu_supports (char char*);
>
> That looks good to me.
>
> Richard.
>
>> thanks,
>>
>> David
>>
>>
>>> for __builtin_cpu_supports, and cater for future features or older 
>>> compilers.
>>>
>>> And of course that builtin would be even cross-platform.
>>>
>>> Implementation-wise I'll leave this to x86 maintainers to comment on.
>>>
>>> Richard.
>>>
>>>>
>>>>        * config/i386/i386.c (build_struct_with_one_bit_fields): New 
>>>> function.
>>>>        (make_var_decl): New function.
>>>>        (get_field_from_struct): New function.
>>>>        (fold_builtin_target): New function.
>>>>        (ix86_fold_builtin): New function.
>>>>        (ix86_expand_builtin): Expand new builtins by folding them.
>>>>        (make_platform_builtin): New functions.
>>>>        (ix86_init_platform_type_builtins): Make the new builtins.
>>>>        (ix86_init_builtins): Make new builtins to detect CPU type.
>>>>        (TARGET_FOLD_BUILTIN): New macro.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_CMOV): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_MMX): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_POPCOUNT): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSE): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSE2): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSE3): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSSE3): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSE4_1): New enum value.
>>>>        (IX86_BUILTIN_CPU_SUPPORTS_SSE4_2): New enum value.
>>>>        (IX86_BUILTIN_CPU_INIT): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMD): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL_ATOM): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL_CORE2): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL_COREI7_NEHALEM): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL_COREI7_WESTMERE): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_INTEL_COREI7_SANDYBRIDGE): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMDFAM10_BARCELONA): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMDFAM10_SHANGHAI): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMDFAM10_ISTANBUL): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER1): New enum value.
>>>>        (IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER2): New enum value.
>>>>        * config/i386/i386-builtin-types.def: New function type.
>>>>        * testsuite/gcc.target/builtin_target.c: New testcase.
>>>>
>>>>        * libgcc/config/i386/i386-cpuinfo.c: New file.
>>>>        * libgcc/config/i386/t-cpuinfo: New file.
>>>>        * libgcc/config.host: Include t-cpuinfo.
>>>>        * libgcc/config/i386/libgcc-glibc.ver: Version symbols __cpu_model
>>>>        and __cpu_features.
>>>>
>>>> Index: libgcc/config.host
>>>> ===================================================================
>>>> --- libgcc/config.host  (revision 184971)
>>>> +++ libgcc/config.host  (working copy)
>>>> @@ -1142,7 +1142,7 @@ i[34567]86-*-linux* | x86_64-*-linux* | \
>>>>   i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu | \
>>>>   i[34567]86-*-knetbsd*-gnu | \
>>>>   i[34567]86-*-gnu*)
>>>> -       tmake_file="${tmake_file} t-tls i386/t-linux"
>>>> +       tmake_file="${tmake_file} t-tls i386/t-linux i386/t-cpuinfo"
>>>>        if test "$libgcc_cv_cfi" = "yes"; then
>>>>                tmake_file="${tmake_file} t-stack i386/t-stack-i386"
>>>>        fi
>>>> Index: libgcc/config/i386/t-cpuinfo
>>>> ===================================================================
>>>> --- libgcc/config/i386/t-cpuinfo        (revision 0)
>>>> +++ libgcc/config/i386/t-cpuinfo        (revision 0)
>>>> @@ -0,0 +1 @@
>>>> +LIB2ADD += $(srcdir)/config/i386/i386-cpuinfo.c
>>>> Index: libgcc/config/i386/i386-cpuinfo.c
>>>> ===================================================================
>>>> --- libgcc/config/i386/i386-cpuinfo.c   (revision 0)
>>>> +++ libgcc/config/i386/i386-cpuinfo.c   (revision 0)
>>>> @@ -0,0 +1,306 @@
>>>> +/* Get CPU type and Features for x86 processors.
>>>> +   Copyright (C) 2011 Free Software Foundation, Inc.
>>>> +   Contributed by Sriraman Tallam (tmsri...@google.com)
>>>> +
>>>> +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 "cpuid.h"
>>>> +#include "tsystem.h"
>>>> +
>>>> +int __cpu_indicator_init (void) __attribute__ ((constructor (101)));
>>>> +
>>>> +enum vendor_signatures
>>>> +{
>>>> +  SIG_INTEL =  0x756e6547 /* Genu */,
>>>> +  SIG_AMD =    0x68747541 /* Auth */
>>>> +};
>>>> +
>>>> +/* ISA Features supported. */
>>>> +
>>>> +struct __processor_features
>>>> +{
>>>> +  unsigned int __cpu_cmov : 1;
>>>> +  unsigned int __cpu_mmx : 1;
>>>> +  unsigned int __cpu_popcnt : 1;
>>>> +  unsigned int __cpu_sse : 1;
>>>> +  unsigned int __cpu_sse2 : 1;
>>>> +  unsigned int __cpu_sse3 : 1;
>>>> +  unsigned int __cpu_ssse3 : 1;
>>>> +  unsigned int __cpu_sse4_1 : 1;
>>>> +  unsigned int __cpu_sse4_2 : 1;
>>>> +} __cpu_features;
>>>> +
>>>> +/* Processor Model. */
>>>> +
>>>> +struct __processor_model
>>>> +{
>>>> +  /* Vendor. */
>>>> +  unsigned int __cpu_is_amd : 1;
>>>> +  unsigned int __cpu_is_intel : 1;
>>>> +  /* CPU type. */
>>>> +  unsigned int __cpu_is_intel_atom : 1;
>>>> +  unsigned int __cpu_is_intel_core2 : 1;
>>>> +  unsigned int __cpu_is_intel_corei7 : 1;
>>>> +  unsigned int __cpu_is_intel_corei7_nehalem : 1;
>>>> +  unsigned int __cpu_is_intel_corei7_westmere : 1;
>>>> +  unsigned int __cpu_is_intel_corei7_sandybridge : 1;
>>>> +  unsigned int __cpu_is_amdfam10h : 1;
>>>> +  unsigned int __cpu_is_amdfam10h_barcelona : 1;
>>>> +  unsigned int __cpu_is_amdfam10h_shanghai : 1;
>>>> +  unsigned int __cpu_is_amdfam10h_istanbul : 1;
>>>> +  unsigned int __cpu_is_amdfam15h_bdver1 : 1;
>>>> +  unsigned int __cpu_is_amdfam15h_bdver2 : 1;
>>>> +} __cpu_model;
>>>> +
>>>> +/* Get the specific type of AMD CPU.  */
>>>> +
>>>> +static void
>>>> +get_amd_cpu (unsigned int family, unsigned int model)
>>>> +{
>>>> +  switch (family)
>>>> +    {
>>>> +    /* AMD Family 10h.  */
>>>> +    case 0x10:
>>>> +      switch (model)
>>>> +       {
>>>> +       case 0x2:
>>>> +         /* Barcelona.  */
>>>> +         __cpu_model.__cpu_is_amdfam10h = 1;
>>>> +         __cpu_model.__cpu_is_amdfam10h_barcelona = 1;
>>>> +         break;
>>>> +       case 0x4:
>>>> +         /* Shanghai.  */
>>>> +         __cpu_model.__cpu_is_amdfam10h = 1;
>>>> +         __cpu_model.__cpu_is_amdfam10h_shanghai = 1;
>>>> +         break;
>>>> +       case 0x8:
>>>> +         /* Istanbul.  */
>>>> +         __cpu_model.__cpu_is_amdfam10h = 1;
>>>> +         __cpu_model.__cpu_is_amdfam10h_istanbul = 1;
>>>> +         break;
>>>> +       default:
>>>> +         break;
>>>> +       }
>>>> +      break;
>>>> +    /* AMD Family 15h.  */
>>>> +    case 0x15:
>>>> +      /* Bulldozer version 1.  */
>>>> +      if (model >= 0 && model <= 0xf)
>>>> +        __cpu_model.__cpu_is_amdfam15h_bdver1 = 1;
>>>> +      /* Bulldozer version 2.  */
>>>> +      if (model >= 0x10 && model <= 0x1f)
>>>> +        __cpu_model.__cpu_is_amdfam15h_bdver2 = 1;
>>>> +      break;
>>>> +    default:
>>>> +      break;
>>>> +    }
>>>> +}
>>>> +
>>>> +/* Get the specific type of Intel CPU.  */
>>>> +
>>>> +static void
>>>> +get_intel_cpu (unsigned int family, unsigned int model, unsigned int 
>>>> brand_id)
>>>> +{
>>>> +  /* Parse family and model only if brand ID is 0. */
>>>> +  if (brand_id == 0)
>>>> +    {
>>>> +      switch (family)
>>>> +       {
>>>> +       case 0x5:
>>>> +         /* Pentium.  */
>>>> +         break;
>>>> +       case 0x6:
>>>> +         switch (model)
>>>> +           {
>>>> +           case 0x1c:
>>>> +           case 0x26:
>>>> +             /* Atom.  */
>>>> +             __cpu_model.__cpu_is_intel_atom = 1;
>>>> +             break;
>>>> +           case 0x1a:
>>>> +           case 0x1e:
>>>> +           case 0x1f:
>>>> +           case 0x2e:
>>>> +             /* Nehalem.  */
>>>> +             __cpu_model.__cpu_is_intel_corei7 = 1;
>>>> +             __cpu_model.__cpu_is_intel_corei7_nehalem = 1;
>>>> +             break;
>>>> +           case 0x25:
>>>> +           case 0x2c:
>>>> +           case 0x2f:
>>>> +             /* Westmere.  */
>>>> +             __cpu_model.__cpu_is_intel_corei7 = 1;
>>>> +             __cpu_model.__cpu_is_intel_corei7_westmere = 1;
>>>> +             break;
>>>> +           case 0x2a:
>>>> +             /* Sandy Bridge.  */
>>>> +             __cpu_model.__cpu_is_intel_corei7 = 1;
>>>> +             __cpu_model.__cpu_is_intel_corei7_sandybridge = 1;
>>>> +             break;
>>>> +           case 0x17:
>>>> +           case 0x1d:
>>>> +             /* Penryn.  */
>>>> +           case 0x0f:
>>>> +             /* Merom.  */
>>>> +             __cpu_model.__cpu_is_intel_core2 = 1;
>>>> +             break;
>>>> +           default:
>>>> +             break;
>>>> +           }
>>>> +         break;
>>>> +       default:
>>>> +         /* We have no idea.  */
>>>> +         break;
>>>> +       }
>>>> +    }
>>>> +}
>>>> +
>>>> +static void
>>>> +get_available_features (unsigned int ecx, unsigned int edx)
>>>> +{
>>>> +  __cpu_features.__cpu_cmov = (edx & bit_CMOV) ? 1 : 0;
>>>> +  __cpu_features.__cpu_mmx = (edx & bit_MMX) ? 1 : 0;
>>>> +  __cpu_features.__cpu_sse = (edx & bit_SSE) ? 1 : 0;
>>>> +  __cpu_features.__cpu_sse2 = (edx & bit_SSE2) ? 1 : 0;
>>>> +  __cpu_features.__cpu_popcnt = (ecx & bit_POPCNT) ? 1 : 0;
>>>> +  __cpu_features.__cpu_sse3 = (ecx & bit_SSE3) ? 1 : 0;
>>>> +  __cpu_features.__cpu_ssse3 = (ecx & bit_SSSE3) ? 1 : 0;
>>>> +  __cpu_features.__cpu_sse4_1 = (ecx & bit_SSE4_1) ? 1 : 0;
>>>> +  __cpu_features.__cpu_sse4_2 = (ecx & bit_SSE4_2) ? 1 : 0;
>>>> +}
>>>> +
>>>> +
>>>> +/* Sanity check for the vendor and cpu type flags.  */
>>>> +
>>>> +static int
>>>> +sanity_check (void)
>>>> +{
>>>> +  unsigned int one_type = 0;
>>>> +
>>>> +  /* Vendor cannot be Intel and AMD. */
>>>> +  gcc_assert((__cpu_model.__cpu_is_intel == 0)
>>>> +             || (__cpu_model.__cpu_is_amd == 0));
>>>> +
>>>> +  /* Only one CPU type can be set. */
>>>> +  one_type = (__cpu_model.__cpu_is_intel_atom
>>>> +             + __cpu_model.__cpu_is_intel_core2
>>>> +             + __cpu_model.__cpu_is_intel_corei7_nehalem
>>>> +             + __cpu_model.__cpu_is_intel_corei7_westmere
>>>> +             + __cpu_model.__cpu_is_intel_corei7_sandybridge
>>>> +             + __cpu_model.__cpu_is_amdfam10h_barcelona
>>>> +             + __cpu_model.__cpu_is_amdfam10h_shanghai
>>>> +             + __cpu_model.__cpu_is_amdfam10h_istanbul
>>>> +             + __cpu_model.__cpu_is_amdfam15h_bdver1
>>>> +             + __cpu_model.__cpu_is_amdfam15h_bdver2);
>>>> +
>>>> +  gcc_assert (one_type <= 1);
>>>> +  return 0;
>>>> +}
>>>> +
>>>> +/* A noinline function calling __get_cpuid. Having many calls to
>>>> +   cpuid in one function in 32-bit mode causes GCC to complain:
>>>> +   "can’t find a register in class ‘CLOBBERED_REGS’".  This is
>>>> +   related to PR rtl-optimization 44174. */
>>>> +
>>>> +static int __attribute__ ((noinline))
>>>> +__get_cpuid_output (unsigned int __level,
>>>> +                   unsigned int *__eax, unsigned int *__ebx,
>>>> +                   unsigned int *__ecx, unsigned int *__edx)
>>>> +{
>>>> +  return __get_cpuid (__level, __eax, __ebx, __ecx, __edx);
>>>> +}
>>>> +
>>>> +
>>>> +/* A constructor function that is sets __cpu_model and __cpu_features with
>>>> +   the right values.  This needs to run only once.  This constructor is
>>>> +   given the highest priority and it should run before constructors 
>>>> without
>>>> +   the priority set.  However, it still runs after ifunc initializers and
>>>> +   needs to be called explicitly there.  */
>>>> +
>>>> +int __attribute__ ((constructor (101)))
>>>> +__cpu_indicator_init (void)
>>>> +{
>>>> +  unsigned int eax, ebx, ecx, edx;
>>>> +
>>>> +  int max_level = 5;
>>>> +  unsigned int vendor;
>>>> +  unsigned int model, family, brand_id;
>>>> +  unsigned int extended_model, extended_family;
>>>> +  static int called = 0;
>>>> +
>>>> +  /* This function needs to run just once.  */
>>>> +  if (called)
>>>> +    return 0;
>>>> +  else
>>>> +    called = 1;
>>>> +
>>>> +  /* Assume cpuid insn present. Run in level 0 to get vendor id. */
>>>> +  if (!__get_cpuid_output (0, &eax, &ebx, &ecx, &edx))
>>>> +    return -1;
>>>> +
>>>> +  vendor = ebx;
>>>> +  max_level = eax;
>>>> +
>>>> +  if (max_level < 1)
>>>> +    return -1;
>>>> +
>>>> +  if (!__get_cpuid_output (1, &eax, &ebx, &ecx, &edx))
>>>> +    return -1;
>>>> +
>>>> +  model = (eax >> 4) & 0x0f;
>>>> +  family = (eax >> 8) & 0x0f;
>>>> +  brand_id = ebx & 0xff;
>>>> +  extended_model = (eax >> 12) & 0xf0;
>>>> +  extended_family = (eax >> 20) & 0xff;
>>>> +
>>>> +  if (vendor == SIG_INTEL)
>>>> +    {
>>>> +      /* Adjust model and family for Intel CPUS. */
>>>> +      if (family == 0x0f)
>>>> +       {
>>>> +         family += extended_family;
>>>> +         model += extended_model;
>>>> +       }
>>>> +      else if (family == 0x06)
>>>> +       model += extended_model;
>>>> +
>>>> +      /* Get CPU type.  */
>>>> +      __cpu_model.__cpu_is_intel = 1;
>>>> +      get_intel_cpu (family, model, brand_id);
>>>> +    }
>>>> +
>>>> +  if (vendor == SIG_AMD)
>>>> +    {
>>>> +      /* Adjust model and family for AMD CPUS. */
>>>> +      if (family == 0x0f)
>>>> +       {
>>>> +         family += extended_family;
>>>> +         model += (extended_model << 4);
>>>> +       }
>>>> +
>>>> +      /* Get CPU type.  */
>>>> +      __cpu_model.__cpu_is_amd = 1;
>>>> +      get_amd_cpu (family, model);
>>>> +    }
>>>> +
>>>> +  /* Find available features. */
>>>> +  get_available_features (ecx, edx);
>>>> +
>>>> +  sanity_check ();
>>>> +
>>>> +  return 0;
>>>> +}
>>>> Index: libgcc/config/i386/libgcc-glibc.ver
>>>> ===================================================================
>>>> --- libgcc/config/i386/libgcc-glibc.ver (revision 184971)
>>>> +++ libgcc/config/i386/libgcc-glibc.ver (working copy)
>>>> @@ -147,6 +147,11 @@ GCC_4.3.0 {
>>>>   __trunctfxf2
>>>>   __unordtf2
>>>>  }
>>>> +
>>>> +GCC_4.8.0 {
>>>> +  __cpu_model
>>>> +  __cpu_features
>>>> +}
>>>>  %else
>>>>  GCC_4.4.0 {
>>>>   __addtf3
>>>> @@ -183,4 +188,9 @@ GCC_4.4.0 {
>>>>  GCC_4.5.0 {
>>>>   __extendxftf2
>>>>  }
>>>> +
>>>> +GCC_4.8.0 {
>>>> +  __cpu_model
>>>> +  __cpu_features
>>>> +}
>>>>  %endif
>>>> Index: gcc/config/i386/i386-builtin-types.def
>>>> ===================================================================
>>>> --- gcc/config/i386/i386-builtin-types.def      (revision 184971)
>>>> +++ gcc/config/i386/i386-builtin-types.def      (working copy)
>>>> @@ -143,6 +143,7 @@ DEF_FUNCTION_TYPE (UINT64)
>>>>  DEF_FUNCTION_TYPE (UNSIGNED)
>>>>  DEF_FUNCTION_TYPE (VOID)
>>>>  DEF_FUNCTION_TYPE (PVOID)
>>>> +DEF_FUNCTION_TYPE (INT)
>>>>
>>>>  DEF_FUNCTION_TYPE (FLOAT, FLOAT)
>>>>  DEF_FUNCTION_TYPE (FLOAT128, FLOAT128)
>>>> Index: gcc/config/i386/i386.c
>>>> ===================================================================
>>>> --- gcc/config/i386/i386.c      (revision 184971)
>>>> +++ gcc/config/i386/i386.c      (working copy)
>>>> @@ -25637,6 +25637,33 @@ enum ix86_builtins
>>>>   /* CFString built-in for darwin */
>>>>   IX86_BUILTIN_CFSTRING,
>>>>
>>>> +  /* Builtins to get CPU features. */
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_CMOV,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_MMX,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_POPCOUNT,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSE,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSE2,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSE3,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSSE3,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSE4_1,
>>>> +  IX86_BUILTIN_CPU_SUPPORTS_SSE4_2,
>>>> +  /* Builtins to get CPU type. */
>>>> +  IX86_BUILTIN_CPU_INIT,
>>>> +  IX86_BUILTIN_CPU_IS_AMD,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_ATOM,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_CORE2,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_COREI7,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_COREI7_NEHALEM,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_COREI7_WESTMERE,
>>>> +  IX86_BUILTIN_CPU_IS_INTEL_COREI7_SANDYBRIDGE,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM10H,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM10H_BARCELONA,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM10H_SHANGHAI,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM10H_ISTANBUL,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER1,
>>>> +  IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER2,
>>>> +
>>>>   IX86_BUILTIN_MAX
>>>>  };
>>>>
>>>> @@ -27446,6 +27473,593 @@ ix86_init_mmx_sse_builtins (void)
>>>>     }
>>>>  }
>>>>
>>>> +/* Returns a struct type with name NAME and number of fields equal to
>>>> +   NUM_FIELDS.  Each field is a unsigned int bit field of length 1 bit. */
>>>> +
>>>> +static tree
>>>> +build_struct_with_one_bit_fields (int num_fields, const char *name)
>>>> +{
>>>> +  int i;
>>>> +  char field_name [10];
>>>> +  tree field = NULL_TREE, field_chain = NULL_TREE;
>>>> +  tree type = make_node (RECORD_TYPE);
>>>> +
>>>> +  strcpy (field_name, "k_field");
>>>> +
>>>> +  for (i = 0; i < num_fields; i++)
>>>> +    {
>>>> +      /* Name the fields, 0_field, 1_field, ... */
>>>> +      field_name [0] = '0' + i;
>>>> +      field = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
>>>> +                         get_identifier (field_name), unsigned_type_node);
>>>> +      DECL_BIT_FIELD (field) = 1;
>>>> +      DECL_SIZE (field) = bitsize_one_node;
>>>> +      if (field_chain != NULL_TREE)
>>>> +       DECL_CHAIN (field) = field_chain;
>>>> +      field_chain = field;
>>>> +    }
>>>> +  finish_builtin_struct (type, name, field_chain, NULL_TREE);
>>>> +  return type;
>>>> +}
>>>> +
>>>> +/* Returns a extern, comdat VAR_DECL of type TYPE and name NAME. */
>>>> +
>>>> +static tree
>>>> +make_var_decl (tree type, const char *name)
>>>> +{
>>>> +  tree new_decl;
>>>> +  struct varpool_node *vnode;
>>>> +
>>>> +  new_decl = build_decl (UNKNOWN_LOCATION,
>>>> +                        VAR_DECL,
>>>> +                        get_identifier(name),
>>>> +                        type);
>>>> +
>>>> +  DECL_EXTERNAL (new_decl) = 1;
>>>> +  TREE_STATIC (new_decl) = 1;
>>>> +  TREE_PUBLIC (new_decl) = 1;
>>>> +  DECL_INITIAL (new_decl) = 0;
>>>> +  DECL_ARTIFICIAL (new_decl) = 0;
>>>> +  DECL_PRESERVE_P (new_decl) = 1;
>>>> +
>>>> +  make_decl_one_only (new_decl, DECL_ASSEMBLER_NAME (new_decl));
>>>> +  assemble_variable (new_decl, 0, 0, 0);
>>>> +
>>>> +  vnode = varpool_node (new_decl);
>>>> +  gcc_assert (vnode != NULL);
>>>> +  /* Set finalized to 1, otherwise it asserts in function "write_symbol" 
>>>> in
>>>> +     lto-streamer-out.c. */
>>>> +  vnode->finalized = 1;
>>>> +
>>>> +  return new_decl;
>>>> +}
>>>> +
>>>> +/* Traverses the chain of fields in STRUCT_TYPE and returns the FIELD_NUM
>>>> +   numbered field. */
>>>> +
>>>> +static tree
>>>> +get_field_from_struct (tree struct_type, int field_num)
>>>> +{
>>>> +  int i;
>>>> +  tree field = TYPE_FIELDS (struct_type);
>>>> +
>>>> +  for (i = 0; i < field_num; i++, field = DECL_CHAIN(field))
>>>> +    {
>>>> +      gcc_assert (field != NULL_TREE);
>>>> +    }
>>>> +
>>>> +  return field;
>>>> +}
>>>> +
>>>> +/* FNDECL is a __builtin_cpu_* call that is folded into an integer defined
>>>> +   in libgcc/config/i386/i386-cpuinfo.c */
>>>> +
>>>> +static tree
>>>> +fold_builtin_cpu (enum ix86_builtins fn_code)
>>>> +{
>>>> +  /* This is the order of bit-fields in __processor_features in
>>>> +     i386-cpuinfo.c */
>>>> +  enum processor_features
>>>> +  {
>>>> +    F_CMOV = 0,
>>>> +    F_MMX,
>>>> +    F_POPCNT,
>>>> +    F_SSE,
>>>> +    F_SSE2,
>>>> +    F_SSE3,
>>>> +    F_SSSE3,
>>>> +    F_SSE4_1,
>>>> +    F_SSE4_2,
>>>> +    F_MAX
>>>> +  };
>>>> +
>>>> +  /* This is the order of bit-fields in __processor_model in
>>>> +     i386-cpuinfo.c */
>>>> +  enum processor_model
>>>> +  {
>>>> +    M_AMD = 0,
>>>> +    M_INTEL,
>>>> +    M_INTEL_ATOM,
>>>> +    M_INTEL_CORE2,
>>>> +    M_INTEL_COREI7,
>>>> +    M_INTEL_COREI7_NEHALEM,
>>>> +    M_INTEL_COREI7_WESTMERE,
>>>> +    M_INTEL_COREI7_SANDYBRIDGE,
>>>> +    M_AMDFAM10H,
>>>> +    M_AMDFAM10H_BARCELONA,
>>>> +    M_AMDFAM10H_SHANGHAI,
>>>> +    M_AMDFAM10H_ISTANBUL,
>>>> +    M_AMDFAM15H_BDVER1,
>>>> +    M_AMDFAM15H_BDVER2,
>>>> +    M_MAX
>>>> +  };
>>>> +
>>>> +  static tree __processor_features_type = NULL_TREE;
>>>> +  static tree __cpu_features_var = NULL_TREE;
>>>> +  static tree __processor_model_type = NULL_TREE;
>>>> +  static tree __cpu_model_var = NULL_TREE;
>>>> +  static tree field;
>>>> +  static tree which_struct;
>>>> +
>>>> +  if (__processor_features_type == NULL_TREE)
>>>> +    __processor_features_type = build_struct_with_one_bit_fields (F_MAX,
>>>> +                                 "__processor_features");
>>>> +
>>>> +  if (__processor_model_type == NULL_TREE)
>>>> +    __processor_model_type = build_struct_with_one_bit_fields (M_MAX,
>>>> +                                 "__processor_model");
>>>> +
>>>> +  if (__cpu_features_var == NULL_TREE)
>>>> +    __cpu_features_var = make_var_decl (__processor_features_type,
>>>> +                                       "__cpu_features");
>>>> +
>>>> +  if (__cpu_model_var == NULL_TREE)
>>>> +    __cpu_model_var = make_var_decl (__processor_model_type,
>>>> +                                    "__cpu_model");
>>>> +
>>>> +  /* Look at the code to identify the field requested. */
>>>> +  switch (fn_code)
>>>> +    {
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_CMOV:
>>>> +      field = get_field_from_struct (__processor_features_type, F_CMOV);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_MMX:
>>>> +      field = get_field_from_struct (__processor_features_type, F_MMX);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_POPCOUNT:
>>>> +      field = get_field_from_struct (__processor_features_type, F_POPCNT);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSE);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE2:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSE2);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE3:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSE3);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSSE3:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSSE3);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE4_1:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSE4_1);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE4_2:
>>>> +      field = get_field_from_struct (__processor_features_type, F_SSE4_2);
>>>> +      which_struct = __cpu_features_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMD:
>>>> +      field = get_field_from_struct (__processor_model_type, M_AMD);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL:
>>>> +      field = get_field_from_struct (__processor_model_type, M_INTEL);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_ATOM:
>>>> +      field = get_field_from_struct (__processor_model_type, 
>>>> M_INTEL_ATOM);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_CORE2:
>>>> +      field = get_field_from_struct (__processor_model_type, 
>>>> M_INTEL_CORE2);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_INTEL_COREI7);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_NEHALEM:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_INTEL_COREI7_NEHALEM);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_WESTMERE:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_INTEL_COREI7_WESTMERE);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_SANDYBRIDGE:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_INTEL_COREI7_SANDYBRIDGE);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM10H);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_BARCELONA:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM10H_BARCELONA);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_SHANGHAI:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM10H_SHANGHAI);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_ISTANBUL:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM10H_ISTANBUL);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER1:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM15H_BDVER1);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER2:
>>>> +      field = get_field_from_struct (__processor_model_type,
>>>> +                                    M_AMDFAM15H_BDVER2);
>>>> +      which_struct = __cpu_model_var;
>>>> +      break;
>>>> +    default:
>>>> +      return NULL_TREE;
>>>> +    }
>>>> +
>>>> +  return build3 (COMPONENT_REF, TREE_TYPE (field), which_struct, field, 
>>>> NULL_TREE);
>>>> +}
>>>> +
>>>> +static tree
>>>> +ix86_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
>>>> +                  tree *args ATTRIBUTE_UNUSED, bool ignore 
>>>> ATTRIBUTE_UNUSED)
>>>> +{
>>>> +  const char* decl_name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
>>>> +  if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD
>>>> +      && strstr(decl_name, "__builtin_cpu") != NULL)
>>>> +    {
>>>> +      enum ix86_builtins code = (enum ix86_builtins)
>>>> +                               DECL_FUNCTION_CODE (fndecl);
>>>> +      return fold_builtin_cpu (code);
>>>> +    }
>>>> +  return NULL_TREE;
>>>> +}
>>>> +
>>>> +/* A builtin to init/return the cpu type or feature.  Returns an
>>>> +   integer and the type is a const if IS_CONST is set. */
>>>> +
>>>> +static void
>>>> +make_platform_builtin (const char* name, int code, int is_const)
>>>> +{
>>>> +  tree decl;
>>>> +  tree type;
>>>> +
>>>> +  type = ix86_get_builtin_func_type (INT_FTYPE_VOID);
>>>> +  decl = add_builtin_function (name, type, code, BUILT_IN_MD,
>>>> +                              NULL, NULL_TREE);
>>>> +  gcc_assert (decl != NULL_TREE);
>>>> +  ix86_builtins[(int) code] = decl;
>>>> +  if (is_const)
>>>> +    TREE_READONLY (decl) = 1;
>>>> +}
>>>> +
>>>> +/* Builtins to get CPU type and features supported. */
>>>> +
>>>> +static void
>>>> +ix86_init_platform_type_builtins (void)
>>>> +{
>>>> +  make_platform_builtin ("__builtin_cpu_init",
>>>> +                        IX86_BUILTIN_CPU_INIT, 0);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_cmov",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_CMOV, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_mmx",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_MMX, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_popcount",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_POPCOUNT, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_sse",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSE, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_sse2",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSE2, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_sse3",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSE3, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_ssse3",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSSE3, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_sse4_1",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSE4_1, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_supports_sse4_2",
>>>> +                        IX86_BUILTIN_CPU_SUPPORTS_SSE4_2, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amd",
>>>> +                        IX86_BUILTIN_CPU_IS_AMD, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_atom",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_ATOM, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_core2",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_CORE2, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_corei7",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_COREI7, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_corei7_nehalem",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_COREI7_NEHALEM, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_corei7_westmere",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_COREI7_WESTMERE, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_intel_corei7_sandybridge",
>>>> +                        IX86_BUILTIN_CPU_IS_INTEL_COREI7_SANDYBRIDGE, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam10",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM10H, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam10_barcelona",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM10H_BARCELONA, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam10_shanghai",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM10H_SHANGHAI, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam10_istanbul",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM10H_ISTANBUL, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam15_bdver1",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER1, 1);
>>>> +  make_platform_builtin ("__builtin_cpu_is_amdfam15_bdver2",
>>>> +                        IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER2, 1);
>>>> +}
>>>> +
>>>>  /* Internal method for ix86_init_builtins.  */
>>>>
>>>>  static void
>>>> @@ -27529,6 +28143,9 @@ ix86_init_builtins (void)
>>>>
>>>>   ix86_init_builtin_types ();
>>>>
>>>> +  /* Builtins to get CPU type and features. */
>>>> +  ix86_init_platform_type_builtins ();
>>>> +
>>>>   /* TFmode support builtins.  */
>>>>   def_builtin_const (0, "__builtin_infq",
>>>>                     FLOAT128_FTYPE_VOID, IX86_BUILTIN_INFQ);
>>>> @@ -29145,6 +29762,48 @@ ix86_expand_builtin (tree exp, rtx target, rtx sub
>>>>   enum machine_mode mode0, mode1, mode2, mode3, mode4;
>>>>   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
>>>>
>>>> +  /* For CPU builtins that can be folded, fold first and expand the fold. 
>>>>  */
>>>> +  switch (fcode)
>>>> +    {
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_CMOV:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_MMX:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_POPCOUNT:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE2:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE3:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSSE3:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE4_1:
>>>> +    case IX86_BUILTIN_CPU_SUPPORTS_SSE4_2:
>>>> +    case IX86_BUILTIN_CPU_IS_AMD:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_ATOM:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_CORE2:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_NEHALEM:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_WESTMERE:
>>>> +    case IX86_BUILTIN_CPU_IS_INTEL_COREI7_SANDYBRIDGE:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_BARCELONA:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_SHANGHAI:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM10H_ISTANBUL:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER1:
>>>> +    case IX86_BUILTIN_CPU_IS_AMDFAM15H_BDVER2:
>>>> +      {
>>>> +        tree fold_expr = fold_builtin_cpu ((enum ix86_builtins) fcode);
>>>> +       gcc_assert (fold_expr != NULL_TREE);
>>>> +        return expand_expr (fold_expr, target, mode, EXPAND_NORMAL);
>>>> +      }
>>>> +    case IX86_BUILTIN_CPU_INIT:
>>>> +      {
>>>> +       /* Make it call __cpu_indicator_init in libgcc. */
>>>> +       tree call_expr, fndecl, type;
>>>> +        type = build_function_type_list (integer_type_node, NULL_TREE);
>>>> +       fndecl = build_fn_decl ("__cpu_indicator_init", type);
>>>> +       call_expr = build_call_expr (fndecl, 0);
>>>> +       return expand_expr (call_expr, target, mode, EXPAND_NORMAL);
>>>> +      }
>>>> +    }
>>>> +
>>>>   /* Determine whether the builtin function is available under the current 
>>>> ISA.
>>>>      Originally the builtin was not created if it wasn't applicable to the
>>>>      current ISA based on the command line switches.  With function 
>>>> specific
>>>> @@ -38610,6 +39269,12 @@ ix86_autovectorize_vector_sizes (void)
>>>>  #undef TARGET_BUILD_BUILTIN_VA_LIST
>>>>  #define TARGET_BUILD_BUILTIN_VA_LIST ix86_build_builtin_va_list
>>>>
>>>> +#undef TARGET_FOLD_BUILTIN
>>>> +#define TARGET_FOLD_BUILTIN ix86_fold_builtin
>>>> +
>>>>  #undef TARGET_ENUM_VA_LIST_P
>>>>  #define TARGET_ENUM_VA_LIST_P ix86_enum_va_list
>>>> Index: gcc/testsuite/gcc.target/i386/builtin_target.c
>>>> ===================================================================
>>>> --- gcc/testsuite/gcc.target/i386/builtin_target.c      (revision 0)
>>>> +++ gcc/testsuite/gcc.target/i386/builtin_target.c      (revision 0)
>>>> @@ -0,0 +1,61 @@
>>>> +/* This test checks if the __builtin_cpu_* calls are recognized. */
>>>> +
>>>> +/* { dg-do run } */
>>>> +
>>>> +int
>>>> +fn1 ()
>>>> +{
>>>> +  if (__builtin_cpu_supports_cmov () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_mmx () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_popcount () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_sse () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_sse2 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_sse3 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_ssse3 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_sse4_1 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_supports_sse4_2 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amd () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_atom () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_core2 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_corei7 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_corei7_nehalem () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_corei7_westmere () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_intel_corei7_sandybridge () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam10 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam10_barcelona () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam10_shanghai () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam10_istanbul () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam15_bdver1 () < 0)
>>>> +    return -1;
>>>> +  if (__builtin_cpu_is_amdfam15_bdver2 () < 0)
>>>> +    return -1;
>>>> +
>>>> +  return 0;
>>>> +}
>>>> +
>>>> +int main ()
>>>> +{
>>>> +  return fn1 ();
>>>> +}
>>>>
>>>> --
>>>> This patch is available for review at http://codereview.appspot.com/5754058

Reply via email to