diff mbox

[AArch64,10/14] Implement target pragmas

Message ID 55BF3611.2080107@arm.com
State New
Headers show

Commit Message

Kyrylo Tkachov Aug. 3, 2015, 9:36 a.m. UTC
On 24/07/15 09:36, Kyrill Tkachov wrote:
> On 21/07/15 17:52, James Greenhalgh wrote:
>> On Thu, Jul 16, 2015 at 04:21:05PM +0100, Kyrill Tkachov wrote:
>>> Hi all,
>>>
>>> This patch implements target pragmas for aarch64.
>>> The pragmas accepted are the same as for target attributes (as required).
>>> In addition pragmas will need to redefine the target-specific preprocessor
>>> macros if appropriate.
>>>
>>> A new file: aarch64-c.c is added and the code from TARGET_CPU_CPP_BUILTINS is moved there
>>> and split up into the unconditional parts that are always defined and the conditional stuff
>>> that depends on certain architectural features.  The pragma processing code calls that
>>> to redefine preprocessor macros on the fly.
>>> The implementation is similar to the rs6000 one.
>>>
>>> With target pragmas implemented, we can use them in the arm_neon.h and arm_acle.h headers to
>>> specify the architectural features required for those intrinsics, rather than #ifdef'ing them
>>> out when FP/SIMD is not available from the command line.
>>>
>>> We need to do this in order to handle cases where the user compiles a file with -mgeneral-regs-only
>>> but has a function tagged with +simd and tries to use the arm_neon.h intrinsics.
>>> Tests and documentation comes as a separate patch later on in the series
>>>
>>> Bootstrapped and tested on aarch64.
>>>
>>> Ok for trunk?
>> A couple of ChangeLog nits and some comments below.
>>
>>> 2015-07-16  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>>>
>>>        * config.gcc (aarch64*-*-*): Specify c_target_objs and cxx_target_objs.
>>>        * config/aarch64/aarch64.h (REGISTER_TARGET_PRAGMAS):
>> This should say
>>
>>>        * config/aarch64/aarch64.h (REGISTER_TARGET_PRAGMAS): New.
>> Presumably (or maybe "Define.").
>>
>>
>>>        (TARGET_CPU_CPP_BUILTINS): Redefine to call aarch64_cpu_cpp_builtins.
>>>        * config/aarch64/aarch64.c (aarch64_override_options_internal): Remove
>>>        static keyword.
>>>        (aarch64_reset_previous_fndecl): New function.
>>>        * config/aarch64/aarch64-c.c: New file.
>>>        * config/aarch64/arm_acle.h: Add pragma +crc+nofp at the top.
>>>        Push and pop options at beginning and end.  Remove ifdef
>>>        __ARM_FEATURE_CRC32.
>>>        * config/aarch64/arm_neon.h: Remove #ifdef check on __ARM_NEON.
>>>        Add pragma arch=armv8-a+simd and +crypto where appropriate.
>>>        * config/aarch64/t-aarch64 (aarch64-c.o): New rule.
>> I don't see a ChangeLog entry for these hunks:
>>
>>> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
>>> index 3a5482d..4704736 100644
>>> --- a/gcc/config/aarch64/aarch64-protos.h
>>> +++ b/gcc/config/aarch64/aarch64-protos.h
>>> @@ -360,6 +360,10 @@ bool aarch64_gen_adjusted_ldpstp (rtx *, bool, enum machine_mode, RTX_CODE);
>>>    #endif /* RTX_CODE */
>>>
>>>    void aarch64_init_builtins (void);
>>> +
>>> +bool aarch64_process_target_attr (tree, const char*);
>>> +void aarch64_override_options_internal (struct gcc_options *);
>>> +
>>>    rtx aarch64_expand_builtin (tree exp,
>>>                           rtx target,
>>>                           rtx subtarget ATTRIBUTE_UNUSED,
>>> @@ -376,6 +380,9 @@ extern void aarch64_split_combinev16qi (rtx operands[3]);
>>>    extern void aarch64_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
>>>    extern bool aarch64_madd_needs_nop (rtx_insn *);
>>>    extern void aarch64_final_prescan_insn (rtx_insn *);
>>> +extern void aarch64_reset_previous_fndecl (void);
>>> +extern void aarch64_cpu_cpp_builtins (cpp_reader *);
>>> +extern void aarch64_register_pragmas (void);
>>>    extern bool
>>>    aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel);
>>>    bool aarch64_handle_option (struct gcc_options *, struct gcc_options *,
>>
>>
>>> +static bool
>>> +aarch64_pragma_target_parse (tree args, tree pop_target)
>>> +{
>>> +
>>> +  bool ret;
>>> +
>>> +  /* If args is not NULL then process it and setup the target-specific
>>> +     information that it specifies.  */
>>> +  if (args)
>>> +    {
>>> +      ret = aarch64_process_target_attr (args, "pragma");
>>> +      if (ret)
>>> +    aarch64_override_options_internal (&global_options);
>> RET must equal true.
>>
>>> +      else
>>> +    return false;
>> Early return of false closes the other control path here.
>>
>>> +    }
>>> +
>>> +  /* args is NULL, restore to the state described in pop_target.  */
>>> +  else
>>> +    {
>>> +      pop_target = pop_target ? pop_target : target_option_default_node;
>>> +      cl_target_option_restore (&global_options,
>>> +                            TREE_TARGET_OPTION (pop_target));
>>> +      ret = true;
>>> +    }
>> Therefore RET must equal true here.
>>
>>> +
>>> +  target_option_current_node
>>> +    = build_target_option_node (&global_options);
>>> +
>>> +  aarch64_reset_previous_fndecl ();
>>> +  /* For the definitions, ensure all newly defined macros are considered
>>> +     as used for -Wunused-macros.  There is no point warning about the
>>> +     compiler predefined macros.  */
>>> +  cpp_options *cpp_opts = cpp_get_options (parse_in);
>>> +  unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
>>> +  cpp_opts->warn_unused_macros = 0;
>>> +
>>> +  aarch64_update_cpp_builtins (parse_in);
>>> +
>>> +  cpp_opts->warn_unused_macros = saved_warn_unused_macros;
>>> +
>>> +  return ret;
>> So we don't need "RET" !
>>
>>> +}
>>> +
>>> +/* Implement REGISTER_TARGET_PRAGMAS.  */
>>> +
>>> +void
>>> +aarch64_register_pragmas (void)
>>> +{
>>> +  /* Update pragma hook to allow parsing #pragma GCC target.  */
>>> +  targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
>>> +}
>>> \ No newline at end of file
>> I can't remember if GNU style mandates it, but in my opinion your new
>> file should have a trailing newline.
>>
>>> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
>>> index 3a5482d..4704736 100644
>>> --- a/gcc/config/aarch64/aarch64-protos.h
>>> +++ b/gcc/config/aarch64/aarch64-protos.h
>>> @@ -360,6 +360,10 @@ bool aarch64_gen_adjusted_ldpstp (rtx *, bool, enum machine_mode, RTX_CODE);
>>>    #endif /* RTX_CODE */
>>>
>>>    void aarch64_init_builtins (void);
>>> +
>>> +bool aarch64_process_target_attr (tree, const char*);
>>> +void aarch64_override_options_internal (struct gcc_options *);
>>> +
>>>    rtx aarch64_expand_builtin (tree exp,
>>>                           rtx target,
>>>                           rtx subtarget ATTRIBUTE_UNUSED,
>>> @@ -376,6 +380,9 @@ extern void aarch64_split_combinev16qi (rtx operands[3]);
>>>    extern void aarch64_expand_vec_perm (rtx target, rtx op0, rtx op1, rtx sel);
>>>    extern bool aarch64_madd_needs_nop (rtx_insn *);
>>>    extern void aarch64_final_prescan_insn (rtx_insn *);
>>> +extern void aarch64_reset_previous_fndecl (void);
>>> +extern void aarch64_cpu_cpp_builtins (cpp_reader *);
>>> +extern void aarch64_register_pragmas (void);
>> At one point aarch64-protos.h was in alphabetical order. While we have
>> a number of mistakes already, we should try not to make the situation
>> worse!
>>
>>> diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h
>>> index 7af4ad2..f6b2c11 100644
>>> --- a/gcc/config/aarch64/arm_acle.h
>>> +++ b/gcc/config/aarch64/arm_acle.h
>>> @@ -28,11 +28,16 @@
>>>    #define _GCC_ARM_ACLE_H
>>>
>>>    #include <stdint.h>
>>> +
>>> +#pragma GCC push_options
>>> +/* Add +nofp to make sure that 'fp' is not required to compile these
>>> +   intrinsics.  */
>>> +#pragma GCC target("+crc+nofp")
>> Hm, how does this work with the ARMv8.1 Extensions added by Matthew
>> Wahab recently? Presumably this needs to expand to have a "+no" for
>> all possible extensions. This seems messy, it might be neater to
>> implement something like +nothing which resets the state of the extension
>> features bitmask to zero.
> Thanks, I've implemented the "+nothing" architectural feature modifier
> that can appear only in target attributes and pragmas like so:
> #pragma GCC target ("+nothing+crc") where the +nothing clears out aarch64_isa_flags,
> allowing the rest of the string to enable features one by one.
>
> Also fixed the other issues you pointed.
>
> How's this?

And here is a rebased version to resolve a conflict after Alan's patches went in.

Thanks,
Kyrill


2015-08-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

      * config.gcc (aarch64*-*-*): Specify c_target_objs and cxx_target_objs.
      * config/aarch64/aarch64.h (REGISTER_TARGET_PRAGMAS): Define.
      (TARGET_CPU_CPP_BUILTINS): Redefine to call aarch64_cpu_cpp_builtins.
      * config/aarch64/aarch64.c (aarch64_override_options_internal): Remove
      static keyword.
      (aarch64_reset_previous_fndecl): New function.
      (aarch64_handle_attr_isa_flags): Handle "+nothing" in the beginning of
      the string.
      * config/aarch64/aarch64-c.c: New file.
      * config/aarch64/arm_acle.h: Add pragma +crc+nofp at the top.
      Push and pop options at beginning and end.  Remove ifdef
      __ARM_FEATURE_CRC32.
      * config/aarch64/arm_neon.h: Remove #ifdef check on __ARM_NEON.
      Add pragma arch=armv8-a+simd and +crypto where appropriate.
      * config/aarch64/t-aarch64 (aarch64-c.o): New rule.
      * config/aarch64/aarch64-protos.h (aarch64_cpu_cpp_builtins):
      Define prototype.
      (aarch64_register_pragmas): Likewise.
      (aarch64_reset_previous_fndecl): Likewise.
      (aarch64_process_target_attr): Likewise.
      (aarch64_override_options_internal): Likewise.

2015-08-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>

     * gcc.target/aarch64/arm_neon-nosimd-error.c: Delete.


> Thanks,
> Kyrill
>
> 2015-07-24  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
>
>       * config.gcc (aarch64*-*-*): Specify c_target_objs and cxx_target_objs.
>       * config/aarch64/aarch64.h (REGISTER_TARGET_PRAGMAS): Define.
>       (TARGET_CPU_CPP_BUILTINS): Redefine to call aarch64_cpu_cpp_builtins.
>       * config/aarch64/aarch64.c (aarch64_override_options_internal): Remove
>       static keyword.
>       (aarch64_reset_previous_fndecl): New function.
>       (aarch64_handle_attr_isa_flags): Handle "+nothing" in the beginning of
>       the string.
>       * config/aarch64/aarch64-c.c: New file.
>       * config/aarch64/arm_acle.h: Add pragma +crc+nofp at the top.
>       Push and pop options at beginning and end.  Remove ifdef
>       __ARM_FEATURE_CRC32.
>       * config/aarch64/arm_neon.h: Remove #ifdef check on __ARM_NEON.
>       Add pragma arch=armv8-a+simd and +crypto where appropriate.
>       * config/aarch64/t-aarch64 (aarch64-c.o): New rule.
>       * config/aarch64/aarch64-protos.h (aarch64_cpu_cpp_builtins):
>       Define prototype.
>       (aarch64_register_pragmas): Likewise.
>       (aarch64_reset_previous_fndecl): Likewise.
>       (aarch64_process_target_attr): Likewise.
>       (aarch64_override_options_internal): Likewise.
>
>
>>> +
>>>    #ifdef __cplusplus
>>>    extern "C" {
>>>    #endif
>>>
>>> -#ifdef __ARM_FEATURE_CRC32
>>>    __extension__ static __inline uint32_t __attribute__ ((__always_inline__))
>>>    __crc32b (uint32_t __a, uint8_t __b)
>>>    {
>>> @@ -81,10 +86,10 @@ __crc32d (uint32_t __a, uint64_t __b)
>>>      return __builtin_aarch64_crc32x (__a, __b);
>>>    }
>>>
>>> -#endif
>>> -
>>>    #ifdef __cplusplus
>>>    }
>>>    #endif
>>>
>>> +#pragma GCC pop_options
>>> +
>>>    #endif
>> Thanks,
>> James
>>

Comments

James Greenhalgh Aug. 3, 2015, 11:18 a.m. UTC | #1
On Mon, Aug 03, 2015 at 10:36:17AM +0100, Kyrill Tkachov wrote:
> And here is a rebased version to resolve a conflict after Alan's patches went in.
> 

OK with the nits below fixed.

> 2015-08-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>       * config.gcc (aarch64*-*-*): Specify c_target_objs and cxx_target_objs.
>       * config/aarch64/aarch64.h (REGISTER_TARGET_PRAGMAS): Define.
>       (TARGET_CPU_CPP_BUILTINS): Redefine to call aarch64_cpu_cpp_builtins.
>       * config/aarch64/aarch64.c (aarch64_override_options_internal): Remove
>       static keyword.
>       (aarch64_reset_previous_fndecl): New function.
>       (aarch64_handle_attr_isa_flags): Handle "+nothing" in the beginning of
>       the string.
>       * config/aarch64/aarch64-c.c: New file.
>       * config/aarch64/arm_acle.h: Add pragma +crc+nofp at the top.
>       Push and pop options at beginning and end.  Remove ifdef
>       __ARM_FEATURE_CRC32.
>       * config/aarch64/arm_neon.h: Remove #ifdef check on __ARM_NEON.
>       Add pragma arch=armv8-a+simd and +crypto where appropriate.
>       * config/aarch64/t-aarch64 (aarch64-c.o): New rule.
>       * config/aarch64/aarch64-protos.h (aarch64_cpu_cpp_builtins):
>       Define prototype.
>       (aarch64_register_pragmas): Likewise.
>       (aarch64_reset_previous_fndecl): Likewise.
>       (aarch64_process_target_attr): Likewise.
>       (aarch64_override_options_internal): Likewise.
> 
> 2015-08-03  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
> 
>      * gcc.target/aarch64/arm_neon-nosimd-error.c: Delete.
> 
> 

> +/* Define the macros that we always expect to have on AArch64.  */
> +
> +static void
> +aarch64_define_unconditional_macros (cpp_reader *pfile)
> +{
> +  builtin_define ("__aarch64__");
> +  builtin_define ("__ARM_64BIT_STATE");
> +
> +  builtin_define ("__ARM_ARCH_ISA_A64");
> +  builtin_define_with_int_value ("__ARM_ALIGN_MAX_PWR", 28);
> +  builtin_define_with_int_value ("__ARM_ALIGN_MAX_STACK_PWR", 16);
> +
> +  /* __ARM_ARCH_8A is not mandated by ACLE but we define it unconditionally
> +     as interoperability with the same arm macro.  */
> +  builtin_define ("__ARM_ARCH_8A");
> +
> +  builtin_define_with_int_value ("__ARM_ARCH_PROFILE", 'A');
> +  builtin_define ("__ARM_FEATURE_CLZ");
> +  builtin_define ("__ARM_FEATURE_IDIV");
> +  builtin_define ("__ARM_FEATURE_UNALIGNED");
> +  builtin_define ("__ARM_PCS_AAPCS64");
> +  builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);
> +
> +}

Extra newline.

> diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
> index 3a5482d..6844c90 100644
> --- a/gcc/config/aarch64/aarch64-protos.h
> +++ b/gcc/config/aarch64/aarch64-protos.h
> @@ -249,6 +249,7 @@ enum aarch64_symbol_type
>  aarch64_classify_symbolic_expression (rtx, enum aarch64_symbol_context);
>  bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
>  bool aarch64_constant_address_p (rtx);
> +extern void aarch64_cpu_cpp_builtins (cpp_reader *);

No need for this "extern" - and keep this in alphabetical order (first by
return type, then by name).

> +#pragma GCC push_options
> +#pragma GCC target ("+crypto")

Keep things simple to manage and understand by inspection, and make these
"+nothing+crypto".

> @@ -21067,7 +21065,8 @@ vrsrad_n_u64 (uint64_t __a, uint64_t __b, const int __c)
>    return __builtin_aarch64_ursra_ndi_uuus (__a, __b, __c);
>  }
>  
> -#ifdef __ARM_FEATURE_CRYPTO
> +#pragma GCC push_options
> +#pragma GCC target ("+crypto")
>  
>  /* vsha1  */
>  

