Hi Kyrill,
Thanks for the review,
I have respun the patch on top of trunk and
here is the new changelog to account for the
updates of the new extensions.
Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
Ok for trunk?
Thanks,
Tamar
gcc/ChangeLog:
2019-01-15 Tamar Christina <[email protected]>
PR target/88530
* common/config/aarch64/aarch64-common.c
(struct aarch64_option_extension): Add is_synthetic.
(all_extensions): Use it.
(TARGET_OPTION_INIT_STRUCT): Define hook.
(struct gcc_targetm_common): Moved to end.
(all_extensions_by_on): New.
(opt_ext_cmp, typedef opt_ext): New.
(aarch64_option_init_struct): New.
(aarch64_contains_opt): New.
(aarch64_get_extension_string_for_isa_flags): Output smallest set.
* config/aarch64/aarch64-option-extensions.def
(AARCH64_OPT_EXTENSION): Explicitly include AES and SHA2 in crypto.
(fp, simd, crc, lse, fp16, rcpc, rdma, dotprod, aes, sha2, sha3,
sm4, fp16fml, sve, profile, rng, memtag, sb, ssbs, predres):
Set is_synthetic to false.
(crypto): Set is_synthetic to true.
gcc/testsuite/ChangeLog:
2019-01-15 Tamar Christina <[email protected]>
PR target/88530
* gcc.target/aarch64/options_set_1.c: New test.
* gcc.target/aarch64/options_set_2.c: New test.
* gcc.target/aarch64/options_set_3.c: New test.
* gcc.target/aarch64/options_set_4.c: New test.
* gcc.target/aarch64/options_set_5.c: New test.
* gcc.target/aarch64/options_set_6.c: New test.
* gcc.target/aarch64/options_set_7.c: New test.
* gcc.target/aarch64/options_set_8.c: New test.
* gcc.target/aarch64/options_set_9.c: New test.
The 01/10/2019 17:15, Kyrill Tkachov wrote:
> Hi Tamar,
>
> On 17/12/18 19:18, Tamar Christina wrote:
> > Hi All,
> >
> > The options don't seem to get canonicalized into the smallest possible set
> > before output to the assembler. This means that overlapping feature sets are
> > emitted with superfluous parts.
> >
> > Normally this isn't an issue, but in the case of crypto we have
> > retro-actively
> > split it into aes and sha2. We need to emit only +crypto to the assembler
> > so old assemblers continue to work.
> >
> > Because of how -mcpu=native and -march=native work they end up enabling all
> > feature
> > bits, so we need to get the smallest possible set, which would also fix the
> > problem with older the assemblers and the retro-active split.
> >
> > Admittedly this should be done earlier in options processing, but the
> > problem
> > with the way AArch64 currently processes options is that where the isa_bits
> > are
> > determined we don't know which options are part of the default set yet.
> >
> > Which is why we instead do it late in processing when we have all the
> > information. This however requires us to make a duplicate of the extensions
> > list.
> >
> > The Option handling structures have been extended to have a boolean to
> > indicate
> > whether the option is synthetic, with that I mean if the option flag itself
> > has a bit.
> >
> > e.g. +crypto isn't an actual bit, it just enables other bits, but other
> > features flags
> > like +rdma also enable multiple options but are themselves also a feature.
> >
> > There are two ways to solve this.
> >
> > 1) Either have the options that are feature bits also turn themselves on,
> > e.g. change
> > rdma to turn on FP, SIMD and RDMA as dependency bits.
> > 2) Make a distinction between these two different type of features and have
> > the framework
> > handle it correctly.
> >
> > Even though it's more code I went for the second approach, as it's the one
> > that'll be less
> > fragile and give the least surprises.
> >
> > This is a stop-gap measure that's has the lowest impact and is
> > back-portable.
> >
> > Effectively this patch changes the following:
> >
> > The values before the => are the old compiler and after the => the new code.
> >
> > -march=armv8.2-a+crypto+sha2 => -march=armv8.2-a+crypto
> > -march=armv8.2-a+sha2+aes => -march=armv8.2-a+crypto
> >
> > The remaining behaviors stay the same.
> >
> >
> > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> >
> > Ok for trunk?
> >
>
> This will need rebasing over the Armv8.5-A patches as there are new entries
> in config/aarch64/aarch64-option-extensions.def.
> Since this has to be done anyway, I've also pointed out a few comment typos
> inline.
>
> Apart from that, the patch looks good to me (this is a subtle area of GCC).
>
> Thanks,
> Kyrill
>
>
> > Thanks,
> > Tamar
> >
> > gcc/ChangeLog:
> >
> > 2018-12-17 Tamar Christina <[email protected]>
> >
> > PR target/88530
> > * common/config/aarch64/aarch64-common.c
> > (struct aarch64_option_extension): Add is_synthetic.
> > (all_extensions): Use it.
> > (TARGET_OPTION_INIT_STRUCT): Define hook.
> > (struct gcc_targetm_common): Moved to end.
> > (all_extensions_by_on): New.
> > (opt_ext_cmp, typedef opt_ext): New.
> > (aarch64_option_init_struct): New.
> > (aarch64_contains_opt): New.
> > (aarch64_get_extension_string_for_isa_flags): Output smallest set.
> > * config/aarch64/aarch64-option-extensions.def
> > (AARCH64_OPT_EXTENSION): Explicitly include AES and SHA2 in crypto.
> > (fp, simd, crc, lse, fp16, rcpc, rdma, dotprod, aes, sha2, sha3,
> > sm4, fp16fml, sve, profile): Set is_synthetic to false.
> > (crypto): Set is_synthetic to true.
> >
> > gcc/testsuite/ChangeLog:
> >
> > 2018-12-17 Tamar Christina <[email protected]>
> >
> > PR target/88530
> > * gcc.target/aarch64/options_set_1.c: New test.
> > * gcc.target/aarch64/options_set_2.c: New test.
> > * gcc.target/aarch64/options_set_3.c: New test.
> > * gcc.target/aarch64/options_set_4.c: New test.
> > * gcc.target/aarch64/options_set_5.c: New test.
> > * gcc.target/aarch64/options_set_6.c: New test.
> > * gcc.target/aarch64/options_set_7.c: New test.
> > * gcc.target/aarch64/options_set_8.c: New test.
> > * gcc.target/aarch64/options_set_9.c: New test.
> >
> > --
>
> diff --git a/gcc/common/config/aarch64/aarch64-common.c
> b/gcc/common/config/aarch64/aarch64-common.c
> index
> dd7d42673402c3cf16ebce009d263d62d574690a..d14237d229fd958c940aee32d3d6404b04cc137e
> 100644
> --- a/gcc/common/config/aarch64/aarch64-common.c
> +++ b/gcc/common/config/aarch64/aarch64-common.c
> @@ -46,6 +46,8 @@
> #define TARGET_OPTION_DEFAULT_PARAMS aarch64_option_default_params
> #undef TARGET_OPTION_VALIDATE_PARAM
> #define TARGET_OPTION_VALIDATE_PARAM aarch64_option_validate_param
> +#undef TARGET_OPTION_INIT_STRUCT
> +#define TARGET_OPTION_INIT_STRUCT aarch64_option_init_struct
>
> /* Set default optimization options. */
> static const struct default_options aarch_option_optimization_table[] =
> @@ -164,8 +166,6 @@ aarch64_handle_option (struct gcc_options *opts,
> }
> }
>
> -struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
> -
> /* An ISA extension in the co-processor and main instruction set space. */
> struct aarch64_option_extension
> {
> @@ -173,15 +173,28 @@ struct aarch64_option_extension
> const unsigned long flag_canonical;
> const unsigned long flags_on;
> const unsigned long flags_off;
> + const bool is_synthetic;
> };
>
> /* ISA extensions in AArch64. */
> static const struct aarch64_option_extension all_extensions[] =
> {
> -#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
> - {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
> +#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
> + SYNTHETIC, Z) \
> + {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
> #include "config/aarch64/aarch64-option-extensions.def"
> - {NULL, 0, 0, 0}
> + {NULL, 0, 0, 0, false}
> +};
> +
> +/* A copy of the ISA extensions list for AArch64 sorted by the popcount of
> + bits and extension turned on. Cached for efficiency. */
> +static struct aarch64_option_extension all_extensions_by_on[] =
> +{
> +#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
> + SYNTHETIC, Z) \
> + {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
> +#include "config/aarch64/aarch64-option-extensions.def"
> + {NULL, 0, 0, 0, false}
> };
>
> struct processor_name_to_arch
> @@ -298,6 +311,69 @@ aarch64_get_all_extension_candidates (auto_vec<const
> char *> *candidates)
> candidates->safe_push (opt->name);
> }
>
> +/* Comparer to sort aarch64's feature extensions by population count. Largest
> + first. */
> +
> +typedef const struct aarch64_option_extension opt_ext;
> +
> +int opt_ext_cmp (const void* a, const void* b)
> +{
> + opt_ext *opt_a = (opt_ext *)a;
> + opt_ext *opt_b = (opt_ext *)b;
> + /* We consider an option to set the bit it turns on, and the other flags it
> + turns on as well. */
> + unsigned long total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
> + unsigned long total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
> + int popcnt_a = popcount_hwi ((HOST_WIDE_INT)total_flags_a);
> + int popcnt_b = popcount_hwi ((HOST_WIDE_INT)total_flags_b);
> + int order = popcnt_b - popcnt_a;
> +
> + /* If they have the same amount of bits set, try to give it a more
> + deterministic ordering by using the value of the bits themselves. */
> + if (order == 0)
> + return total_flags_b - total_flags_a;
> +
> + return order;
> +}
> +
> +/* Implement TARGET_OPTION_INIT_STRUCT. */
> +
> +static void
> +aarch64_option_init_struct (struct gcc_options *opts ATTRIBUTE_UNUSED)
> +{
> + /* Sort the extensions based on how many bits they set, order the larger
> + bits first. */
> + int n_extensions
> + = sizeof (all_extensions) / sizeof (struct aarch64_option_extension);
> + qsort (&all_extensions_by_on, n_extensions,
> + sizeof (struct aarch64_option_extension), opt_ext_cmp);
> +}
> +
> +/* Checks to see if enough bits from the option OPT is enabled in
>
> "is enabled" -> "are enabled"
>
> + ISA_FLAG_BITS to be able to replace the invididual options with the
>
> "individual"
>
> + canonicalized version of the option. The rules are a bit tricky as we
> have
> + two kinds of options.
> +
> + 1) Synthetic groups, such as +crypto which on their own don't have a
> feature
> + bit but turn on multiple bits. These kind of options should be used
> when
> + ever the bits they turn on are all available.
> +
> + 2) Options that themselves have a bit, such as +rdma, in this case, all
> the
> + feature bits they turn on must be available and the bit for the option
> + itself must be. In this case it's effectively a reduction rather than
> a
> + grouping.
> +*/
> +
> +static bool
> +aarch64_contains_opt (unsigned long isa_flag_bits, opt_ext *opt)
> +{
> + unsigned long flags_check = opt->flags_on;
> + if (!opt->is_synthetic)
> + flags_check |= opt->flag_canonical;
> +
> + return (isa_flag_bits & flags_check) == flags_check;
> +}
> +
> /* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
> gives the default set of flags which are implied by whatever -march
> we'd put out. Our job is to figure out the minimal set of "+" and
> @@ -311,27 +387,49 @@ aarch64_get_extension_string_for_isa_flags (unsigned
> long isa_flags,
> const struct aarch64_option_extension *opt = NULL;
> std::string outstr = "";
>
> - /* Pass one: Find all the things we need to turn on. As a special case,
> - we always want to put out +crc if it is enabled. */
> - for (opt = all_extensions; opt->name != NULL; opt++)
> - if ((isa_flags & opt->flag_canonical
> + unsigned long isa_flag_bits = isa_flags;
> +
> + /* Pass one: For the bits that turn on multiple bits, remove the invidual
> bits
>
> "individual" again.
>
> + it they are all present. The option on it's own is enough to trigger
> their
> + inclusion. */
> + for (opt = all_extensions_by_on; opt->name != NULL; opt++)
> + if ((popcount_hwi ((HOST_WIDE_INT)opt->flags_on) > 1
> + && aarch64_contains_opt (isa_flag_bits, opt)
> + && !(default_arch_flags & opt->flag_canonical)))
> + {
> + isa_flag_bits &= ~opt->flags_on;
> + isa_flag_bits |= opt->flag_canonical;
> + }
> +
> + /* Pass two: Find all the things we need to turn on. As a special case,
> + we always want to put out +crc if it is enabled. Once a bit has been
> + "claimed" but an option we clear it so another option doesn't get set
>
> "but" -> "by"?
>
> + due to it. This relies on the options being processed in order of
> largest
> + population to smallest. */
> + for (opt = all_extensions_by_on; opt->name != NULL; opt++)
> + if ((isa_flag_bits & opt->flag_canonical
> && !(default_arch_flags & opt->flag_canonical))
> || (default_arch_flags & opt->flag_canonical
> && opt->flag_canonical == AARCH64_ISA_CRC))
> {
> outstr += "+";
> outstr += opt->name;
> + isa_flag_bits &= ~(opt->flag_canonical | opt->flags_on);
> }
>
> - /* Pass two: Find all the things we need to turn off. */
> - for (opt = all_extensions; opt->name != NULL; opt++)
> + /* Pass three: Find all the things we need to turn off, we aim to give the
> + small-ish set possible by looking at the amount of things the feature
> turns
> + on. By reasoning it probably also turns off a bunch of things when you
> + turn it off. Unlike the above we don't care about the smallest set in
> this
> + case as "+no" flags are rarely passed along to the assembler. */
> + for (opt = all_extensions_by_on; opt->name != NULL; opt++)
> if ((~isa_flags) & opt->flag_canonical
> && !((~default_arch_flags) & opt->flag_canonical))
> {
> outstr += "+no";
> outstr += opt->name;
> + isa_flags &= ~(opt->flag_canonical | opt->flags_off);
> }
> -
> return outstr;
> }
>
> @@ -411,5 +509,7 @@ aarch64_rewrite_mcpu (int argc, const char **argv)
> return aarch64_rewrite_selected_cpu (argv[argc - 1]);
> }
>
> +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
> +
> #undef AARCH64_CPU_NAME_LENGTH
>
> diff --git a/gcc/config/aarch64/aarch64-option-extensions.def
> b/gcc/config/aarch64/aarch64-option-extensions.def
> index
> 69ab796a4e1a959b89ebb55b599919c442cfb088..cdf04e2d5fcccb8b9a32af8f83501ce23212bbab
> 100644
> --- a/gcc/config/aarch64/aarch64-option-extensions.def
> +++ b/gcc/config/aarch64/aarch64-option-extensions.def
> @@ -30,6 +30,13 @@
> FLAGS_OFF are the bitwise-or of the features that disabling the extension
> removes, or zero if disabling this extension has no effect on other
> features.
> + SYNTHETIC is a boolean to indicate whether the option is a purely
> synthetic
> + grouping of options and that the option itself has no feature bit (e.g.
> + crypto). This is used to determine when sum of the individual options in
> + FLAGS_ON can be replaced by FLAG_CANONICAL in options minimization. If
> the
> + group is synthetic then they can be replaced when all options in FLAGS_ON
> + are enabled, otherwise they can only replaced when FLAGS_ON |
> FLAG_CANONICAL
>
> "can only replaced" -> "can only be replaced"
>
> + are enabled.
> FEAT_STRING is a string containing the entries in the 'Features' field of
> /proc/cpuinfo on a GNU/Linux system that correspond to this architecture
> extension being available. Sometimes multiple entries are needed to
> enable
> @@ -43,7 +50,8 @@
> "sha3", sm3/sm4 and "sve". */
> AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD |
> AARCH64_FL_CRYPTO |\
> AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 |\
> - AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, "fp")
> + AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, \
> + false, "fp")
>
> /* Enabling "simd" also enables "fp".
> Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2",
> "sha3",
> @@ -51,61 +59,71 @@ AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0,
> AARCH64_FL_SIMD | AARCH64_FL_CRYPT
> AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP,
> AARCH64_FL_CRYPTO |\
> AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 |\
> AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE,
> - "asimd")
> + false, "asimd")
>
> -/* Enabling "crypto" also enables "fp" and "simd".
> +/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
> Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and
> "sm3/sm4". */
> -AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP |
> AARCH64_FL_SIMD,\
> +AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO,
> + AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_AES |\
> + AARCH64_FL_SHA2,\
> AARCH64_FL_AES | AARCH64_FL_SHA2 |AARCH64_FL_SHA3 |
> AARCH64_FL_SM4,\
> - "aes pmull sha1 sha2")
> + true, "aes pmull sha1 sha2")
>
> /* Enabling or disabling "crc" only changes "crc". */
> -AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, "crc32")
> +AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
>
> /* Enabling or disabling "lse" only changes "lse". */
> -AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, "atomics")
> +AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
>
> /* Enabling "fp16" also enables "fp".
> Disabling "fp16" disables "fp16", "fp16fml" and "sve". */
> AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP,
> - AARCH64_FL_F16FML | AARCH64_FL_SVE, "fphp asimdhp")
> + AARCH64_FL_F16FML | AARCH64_FL_SVE, false, "fphp asimdhp")
>
> /* Enabling or disabling "rcpc" only changes "rcpc". */
> -AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, "lrcpc")
> +AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, false, "lrcpc")
>
> /* Enabling "rdma" also enables "fp", "simd".
> Disabling "rdma" just disables "rdma". */
> -AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP |
> AARCH64_FL_SIMD, 0, "asimdrdm")
> +AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, \
> + AARCH64_FL_FP | AARCH64_FL_SIMD, 0, false, "asimdrdm")
>
> /* Enabling "dotprod" also enables "simd".
> Disabling "dotprod" only disables "dotprod". */
> -AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0,
> "asimddp")
> +AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, \
> + false, "asimddp")
>
> /* Enabling "aes" also enables "simd".
> Disabling "aes" just disables "aes". */
> -AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, 0, "aes")
> +AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, 0, false,
> "aes")
>
> /* Enabling "sha2" also enables "simd".
> Disabling "sha2" just disables "sha2". */
> -AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, "sha1
> sha2")
> +AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, \
> + "sha1 sha2")
>
> /* Enabling "sha3" enables "simd" and "sha2".
> Disabling "sha3" just disables "sha3". */
> -AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD |
> AARCH64_FL_SHA2, 0, "sha3 sha512")
> +AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, \
> + AARCH64_FL_SIMD | AARCH64_FL_SHA2, 0, false, \
> + "sha3 sha512")
>
> /* Enabling "sm4" also enables "simd".
> Disabling "sm4" just disables "sm4". */
> -AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, 0, "sm3 sm4")
> +AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, 0, false, \
> + "sm3 sm4")
>
> /* Enabling "fp16fml" also enables "fp" and "fp16".
> Disabling "fp16fml" just disables "fp16fml". */
> -AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP |
> AARCH64_FL_F16, 0, "asimdfml")
> +AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, \
> + AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfml")
>
> /* Enabling "sve" also enables "fp16", "fp" and "simd".
> Disabling "sve" just disables "sve". */
> -AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD
> | AARCH64_FL_F16, 0, "sve")
> +AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD
> | \
> + AARCH64_FL_F16, 0, false, "sve")
>
> /* Enabling/Disabling "profile" does not enable/disable any other feature.
> */
> -AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, "")
> +AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, false, "")
>
> #undef AARCH64_OPT_EXTENSION
> diff --git a/gcc/config/aarch64/driver-aarch64.c
> b/gcc/config/aarch64/driver-aarch64.c
> index
> 4e83c7a7679fa683af221fb5f726bc8da339081e..98f9d7959506338bd6a8524500a168cc22ef5396
> 100644
> --- a/gcc/config/aarch64/driver-aarch64.c
> +++ b/gcc/config/aarch64/driver-aarch64.c
> @@ -36,7 +36,8 @@ struct aarch64_arch_extension
> const char *feat_string;
> };
>
> -#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF,
> FEATURE_STRING) \
> +#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF,
> \
> + SYNTHETIC, FEATURE_STRING) \
> { EXT_NAME, FLAG_CANONICAL, FEATURE_STRING },
> static struct aarch64_arch_extension aarch64_extensions[] =
> {
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_1.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_1.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..40d9a05c905eb07103d3b437b5c1351e8620ab33
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_1.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc} 1 } } */
> +
> +/* Check to see if crc is output by default. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_2.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..3476febce706b34430682e879a4aa3aac8f752db
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a+crypto" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } }
> */
> +
> +/* Check to see if crc and crypto are maintained if crypto specified. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_3.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..4558339f16c19555801899c357c50cedb23c28b0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a+aes+sha2+crypto" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } }
> */
> +
> +/* Check if smallest set is maintained when outputting. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_4.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..15514bfe93e61e63cbce1262ee951358cd22d6ce
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a+aes+sha2" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } }
> */
> +
> +/* Check if individual bits that make up a grouping is specified that only
> the
> + grouping is kept. */
> \ No newline at end of file
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_5.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_5.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..b4c0901195ede4fe0dd71fbe02a47c35e9dedbbd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_5.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a+aes+sha2+nosha2" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes} 1 } } */
> +
> +/* Check if turning off feature bits works correctly and grouping is no
> + longer valid. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_6.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..90a055928a273f06e08124a250e3107ad0704e47
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.2-a+crypto+nosha2" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } }
> */
> +
> +/* Group as a whole was requested to be turned on, crypto itself is a bit
> and so
> + just turning off one feature can't turn it off. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_7.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_7.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..71a2c8a19058c0ec25546085076503d206129e10
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_7.c
> @@ -0,0 +1,11 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.4-a+dotprod" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 } } */
> +
> +/* Checking if enabling default features drops the superfluous bits. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_8.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_8.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..83be1bd7a5c3f2bc8d11a14f2c16415c6a7056f2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_8.c
> @@ -0,0 +1,12 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8.4-a+nodotprod" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 } } */
> +
> +/* Checking if trying to turn off default features propagates the commandline
> + option. */
> diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_9.c
> b/gcc/testsuite/gcc.target/aarch64/options_set_9.c
> new file mode 100644
> index
> 0000000000000000000000000000000000000000..e3c7cdc54ffb0616877260c562354496cfdcb688
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/options_set_9.c
> @@ -0,0 +1,14 @@
> +/* { dg-do compile } */
> +/* { dg-additional-options "-march=armv8-a+simd+fp" } */
> +
> +int main ()
> +{
> + return 0;
> +}
> +
> +/* { dg-final { scan-assembler-times {\.arch armv8\-a} 1 } } */
> +
> + /* Check that grouping of bits that don't form a synthetic group don't turn
> + on the parent. e.g. rdma turns on simd+fp, but simd+fp does not turn on
> + rdma since rdma is it's own group. crypto however turns on aes and sha2
> + and turning on sha2 and eas should turn on crypto!. */
>
>
>
--
diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c
index fd870e187a6634b929bc058f99e768e829008179..45f56ebad5848c646dcb2c5640ddf93a083d2edf 100644
--- a/gcc/common/config/aarch64/aarch64-common.c
+++ b/gcc/common/config/aarch64/aarch64-common.c
@@ -46,6 +46,8 @@
#define TARGET_OPTION_DEFAULT_PARAMS aarch64_option_default_params
#undef TARGET_OPTION_VALIDATE_PARAM
#define TARGET_OPTION_VALIDATE_PARAM aarch64_option_validate_param
+#undef TARGET_OPTION_INIT_STRUCT
+#define TARGET_OPTION_INIT_STRUCT aarch64_option_init_struct
/* Set default optimization options. */
static const struct default_options aarch_option_optimization_table[] =
@@ -164,8 +166,6 @@ aarch64_handle_option (struct gcc_options *opts,
}
}
-struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
-
/* An ISA extension in the co-processor and main instruction set space. */
struct aarch64_option_extension
{
@@ -173,15 +173,28 @@ struct aarch64_option_extension
const unsigned long flag_canonical;
const unsigned long flags_on;
const unsigned long flags_off;
+ const bool is_synthetic;
};
/* ISA extensions in AArch64. */
static const struct aarch64_option_extension all_extensions[] =
{
-#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, Z) \
- {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF},
+#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+ SYNTHETIC, Z) \
+ {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
#include "config/aarch64/aarch64-option-extensions.def"
- {NULL, 0, 0, 0}
+ {NULL, 0, 0, 0, false}
+};
+
+/* A copy of the ISA extensions list for AArch64 sorted by the popcount of
+ bits and extension turned on. Cached for efficiency. */
+static struct aarch64_option_extension all_extensions_by_on[] =
+{
+#define AARCH64_OPT_EXTENSION(NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+ SYNTHETIC, Z) \
+ {NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, SYNTHETIC},
+#include "config/aarch64/aarch64-option-extensions.def"
+ {NULL, 0, 0, 0, false}
};
struct processor_name_to_arch
@@ -298,6 +311,69 @@ aarch64_get_all_extension_candidates (auto_vec<const char *> *candidates)
candidates->safe_push (opt->name);
}
+/* Comparer to sort aarch64's feature extensions by population count. Largest
+ first. */
+
+typedef const struct aarch64_option_extension opt_ext;
+
+int opt_ext_cmp (const void* a, const void* b)
+{
+ opt_ext *opt_a = (opt_ext *)a;
+ opt_ext *opt_b = (opt_ext *)b;
+ /* We consider an option to set the bit it turns on, and the other flags it
+ turns on as well. */
+ unsigned long total_flags_a = opt_a->flag_canonical & opt_a->flags_on;
+ unsigned long total_flags_b = opt_b->flag_canonical & opt_b->flags_on;
+ int popcnt_a = popcount_hwi ((HOST_WIDE_INT)total_flags_a);
+ int popcnt_b = popcount_hwi ((HOST_WIDE_INT)total_flags_b);
+ int order = popcnt_b - popcnt_a;
+
+ /* If they have the same amount of bits set, try to give it a more
+ deterministic ordering by using the value of the bits themselves. */
+ if (order == 0)
+ return total_flags_b - total_flags_a;
+
+ return order;
+}
+
+/* Implement TARGET_OPTION_INIT_STRUCT. */
+
+static void
+aarch64_option_init_struct (struct gcc_options *opts ATTRIBUTE_UNUSED)
+{
+ /* Sort the extensions based on how many bits they set, order the larger
+ bits first. */
+ int n_extensions
+ = sizeof (all_extensions) / sizeof (struct aarch64_option_extension);
+ qsort (&all_extensions_by_on, n_extensions,
+ sizeof (struct aarch64_option_extension), opt_ext_cmp);
+}
+
+/* Checks to see if enough bits from the option OPT are enabled in
+ ISA_FLAG_BITS to be able to replace the individual options with the
+ canonicalized version of the option. The rules are a bit tricky as we have
+ two kinds of options.
+
+ 1) Synthetic groups, such as +crypto which on their own don't have a feature
+ bit but turn on multiple bits. These kind of options should be used when
+ ever the bits they turn on are all available.
+
+ 2) Options that themselves have a bit, such as +rdma, in this case, all the
+ feature bits they turn on must be available and the bit for the option
+ itself must be. In this case it's effectively a reduction rather than a
+ grouping.
+*/
+
+static bool
+aarch64_contains_opt (unsigned long isa_flag_bits, opt_ext *opt)
+{
+ unsigned long flags_check = opt->flags_on;
+ if (!opt->is_synthetic)
+ flags_check |= opt->flag_canonical;
+
+ return (isa_flag_bits & flags_check) == flags_check;
+}
+
/* Return a string representation of ISA_FLAGS. DEFAULT_ARCH_FLAGS
gives the default set of flags which are implied by whatever -march
we'd put out. Our job is to figure out the minimal set of "+" and
@@ -311,27 +387,49 @@ aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags,
const struct aarch64_option_extension *opt = NULL;
std::string outstr = "";
- /* Pass one: Find all the things we need to turn on. As a special case,
- we always want to put out +crc if it is enabled. */
- for (opt = all_extensions; opt->name != NULL; opt++)
- if ((isa_flags & opt->flag_canonical
+ unsigned long isa_flag_bits = isa_flags;
+
+ /* Pass one: For the bits that turn on multiple bits, remove the individual bits
+ it they are all present. The option on it's own is enough to trigger their
+ inclusion. */
+ for (opt = all_extensions_by_on; opt->name != NULL; opt++)
+ if ((popcount_hwi ((HOST_WIDE_INT)opt->flags_on) > 1
+ && aarch64_contains_opt (isa_flag_bits, opt)
+ && !(default_arch_flags & opt->flag_canonical)))
+ {
+ isa_flag_bits &= ~opt->flags_on;
+ isa_flag_bits |= opt->flag_canonical;
+ }
+
+ /* Pass two: Find all the things we need to turn on. As a special case,
+ we always want to put out +crc if it is enabled. Once a bit has been
+ "claimed" by an option we clear it so another option doesn't get set
+ due to it. This relies on the options being processed in order of largest
+ population to smallest. */
+ for (opt = all_extensions_by_on; opt->name != NULL; opt++)
+ if ((isa_flag_bits & opt->flag_canonical
&& !(default_arch_flags & opt->flag_canonical))
|| (default_arch_flags & opt->flag_canonical
&& opt->flag_canonical == AARCH64_ISA_CRC))
{
outstr += "+";
outstr += opt->name;
+ isa_flag_bits &= ~(opt->flag_canonical | opt->flags_on);
}
- /* Pass two: Find all the things we need to turn off. */
- for (opt = all_extensions; opt->name != NULL; opt++)
+ /* Pass three: Find all the things we need to turn off, we aim to give the
+ small-ish set possible by looking at the amount of things the feature turns
+ on. By reasoning it probably also turns off a bunch of things when you
+ turn it off. Unlike the above we don't care about the smallest set in this
+ case as "+no" flags are rarely passed along to the assembler. */
+ for (opt = all_extensions_by_on; opt->name != NULL; opt++)
if ((~isa_flags) & opt->flag_canonical
&& !((~default_arch_flags) & opt->flag_canonical))
{
outstr += "+no";
outstr += opt->name;
+ isa_flags &= ~(opt->flag_canonical | opt->flags_off);
}
-
return outstr;
}
@@ -411,5 +509,7 @@ aarch64_rewrite_mcpu (int argc, const char **argv)
return aarch64_rewrite_selected_cpu (argv[argc - 1]);
}
+struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
+
#undef AARCH64_CPU_NAME_LENGTH
diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def
index 2879e35cf2d41d96cb41bb3edd82c0f50091b077..50909debf5455d57b86db91a0a5539fed1d5b91e 100644
--- a/gcc/config/aarch64/aarch64-option-extensions.def
+++ b/gcc/config/aarch64/aarch64-option-extensions.def
@@ -30,6 +30,13 @@
FLAGS_OFF are the bitwise-or of the features that disabling the extension
removes, or zero if disabling this extension has no effect on other
features.
+ SYNTHETIC is a boolean to indicate whether the option is a purely synthetic
+ grouping of options and that the option itself has no feature bit (e.g.
+ crypto). This is used to determine when sum of the individual options in
+ FLAGS_ON can be replaced by FLAG_CANONICAL in options minimization. If the
+ group is synthetic then they can be replaced when all options in FLAGS_ON
+ are enabled, otherwise they can only be replaced when FLAGS_ON | FLAG_CANONICAL
+ are enabled.
FEAT_STRING is a string containing the entries in the 'Features' field of
/proc/cpuinfo on a GNU/Linux system that correspond to this architecture
extension being available. Sometimes multiple entries are needed to enable
@@ -43,7 +50,8 @@
"sha3", sm3/sm4 and "sve". */
AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO |\
AARCH64_FL_F16 | AARCH64_FL_AES | AARCH64_FL_SHA2 |\
- AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, "fp")
+ AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE, \
+ false, "fp")
/* Enabling "simd" also enables "fp".
Disabling "simd" also disables "crypto", "dotprod", "aes", "sha2", "sha3",
@@ -51,76 +59,86 @@ AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, 0, AARCH64_FL_SIMD | AARCH64_FL_CRYPT
AARCH64_OPT_EXTENSION("simd", AARCH64_FL_SIMD, AARCH64_FL_FP, AARCH64_FL_CRYPTO |\
AARCH64_FL_DOTPROD | AARCH64_FL_AES | AARCH64_FL_SHA2 |\
AARCH64_FL_SHA3 | AARCH64_FL_SM4 | AARCH64_FL_SVE,
- "asimd")
+ false, "asimd")
-/* Enabling "crypto" also enables "fp" and "simd".
+/* Enabling "crypto" also enables "fp", "simd", "aes" and "sha2".
Disabling "crypto" disables "crypto", "aes", "sha2", "sha3" and "sm3/sm4". */
-AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO, AARCH64_FL_FP | AARCH64_FL_SIMD,\
+AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO,
+ AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_AES |\
+ AARCH64_FL_SHA2,\
AARCH64_FL_AES | AARCH64_FL_SHA2 |AARCH64_FL_SHA3 | AARCH64_FL_SM4,\
- "aes pmull sha1 sha2")
+ true, "aes pmull sha1 sha2")
/* Enabling or disabling "crc" only changes "crc". */
-AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, "crc32")
+AARCH64_OPT_EXTENSION("crc", AARCH64_FL_CRC, 0, 0, false, "crc32")
/* Enabling or disabling "lse" only changes "lse". */
-AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, "atomics")
+AARCH64_OPT_EXTENSION("lse", AARCH64_FL_LSE, 0, 0, false, "atomics")
/* Enabling "fp16" also enables "fp".
Disabling "fp16" disables "fp16", "fp16fml" and "sve". */
AARCH64_OPT_EXTENSION("fp16", AARCH64_FL_F16, AARCH64_FL_FP,
- AARCH64_FL_F16FML | AARCH64_FL_SVE, "fphp asimdhp")
+ AARCH64_FL_F16FML | AARCH64_FL_SVE, false, "fphp asimdhp")
/* Enabling or disabling "rcpc" only changes "rcpc". */
-AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, "lrcpc")
+AARCH64_OPT_EXTENSION("rcpc", AARCH64_FL_RCPC, 0, 0, false, "lrcpc")
/* Enabling "rdma" also enables "fp", "simd".
Disabling "rdma" just disables "rdma". */
-AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, AARCH64_FL_FP | AARCH64_FL_SIMD, 0, "asimdrdm")
+AARCH64_OPT_EXTENSION("rdma", AARCH64_FL_RDMA, \
+ AARCH64_FL_FP | AARCH64_FL_SIMD, 0, false, "asimdrdm")
/* Enabling "dotprod" also enables "simd".
Disabling "dotprod" only disables "dotprod". */
-AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, "asimddp")
+AARCH64_OPT_EXTENSION("dotprod", AARCH64_FL_DOTPROD, AARCH64_FL_SIMD, 0, \
+ false, "asimddp")
/* Enabling "aes" also enables "simd".
Disabling "aes" just disables "aes". */
-AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, 0, "aes")
+AARCH64_OPT_EXTENSION("aes", AARCH64_FL_AES, AARCH64_FL_SIMD, 0, false, "aes")
/* Enabling "sha2" also enables "simd".
Disabling "sha2" just disables "sha2". */
-AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, "sha1 sha2")
+AARCH64_OPT_EXTENSION("sha2", AARCH64_FL_SHA2, AARCH64_FL_SIMD, 0, false, \
+ "sha1 sha2")
/* Enabling "sha3" enables "simd" and "sha2".
Disabling "sha3" just disables "sha3". */
-AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, AARCH64_FL_SIMD | AARCH64_FL_SHA2, 0, "sha3 sha512")
+AARCH64_OPT_EXTENSION("sha3", AARCH64_FL_SHA3, \
+ AARCH64_FL_SIMD | AARCH64_FL_SHA2, 0, false, \
+ "sha3 sha512")
/* Enabling "sm4" also enables "simd".
Disabling "sm4" just disables "sm4". */
-AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, 0, "sm3 sm4")
+AARCH64_OPT_EXTENSION("sm4", AARCH64_FL_SM4, AARCH64_FL_SIMD, 0, false, \
+ "sm3 sm4")
/* Enabling "fp16fml" also enables "fp" and "fp16".
Disabling "fp16fml" just disables "fp16fml". */
-AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, AARCH64_FL_FP | AARCH64_FL_F16, 0, "asimdfml")
+AARCH64_OPT_EXTENSION("fp16fml", AARCH64_FL_F16FML, \
+ AARCH64_FL_FP | AARCH64_FL_F16, 0, false, "asimdfml")
/* Enabling "sve" also enables "fp16", "fp" and "simd".
Disabling "sve" just disables "sve". */
-AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16, 0, "sve")
+AARCH64_OPT_EXTENSION("sve", AARCH64_FL_SVE, AARCH64_FL_FP | AARCH64_FL_SIMD | \
+ AARCH64_FL_F16, 0, false, "sve")
/* Enabling/Disabling "profile" does not enable/disable any other feature. */
-AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, "")
+AARCH64_OPT_EXTENSION("profile", AARCH64_FL_PROFILE, 0, 0, false, "")
/* Enabling/Disabling "rng" only changes "rng". */
-AARCH64_OPT_EXTENSION("rng", AARCH64_FL_RNG, 0, 0, "")
+AARCH64_OPT_EXTENSION("rng", AARCH64_FL_RNG, 0, 0, false, "")
/* Enabling/Disabling "memtag" only changes "memtag". */
-AARCH64_OPT_EXTENSION("memtag", AARCH64_FL_MEMTAG, 0, 0, "")
+AARCH64_OPT_EXTENSION("memtag", AARCH64_FL_MEMTAG, 0, 0, false, "")
/* Enabling/Disabling "sb" only changes "sb". */
-AARCH64_OPT_EXTENSION("sb", AARCH64_FL_SB, 0, 0, "")
+AARCH64_OPT_EXTENSION("sb", AARCH64_FL_SB, 0, 0, false, "")
/* Enabling/Disabling "ssbs" only changes "ssbs". */
-AARCH64_OPT_EXTENSION("ssbs", AARCH64_FL_SSBS, 0, 0, "")
+AARCH64_OPT_EXTENSION("ssbs", AARCH64_FL_SSBS, 0, 0, false, "")
/* Enabling/Disabling "predres" only changes "predres". */
-AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, "")
+AARCH64_OPT_EXTENSION("predres", AARCH64_FL_PREDRES, 0, 0, false, "")
#undef AARCH64_OPT_EXTENSION
diff --git a/gcc/config/aarch64/driver-aarch64.c b/gcc/config/aarch64/driver-aarch64.c
index 2bf1f9a8c13880dd53980cfb7b829d4263d3d7b6..05f1360d48583473820c8008cc09ed139bddc0ce 100644
--- a/gcc/config/aarch64/driver-aarch64.c
+++ b/gcc/config/aarch64/driver-aarch64.c
@@ -36,7 +36,8 @@ struct aarch64_arch_extension
const char *feat_string;
};
-#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \
+#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+ SYNTHETIC, FEATURE_STRING) \
{ EXT_NAME, FLAG_CANONICAL, FEATURE_STRING },
static struct aarch64_arch_extension aarch64_extensions[] =
{
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_1.c b/gcc/testsuite/gcc.target/aarch64/options_set_1.c
new file mode 100644
index 0000000000000000000000000000000000000000..40d9a05c905eb07103d3b437b5c1351e8620ab33
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc} 1 } } */
+
+/* Check to see if crc is output by default. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_2.c b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
new file mode 100644
index 0000000000000000000000000000000000000000..3476febce706b34430682e879a4aa3aac8f752db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_2.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+crypto" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
+
+/* Check to see if crc and crypto are maintained if crypto specified. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_3.c b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
new file mode 100644
index 0000000000000000000000000000000000000000..4558339f16c19555801899c357c50cedb23c28b0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_3.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+aes+sha2+crypto" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
+
+/* Check if smallest set is maintained when outputting. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_4.c b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
new file mode 100644
index 0000000000000000000000000000000000000000..15514bfe93e61e63cbce1262ee951358cd22d6ce
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_4.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+aes+sha2" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
+
+/* Check if individual bits that make up a grouping is specified that only the
+ grouping is kept. */
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_5.c b/gcc/testsuite/gcc.target/aarch64/options_set_5.c
new file mode 100644
index 0000000000000000000000000000000000000000..b4c0901195ede4fe0dd71fbe02a47c35e9dedbbd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_5.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+aes+sha2+nosha2" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crc\+aes} 1 } } */
+
+/* Check if turning off feature bits works correctly and grouping is no
+ longer valid. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_6.c b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
new file mode 100644
index 0000000000000000000000000000000000000000..90a055928a273f06e08124a250e3107ad0704e47
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_6.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.2-a+crypto+nosha2" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.2\-a\+crypto\+crc} 1 } } */
+
+/* Group as a whole was requested to be turned on, crypto itself is a bit and so
+ just turning off one feature can't turn it off. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_7.c b/gcc/testsuite/gcc.target/aarch64/options_set_7.c
new file mode 100644
index 0000000000000000000000000000000000000000..71a2c8a19058c0ec25546085076503d206129e10
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_7.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.4-a+dotprod" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 } } */
+
+/* Checking if enabling default features drops the superfluous bits. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_8.c b/gcc/testsuite/gcc.target/aarch64/options_set_8.c
new file mode 100644
index 0000000000000000000000000000000000000000..83be1bd7a5c3f2bc8d11a14f2c16415c6a7056f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_8.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8.4-a+nodotprod" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\.4\-a} 1 } } */
+
+/* Checking if trying to turn off default features propagates the commandline
+ option. */
diff --git a/gcc/testsuite/gcc.target/aarch64/options_set_9.c b/gcc/testsuite/gcc.target/aarch64/options_set_9.c
new file mode 100644
index 0000000000000000000000000000000000000000..e3c7cdc54ffb0616877260c562354496cfdcb688
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/options_set_9.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-march=armv8-a+simd+fp" } */
+
+int main ()
+{
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times {\.arch armv8\-a} 1 } } */
+
+ /* Check that grouping of bits that don't form a synthetic group don't turn
+ on the parent. e.g. rdma turns on simd+fp, but simd+fp does not turn on
+ rdma since rdma is it's own group. crypto however turns on aes and sha2
+ and turning on sha2 and eas should turn on crypto!. */