Hi All, This patch adds support for the setting the architecture and extensions using the target GCC pragma.
#pragma GCC target ("arch=armv8-a+crc") It also supports a short hand where an extension is just added to the current architecture without changing it #pragma GCC target ("+crc") Popping and pushing options also correctly reconfigure the global state as expected. Also supported is using the __attribute__((target("..."))) attributes on functions to change the architecture or extension. Regtested on arm-none-eabi and no regressions. Ok for trunk? gcc/ 2017-11-06 Tamar Christina <tamar.christ...@arm.com> PR target/82641 * config/arm/arm.c (arm_valid_target_attribute_rec): Parse "arch=" and "+<ext>". (arm_valid_target_attribute_tree): Re-init global options. (arm_option_override): Make non-static. (arm_options_perform_arch_sanity_checks): Make errors fatal. * gcc/config/arm/arm-c.c (__ARM_FEATURE_CMSE): Support undef. (__ARM_FEATURE_CRC32): Support undef. * config/arm/arm_acle.h (__ARM_FEATURE_CRC32): Replace with pragma. * doc/extend.texi (ARM Function Attributes): Add pragma and target. gcc/testsuite/ 2017-11-06 Tamar Christina <tamar.christ...@arm.com> PR target/82641 * gcc.target/arm/pragma_arch_attribute.c: New. --
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index ea47d1746fefb8dfb7981e1817edbf942d37be55..2b308fa2e3d5274682cc32dd9b91712c5604267e 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -3297,6 +3297,7 @@ arm_configure_build_target (struct arm_build_target *target, target->tune_flags = tune_data->tune_flags; target->tune = tune_data->tune; target->tune_core = tune_data->scheduler; + arm_option_reconfigure_globals (); } /* Fix up any incompatible options that the user has specified. */ @@ -30642,7 +30643,7 @@ arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) if (! opt_enum_arg_to_value (OPT_mfpu_, q+4, &fpu_index, CL_TARGET)) { - error ("invalid fpu for attribute(target(\"%s\"))", q); + error ("invalid fpu for target attribute or pragma %qs", q); return false; } if (fpu_index == TARGET_FPU_auto) @@ -30655,9 +30656,29 @@ arm_valid_target_attribute_rec (tree args, struct gcc_options *opts) } opts->x_arm_fpu_index = (enum fpu_type) fpu_index; } + else if (!strncmp (q, "arch=", 5)) + { + char* arch = q+5; + const arch_option *arm_selected_arch + = arm_parse_arch_option_name (all_architectures, "arch", arch); + + if (!arm_selected_arch) + { + error ("invalid architecture for target attribute or pragma %qs", + q); + return false; + } + + opts->x_arm_arch_string = xstrndup (arch, strlen (arch)); + } + else if (q[0] == '+') + { + opts->x_arm_arch_string + = xasprintf ("%s%s", opts->x_arm_arch_string, q); + } else { - error ("attribute(target(\"%s\")) is unknown", q); + error ("unknown target attribute or pragma %qs", q); return false; } } @@ -30679,7 +30700,10 @@ arm_valid_target_attribute_tree (tree args, struct gcc_options *opts, cl_target_option_save (&cl_opts, opts); arm_configure_build_target (&arm_active_target, &cl_opts, opts_set, false); arm_option_check_internal (opts); - /* Do any overrides, such as global options arch=xxx. */ + /* Do any overrides, such as global options arch=xxx. + We do this since arm_active_target was overridden. */ + arm_option_reconfigure_globals (); + arm_options_perform_arch_sanity_checks (); arm_option_override_internal (opts, opts_set); return build_target_option_node (opts); diff --git a/gcc/config/arm/arm_acle.h b/gcc/config/arm/arm_acle.h index 972e28edb86c1f137e16982acc6f346e0eac04fb..ad28a45866df8dadd7d4c830efc7e8494f41716a 100644 --- a/gcc/config/arm/arm_acle.h +++ b/gcc/config/arm/arm_acle.h @@ -173,7 +173,10 @@ __arm_mrrc2 (const unsigned int __coproc, const unsigned int __opc1, #endif /* __ARM_ARCH >= 5. */ #endif /* (!__thumb__ || __thumb2__) && __ARM_ARCH >= 4. */ -#ifdef __ARM_FEATURE_CRC32 +#pragma GCC push_options +#if __ARM_ARCH >= 8 +#pragma GCC target ("arch=armv8-a+crc") + __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) __crc32b (uint32_t __a, uint8_t __b) { @@ -232,7 +235,8 @@ __crc32cd (uint32_t __a, uint64_t __b) } #endif -#endif +#endif /* __ARM_ARCH >= 8. */ +#pragma GCC pop_options #ifdef __cplusplus } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 8aa443f87fb700f7a723d736bdbd53b6c839656d..18d0ffa6820326ce7badf33001b1c6a467c95883 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -3858,6 +3858,42 @@ Specifies the fpu for which to tune the performance of this function. The behavior and permissible arguments are the same as for the @option{-mfpu=} command-line option. +@item arch= +@cindex @code{arch=} function attribute, ARM +Specifies the architecture version and architectural extensions to use +for this function. The behavior and permissible arguments are the same as +for the @option{-march=} command-line option. + +The above target attributes can be specified as follows: + +@smallexample +__attribute__((target("@var{attr-string}"))) +int +f (int a) +@{ + return a + 5; +@} +@end smallexample + +where @code{@var{attr-string}} is one of the attribute strings. + +Additionally, the architectural extension string may be specified on its +own. This can be used to turn on and off particular architectural extensions +without having to specify a particular architecture version or core. Example: + +@smallexample +__attribute__((target("+crc+nocrypto"))) +int +foo (int a) +@{ + return a + 5; +@} +@end smallexample + +In this example @code{target("+crc+nocrypto")} enables the @code{crc} +extension and disables the @code{crypto} extension for the function @code{foo} +without modifying an existing @option{-march=} or @option{-mcpu} option. + @end table @end table diff --git a/gcc/testsuite/gcc.target/arm/pragma_arch_attribute.c b/gcc/testsuite/gcc.target/arm/pragma_arch_attribute.c new file mode 100644 index 0000000000000000000000000000000000000000..a06dbf04037384e98b6b9eaf5ab90b04a09a6d07 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pragma_arch_attribute.c @@ -0,0 +1,54 @@ +/* Test for #pragma target macros. */ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_arch_v8a_ok } */ +/* { dg-add-options arm_arch_v8a } */ + +#include <arm_acle.h> + +#ifdef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is already defined." +#endif + +#pragma GCC push_options +#pragma GCC target ("arch=armv8-a+crc") +#ifndef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is not defined in push 1." +#endif +#pragma GCC pop_options + +#ifdef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is defined after pop 1." +#endif + +#pragma GCC push_options +#pragma GCC target ("+crc") +#ifndef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is not defined in push 2." +#endif +#pragma GCC pop_options + +#ifdef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is defined after pop 2." +#endif + +__attribute__((target("+crc"))) +void test_crc_unknown_ok_attr_1 () +{ + __crc32b (0, 0); +} + +#ifdef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is defined after attribute set 1." +#endif + +__attribute__((target("arch=armv8-a+crc"))) +void test_crc_unknown_ok_attr_2 () +{ + __crc32b (0, 0); +} + +#ifdef __ARM_FEATURE_CRC32 +# error "__ARM_FEATURE_CRC32 is defined after attribute set 2." +#endif + +#pragma GCC reset_options \ No newline at end of file