Likewise here.

Thanks,
James
diff mbox

Patch

commit eef5b2cf262c76fbfed80e9a5e3795d4667d473a
Author: Kyrylo Tkachov <kyrylo.tkachov@arm.com>
Date:   Thu May 14 15:36:07 2015 +0100

    [AArch64][10/N] Implement target pragmas

diff --git a/gcc/config.gcc b/gcc/config.gcc
index d6b928d..24f6d35 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -302,6 +302,8 @@  m32c*-*-*)
 aarch64*-*-*)
 	cpu_type=aarch64
 	extra_headers="arm_neon.h arm_acle.h"
+	c_target_objs="aarch64-c.o"
+	cxx_target_objs="aarch64-c.o"
 	extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o"
 	target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c"
 	target_has_targetm_common=yes
diff --git a/gcc/config/aarch64/aarch64-c.c b/gcc/config/aarch64/aarch64-c.c
new file mode 100644
index 0000000..a9020ab
--- /dev/null
+++ b/gcc/config/aarch64/aarch64-c.c
@@ -0,0 +1,191 @@ 
+/* Target-specific code for C family languages.
+   Copyright (C) 2015 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 "input.h"
+#include "tm_p.h"
+#include "flags.h"
+#include "c-family/c-common.h"
+#include "cpplib.h"
+#include "c-family/c-pragma.h"
+#include "langhooks.h"
+#include "target.h"
+
+
+#define builtin_define(TXT) cpp_define (pfile, TXT)
+#define builtin_assert(TXT) cpp_assert (pfile, TXT)
+
+
+static void
+aarch64_def_or_undef (bool def_p, const char *macro, cpp_reader *pfile)
+{
+  if (def_p)
+    cpp_define (pfile, macro);
+  else
+    cpp_undef (pfile, macro);
+}
+
+/* Define the macros that we always expect to have on AArch64.  */
+
+static void
+aarch64_define_unconditional_macros (cpp_reader *pfile)
+{
+  builtin_define ("__aarch64__");
+  builtin_define ("__ARM_64BIT_STATE");
+
+  builtin_define ("__ARM_ARCH_ISA_A64");
+  builtin_define_with_int_value ("__ARM_ALIGN_MAX_PWR", 28);
+  builtin_define_with_int_value ("__ARM_ALIGN_MAX_STACK_PWR", 16);
+
+  /* __ARM_ARCH_8A is not mandated by ACLE but we define it unconditionally
+     as interoperability with the same arm macro.  */
+  builtin_define ("__ARM_ARCH_8A");
+
+  builtin_define_with_int_value ("__ARM_ARCH_PROFILE", 'A');
+  builtin_define ("__ARM_FEATURE_CLZ");
+  builtin_define ("__ARM_FEATURE_IDIV");
+  builtin_define ("__ARM_FEATURE_UNALIGNED");
+  builtin_define ("__ARM_PCS_AAPCS64");
+  builtin_define_with_int_value ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);
+
+}
+
+/* Undefine/redefine macros that depend on the current backend state and may
+   need to change when a target pragma modifies the backend state.  */
+
+static void
+aarch64_update_cpp_builtins (cpp_reader *pfile)
+{
+  aarch64_def_or_undef (flag_unsafe_math_optimizations, "__ARM_FP_FAST", pfile);
+
+  builtin_define_with_int_value ("__ARM_ARCH", aarch64_architecture_version);
+
+  builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
+				 flag_short_enums ? 1 : 4);
+  aarch64_def_or_undef (TARGET_BIG_END, "__AARCH64EB__", pfile);
+  aarch64_def_or_undef (TARGET_BIG_END, "__ARM_BIG_ENDIAN", pfile);
+  aarch64_def_or_undef (!TARGET_BIG_END, "__AARCH64EL__", pfile);
+
+  aarch64_def_or_undef (TARGET_FLOAT, "__ARM_FEATURE_FMA", pfile);
+
+  if (TARGET_FLOAT || TARGET_SIMD)
+    {
+      builtin_define_with_int_value ("__ARM_FP", 0x0E);
+      builtin_define ("__ARM_FP16_FORMAT_IEEE");
+      builtin_define ("__ARM_FP16_ARGS");
+    }
+  else
+    cpp_undef (pfile, "__ARM_FP");
+
+  aarch64_def_or_undef (TARGET_SIMD, "__ARM_FEATURE_NUMERIC_MAXMIN", pfile);
+  aarch64_def_or_undef (TARGET_SIMD, "__ARM_NEON", pfile);
+
+
+  aarch64_def_or_undef (TARGET_CRC32, "__ARM_FEATURE_CRC32", pfile);
+
+  cpp_undef (pfile, "__AARCH64_CMODEL_TINY__");
+  cpp_undef (pfile, "__AARCH64_CMODEL_SMALL__");
+  cpp_undef (pfile, "__AARCH64_CMODEL_LARGE__");
+
+  switch (aarch64_cmodel)
+    {
+      case AARCH64_CMODEL_TINY:
+      case AARCH64_CMODEL_TINY_PIC:
+	builtin_define ("__AARCH64_CMODEL_TINY__");
+	break;
+      case AARCH64_CMODEL_SMALL:
+      case AARCH64_CMODEL_SMALL_PIC:
+	builtin_define ("__AARCH64_CMODEL_SMALL__");
+	break;
+      case AARCH64_CMODEL_LARGE:
+	builtin_define ("__AARCH64_CMODEL_LARGE__");
+	break;
+      default:
+	break;
+    }
+
+  aarch64_def_or_undef (TARGET_ILP32, "_ILP32", pfile);
+  aarch64_def_or_undef (TARGET_ILP32, "__ILP32__", pfile);
+
+  aarch64_def_or_undef (TARGET_CRYPTO, "__ARM_FEATURE_CRYPTO", pfile);
+}
+
+/* Implement TARGET_CPU_CPP_BUILTINS.  */
+
+void
+aarch64_cpu_cpp_builtins (cpp_reader *pfile)
+{
+  aarch64_define_unconditional_macros (pfile);
+  aarch64_update_cpp_builtins (pfile);
+}
+
+/* Hook to validate the current #pragma GCC target and set the state, and
+   update the macros based on what was changed.  If ARGS is NULL, then
+   POP_TARGET is used to reset the options.  */
+
+static bool
+aarch64_pragma_target_parse (tree args, tree pop_target)
+{
+  /* If args is not NULL then process it and setup the target-specific
+     information that it specifies.  */
+  if (args)
+    {
+      if (!aarch64_process_target_attr (args, "pragma"))
+	return false;
+
+      aarch64_override_options_internal (&global_options);
+    }
+
+  /* args is NULL, restore to the state described in pop_target.  */
+  else
+    {
+      pop_target = pop_target ? pop_target : target_option_default_node;
+      cl_target_option_restore (&global_options,
+				TREE_TARGET_OPTION (pop_target));
+    }
+
+  target_option_current_node
+    = build_target_option_node (&global_options);
+
+  aarch64_reset_previous_fndecl ();
+  /* For the definitions, ensure all newly defined macros are considered
+     as used for -Wunused-macros.  There is no point warning about the
+     compiler predefined macros.  */
+  cpp_options *cpp_opts = cpp_get_options (parse_in);
+  unsigned char saved_warn_unused_macros = cpp_opts->warn_unused_macros;
+  cpp_opts->warn_unused_macros = 0;
+
+  aarch64_update_cpp_builtins (parse_in);
+
+  cpp_opts->warn_unused_macros = saved_warn_unused_macros;
+
+  return true;
+}
+
+/* Implement REGISTER_TARGET_PRAGMAS.  */
+
+void
+aarch64_register_pragmas (void)
+{
+  /* Update pragma hook to allow parsing #pragma GCC target.  */
+  targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
+}
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 3a5482d..6844c90 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -249,6 +249,7 @@  enum aarch64_symbol_type
 aarch64_classify_symbolic_expression (rtx, enum aarch64_symbol_context);
 bool aarch64_const_vec_all_same_int_p (rtx, HOST_WIDE_INT);
 bool aarch64_constant_address_p (rtx);
+extern void aarch64_cpu_cpp_builtins (cpp_reader *);
 bool aarch64_expand_movmem (rtx *);
 bool aarch64_float_const_zero_rtx_p (rtx);
 bool aarch64_function_arg_regno_p (unsigned);
@@ -323,6 +324,8 @@  void aarch64_init_expanders (void);
 void aarch64_print_operand (FILE *, rtx, char);
 void aarch64_print_operand_address (FILE *, rtx);
 void aarch64_emit_call_insn (rtx);
+void aarch64_register_pragmas (void);
+void aarch64_reset_previous_fndecl (void);
 
 /* Initialize builtins for SIMD intrinsics.  */
 void init_aarch64_simd_builtins (void);
@@ -360,6 +363,10 @@  bool aarch64_gen_adjusted_ldpstp (rtx *, bool, enum machine_mode, RTX_CODE);
 #endif /* RTX_CODE */
 
 void aarch64_init_builtins (void);
+
+bool aarch64_process_target_attr (tree, const char*);
+void aarch64_override_options_internal (struct gcc_options *);
+
 rtx aarch64_expand_builtin (tree exp,
 			    rtx target,
 			    rtx subtarget ATTRIBUTE_UNUSED,
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 7fdcffa..addcc5c 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -7524,7 +7524,7 @@  aarch64_override_options_after_change_1 (struct gcc_options *opts)
     as all the other target-specific codegen decisions are
     derived from them.  */
 
-static void
+void
 aarch64_override_options_internal (struct gcc_options *opts)
 {
   aarch64_tune_flags = selected_tune->flags;
@@ -7915,6 +7915,12 @@  aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr)
 
 static GTY(()) tree aarch64_previous_fndecl;
 
+void
+aarch64_reset_previous_fndecl (void)
+{
+  aarch64_previous_fndecl = NULL;
+}
+
 /* Implement TARGET_SET_CURRENT_FUNCTION.  Unpack the codegen decisions
    like tuning and ISA features from the DECL_FUNCTION_SPECIFIC_TARGET
    of the function, if such exists.  This function may be called multiple
@@ -8118,6 +8124,14 @@  aarch64_handle_attr_isa_flags (char *str, const char *pragma_or_attr)
   enum aarch64_parse_opt_result parse_res;
   unsigned long isa_flags = aarch64_isa_flags;
 
+  /* We allow "+nothing" in the beginning to clear out all architectural
+     features if the user wants to handpick specific features.  */
+  if (strncmp ("+nothing", str, 8) == 0)
+    {
+      isa_flags = 0;
+      str += 8;
+    }
+
   parse_res = aarch64_parse_extension (str, &isa_flags);
 
   if (parse_res == AARCH64_PARSE_OK)
diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
index 41f50fe..721927f 100644
--- a/gcc/config/aarch64/aarch64.h
+++ b/gcc/config/aarch64/aarch64.h
@@ -23,85 +23,13 @@ 
 #define GCC_AARCH64_H
 
 /* Target CPU builtins.  */
-#define TARGET_CPU_CPP_BUILTINS()			\
-  do							\
-    {							\
-      builtin_define ("__aarch64__");                   \
-      builtin_define ("__ARM_64BIT_STATE");             \
-      builtin_define_with_int_value                     \
-        ("__ARM_ALIGN_MAX_PWR", 28);                    \
-      builtin_define_with_int_value                     \
-        ("__ARM_ALIGN_MAX_STACK_PWR", 16);              \
-      builtin_define_with_int_value                     \
-        ("__ARM_ARCH", aarch64_architecture_version);   \
-      builtin_define ("__ARM_ARCH_8A");                   \
-      builtin_define ("__ARM_ARCH_ISA_A64");            \
-      builtin_define_with_int_value                     \
-        ("__ARM_ARCH_PROFILE", 'A');                    \
-      builtin_define ("__ARM_FEATURE_CLZ");             \
-      builtin_define ("__ARM_FEATURE_IDIV");            \
-      builtin_define ("__ARM_FEATURE_UNALIGNED");       \
-      if (flag_unsafe_math_optimizations)               \
-        builtin_define ("__ARM_FP_FAST");               \
-      builtin_define ("__ARM_PCS_AAPCS64");             \
-      builtin_define_with_int_value                     \
-        ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8);  \
-      builtin_define_with_int_value                     \
-        ("__ARM_SIZEOF_MINIMAL_ENUM",                   \
-         flag_short_enums? 1 : 4);                      \
-      if (TARGET_BIG_END)				\
-        {                                               \
-          builtin_define ("__AARCH64EB__");             \
-          builtin_define ("__ARM_BIG_ENDIAN");          \
-        }                                               \
-      else						\
-	builtin_define ("__AARCH64EL__");		\
-							\
-      if (TARGET_FLOAT)                                         \
-        {                                                       \
-          builtin_define ("__ARM_FEATURE_FMA");                 \
-	  builtin_define_with_int_value ("__ARM_FP", 0x0E);     \
-	  builtin_define ("__ARM_FP16_FORMAT_IEEE");		\
-	  builtin_define ("__ARM_FP16_ARGS");			\
-        }                                                       \
-      if (TARGET_SIMD)                                          \
-        {                                                       \
-          builtin_define ("__ARM_FEATURE_NUMERIC_MAXMIN");      \
-          builtin_define ("__ARM_NEON");			\
-          builtin_define_with_int_value ("__ARM_NEON_FP", 0x0C);\
-        }                                                       \
-							        \
-      if (TARGET_CRC32)				        \
-	builtin_define ("__ARM_FEATURE_CRC32");		\
-							\
-      switch (aarch64_cmodel)				\
-	{						\
-	  case AARCH64_CMODEL_TINY:			\
-	  case AARCH64_CMODEL_TINY_PIC:			\
-	    builtin_define ("__AARCH64_CMODEL_TINY__");	\
-	    break;					\
-	  case AARCH64_CMODEL_SMALL:			\
-	  case AARCH64_CMODEL_SMALL_PIC:		\
-	    builtin_define ("__AARCH64_CMODEL_SMALL__");\
-	    break;					\
-	  case AARCH64_CMODEL_LARGE:			\
-	    builtin_define ("__AARCH64_CMODEL_LARGE__");	\
-	    break;					\
-	  default:					\
-	    break;					\
-	}						\
-							\
-      if (TARGET_ILP32)					\
-	{						\
-	  cpp_define (parse_in, "_ILP32");		\
-	  cpp_define (parse_in, "__ILP32__");		\
-	}						\
-      if (TARGET_CRYPTO)				\
-	builtin_define ("__ARM_FEATURE_CRYPTO");	\
-    } while (0)
+#define TARGET_CPU_CPP_BUILTINS()	\
+  aarch64_cpu_cpp_builtins (pfile)
 
 
 
+#define REGISTER_TARGET_PRAGMAS() aarch64_register_pragmas ()
+
 /* Target machine storage layout.  */
 
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)	\
diff --git a/gcc/config/aarch64/arm_acle.h b/gcc/config/aarch64/arm_acle.h
index 7af4ad2..addbc6a 100644
--- a/gcc/config/aarch64/arm_acle.h
+++ b/gcc/config/aarch64/arm_acle.h
@@ -28,11 +28,15 @@ 
 #define _GCC_ARM_ACLE_H
 
 #include <stdint.h>
+
+#pragma GCC push_options
+
+#pragma GCC target ("+nothing+crc")
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#ifdef __ARM_FEATURE_CRC32
 __extension__ static __inline uint32_t __attribute__ ((__always_inline__))
 __crc32b (uint32_t __a, uint8_t __b)
 {
@@ -81,10 +85,10 @@  __crc32d (uint32_t __a, uint64_t __b)
   return __builtin_aarch64_crc32x (__a, __b);
 }
 
-#endif
-
 #ifdef __cplusplus
 }
 #endif
 
+#pragma GCC pop_options
+
 #endif
diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
index fce5577..f5d183f 100644
--- a/gcc/config/aarch64/arm_neon.h
+++ b/gcc/config/aarch64/arm_neon.h
@@ -27,9 +27,8 @@ 
 #ifndef _AARCH64_NEON_H_
 #define _AARCH64_NEON_H_
 
-#ifndef __ARM_NEON
-#error You must enable AdvancedSIMD instructions to use arm_neon.h
-#else
+#pragma GCC push_options
+#pragma GCC target ("+nothing+simd")
 
 #include <stdint.h>
 
@@ -11414,8 +11413,8 @@  vbslq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c)
   return __builtin_aarch64_simd_bslv2di_uuuu (__a, __b, __c);
 }
 
-#ifdef __ARM_FEATURE_CRYPTO
-
+#pragma GCC push_options
+#pragma GCC target ("+crypto")
 /* vaes  */
 
 __extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
@@ -11441,8 +11440,7 @@  vaesimcq_u8 (uint8x16_t data)
 {
   return __builtin_aarch64_crypto_aesimcv16qi_uu (data);
 }
-
-#endif
+#pragma GCC pop_options
 
 /* vcage  */
 
@@ -21067,7 +21065,8 @@  vrsrad_n_u64 (uint64_t __a, uint64_t __b, const int __c)
   return __builtin_aarch64_ursra_ndi_uuus (__a, __b, __c);
 }
 
-#ifdef __ARM_FEATURE_CRYPTO
+#pragma GCC push_options
+#pragma GCC target ("+crypto")
 
 /* vsha1  */
 
@@ -21144,7 +21143,7 @@  vmull_high_p64 (poly64x2_t a, poly64x2_t b)
   return __builtin_aarch64_crypto_pmullv2di_ppp (a, b);
 }
 
-#endif
+#pragma GCC pop_options
 
 /* vshl */
 
@@ -24912,6 +24911,6 @@  __INTERLEAVE_LIST (zip)
 #undef __aarch64_vdupq_laneq_u32
 #undef __aarch64_vdupq_laneq_u64
 
-#endif
+#pragma GCC pop_options
 
 #endif
diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
index af154f4..782853b 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -48,6 +48,11 @@  aarch-common.o: $(srcdir)/config/arm/aarch-common.c $(CONFIG_H) $(SYSTEM_H) \
 	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
 		$(srcdir)/config/arm/aarch-common.c
 
+aarch64-c.o: $(srcdir)/config/aarch64/aarch64-c.c $(CONFIG_H) $(SYSTEM_H) \
+    coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+	$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+		$(srcdir)/config/aarch64/aarch64-c.c
+
 cortex-a57-fma-steering.o: $(srcdir)/config/aarch64/cortex-a57-fma-steering.c \
     $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(REGS_H) insn-config.h $(RTL_BASE_H) \
     dominance.h cfg.h cfganal.h $(BASIC_BLOCK_H) $(INSN_ATTR_H) $(RECOG_H) \
diff --git a/gcc/testsuite/gcc.target/aarch64/arm_neon-nosimd-error.c b/gcc/testsuite/gcc.target/aarch64/arm_neon-nosimd-error.c
deleted file mode 100644
index 6c508ec..0000000
--- a/gcc/testsuite/gcc.target/aarch64/arm_neon-nosimd-error.c
+++ /dev/null
@@ -1,11 +0,0 @@ 
-/* { dg-do compile } */
-/* { dg-options "-mgeneral-regs-only" } */
-/* { dg-excess-errors "You must enable" } */
-
-#include "arm_neon.h"
-
-int
-foo ()
-{
-  return 0;
-}