On Wed, Dec 10, 2025 at 10:49:00AM +0000, Alfie Richards wrote:
> Adds the AARCH64_OPT_EXTENSION_ALIAS macro to aarch64-option-extensions.def
> to define architecture features which gate no features themselves, but
> act as aliases for other features.
>
> When getting the extension string for some architecture flags, alias features
> should be used over their constituent features, even if some of the
> constituent
> features are enabled transitively by other features.
>
> Changes +crypto option to use this macro.
>
> gcc/ChangeLog:
>
> * common/config/aarch64/aarch64-common.cc
> (struct aarch64_extension_info): Add flags_alias_preferred_over.
> (AARCH64_OPT_EXTENSION): Add setting flags preferred over to 0.
> (AARCH64_OPT_EXTENSION_ALIAS): New macro def.
> (aarch64_get_extension_string_for_isa_flags): Update to use alias
> extensions over constituent extensions.
> * config/aarch64/aarch64-feature-deps.h (alias_flags): New variable
> (AARCH64_OPT_EXTENSION): New macro def.
> (AARCH64_OPT_EXTENSION_ALIAS): New macro def.
> (HANDLE): Update to use alias_flags.
> (AARCH64_CORE): Update to use alias_flags.
> * config/aarch64/aarch64-option-extensions.def
> (AARCH64_OPT_EXTENSION_ALIAS): New macro def to
> define alias_prefer_over_flags_X.
> (crypto): Update to us AARCH64_OPT_EXTENSION_ALIAS.
> * config/aarch64/aarch64.h: Undef macros after use.
> ---
> gcc/common/config/aarch64/aarch64-common.cc | 91 ++++++++++++-------
> gcc/config/aarch64/aarch64-feature-deps.h | 30 +++++-
> .../aarch64/aarch64-option-extensions.def | 21 ++++-
> gcc/config/aarch64/aarch64.h | 2 +
> 4 files changed, 103 insertions(+), 41 deletions(-)
>
> diff --git a/gcc/common/config/aarch64/aarch64-common.cc
> b/gcc/common/config/aarch64/aarch64-common.cc
> index 1488697c6ce..b4efd887eae 100644
> --- a/gcc/common/config/aarch64/aarch64-common.cc
> +++ b/gcc/common/config/aarch64/aarch64-common.cc
> @@ -165,6 +165,10 @@ struct aarch64_extension_info
> aarch64_feature_flags flags_off;
> /* If this feature remains enabled, these bits must also remain enabled.
> */
> aarch64_feature_flags flags_required;
> + /* If this is not an alias extension, then this is zero.
> + Otherwise, this is the set of feature bits this alias is preferred
> + over. */
> + aarch64_feature_flags flags_alias_preferred_over;
> };
>
> /* ISA extensions in AArch64. */
> @@ -173,9 +177,14 @@ static constexpr aarch64_extension_info all_extensions[]
> =
> #define AARCH64_OPT_EXTENSION(NAME, IDENT, C, D, E, FEATURE_STRING) \
> {NAME, AARCH64_FL_##IDENT, feature_deps::IDENT ().explicit_on, \
> feature_deps::get_flags_off (feature_deps::root_off_##IDENT), \
> - feature_deps::IDENT ().enable},
> + feature_deps::IDENT ().enable, 0},
> +#define AARCH64_OPT_EXTENSION_ALIAS(NAME, IDENT, C, D, E, FEATURE_STRING, G)
> \
> + {NAME, AARCH64_FL_##IDENT, feature_deps::IDENT ().explicit_on, \
> + feature_deps::get_flags_off (feature_deps::root_off_##IDENT), \
> + feature_deps::IDENT ().enable, \
> + feature_deps::alias_prefer_over_flags_##IDENT},
> #include "config/aarch64/aarch64-option-extensions.def"
> - {NULL, 0, 0, 0, 0}
> + {NULL, 0, 0, 0, 0, 0}
> };
>
> struct aarch64_arch_info
> @@ -634,10 +643,10 @@ aarch64_get_extension_string_for_isa_flags
> {
> std::string outstr = "";
>
> - /* The CRYPTO bit should only be used to support the +crypto alias
> + /* The alias bits should only be used to support the aliases
> during option processing, and should be cleared at all other times.
> Verify this property for the supplied flags bitmask. */
> - gcc_assert (!(AARCH64_FL_CRYPTO & aarch64_isa_flags));
> + gcc_assert (!(feature_deps::alias_flags & aarch64_isa_flags));
> aarch64_feature_flags current_flags = default_arch_flags;
>
> /* As a special case, do not assume that the assembler will enable CRC
> @@ -657,24 +666,30 @@ aarch64_get_extension_string_for_isa_flags
> But in order to make the output more readable, it seems better
> to add the strings in definition order. */
> aarch64_feature_flags added = 0;
> - auto flags_crypto = AARCH64_FL_AES | AARCH64_FL_SHA2;
> for (unsigned int i = ARRAY_SIZE (all_extensions); i-- > 0; )
> {
> auto &opt = all_extensions[i];
>
> - /* As a special case, emit +crypto rather than +aes+sha2,
> - in order to support assemblers that predate the separate
> - per-feature crypto flags. */
> - auto flags = opt.flag_canonical;
> - if (flags == AARCH64_FL_CRYPTO)
> - flags = flags_crypto;
> -
> - if ((flags & isa_flags & (explicit_flags | ~current_flags)) == flags)
> + if (!opt.flags_alias_preferred_over
> + && (opt.flag_canonical & isa_flags
> + & (explicit_flags | ~current_flags)) == opt.flag_canonical)
The '== opt.flag_canonical' can be removed now that it is always a single bit.
> {
> current_flags |= opt.flags_on;
> added |= opt.flag_canonical;
> }
> }
> +
> + /* Replace any aliased extensions. */
> + for (auto alias: all_extensions)
> + if (alias.flags_alias_preferred_over
> + && (added & alias.flags_alias_preferred_over)
> + == alias.flags_alias_preferred_over
> + && (alias.flags_on | isa_flags) == isa_flags)
> + {
> + added &= ~alias.flags_on;
> + added |= alias.flag_canonical;
> + }
> +
> for (auto &opt : all_extensions)
> if (added & opt.flag_canonical)
> {
> @@ -687,31 +702,43 @@ aarch64_get_extension_string_for_isa_flags
> detection because one way or another we can't tell if it's available
> or not. */
>
> + aarch64_feature_flags removed = 0;
> for (auto &opt : all_extensions)
> + if (!opt.flags_alias_preferred_over
> + && (opt.flag_canonical & current_flags & ~isa_flags))
> + {
> + current_flags &= ~opt.flags_off;
> + removed |= opt.flag_canonical;
> + }
> +
> + /* Replace any aliased extensions. */
> + for (auto alias: all_extensions)
> {
> - auto flags = opt.flag_canonical;
> - /* As a special case, don't emit "+noaes" or "+nosha2" when we could
> emit
> - "+nocrypto" instead, in order to support assemblers that predate the
> - separate per-feature crypto flags. Only allow "+nocrypto" when "sm4"
> - is not already enabled (to avoid dependending on whether "+nocrypto"
> - also disables "sm4"). */
> - if (flags & flags_crypto
> - && (flags_crypto & current_flags & ~isa_flags) == flags_crypto
> - && !(current_flags & AARCH64_FL_SM4))
> - continue;
> -
> - if (flags == AARCH64_FL_CRYPTO)
> - /* If either crypto flag needs removing here, then both do. */
> - flags = flags_crypto;
> -
> - if (flags & current_flags & ~isa_flags)
> + /* Only allow "+nocrypto" when "sm4" is not already enabled
> + (to avoid dependending on whether "+nocrypto" also disables "sm4"). */
> + if (alias.flag_canonical == AARCH64_FL_CRYPTO
> + && (current_flags & AARCH64_FL_SM4))
> + continue;
> +
> + if (alias.flags_alias_preferred_over /* Check this is an alias. */
> + /* Check we turn off any of the extensions for which we would prefer
> + to use the alias. */
> + && (removed & alias.flags_alias_preferred_over)
> + /* Check this doesn't turn off more flags than we need. */
> + && (alias.flags_off & isa_flags) == 0)
> {
> - current_flags &= ~opt.flags_off;
> - outstr += "+no";
> - outstr += opt.name;
> + removed &= ~alias.flags_off;
> + removed |= alias.flag_canonical;
> }
> }
>
> + for (auto &opt : all_extensions)
> + if (removed & opt.flag_canonical)
> + {
> + outstr += "+no";
> + outstr += opt.name;
> + }
> +
> return outstr;
> }
>
> diff --git a/gcc/config/aarch64/aarch64-feature-deps.h
> b/gcc/config/aarch64/aarch64-feature-deps.h
> index 55a0dbfae61..796043087db 100644
> --- a/gcc/config/aarch64/aarch64-feature-deps.h
> +++ b/gcc/config/aarch64/aarch64-feature-deps.h
> @@ -66,12 +66,20 @@ get_enable (T1 i, Ts... args)
> files are in topological order. */
> template<aarch64_feature> struct info;
>
> + constexpr auto alias_flags = aarch64_feature_flags (0)
> +#define AARCH64_OPT_EXTENSION_ALIAS(A, IDENT, C, D, E, F, G) |
> AARCH64_FL_##IDENT
> +#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F)
> +#include "config/aarch64/aarch64-option-extensions.def"
> +;
> +#undef AARCH64_OPT_EXTENSION_ALIAS
> +#undef AARCH64_OPT_EXTENSION
You've added a lot of new #undefs, but they should all be unnecessary because
we already have the #undefs in the .def files.
> +
> #define HANDLE(IDENT, REQUIRES, EXPLICIT_ON) \
> template<> struct info<aarch64_feature::IDENT> { \
> static constexpr auto flag = AARCH64_FL_##IDENT; \
> static constexpr auto enable = flag | get_enable REQUIRES;
> \
> - static constexpr auto explicit_on \
> - = (enable | get_enable EXPLICIT_ON) & ~AARCH64_FL_CRYPTO; \
> + static constexpr auto explicit_on
> \
> + = (enable | get_enable EXPLICIT_ON) & ~alias_flags; \
> }; \
> constexpr aarch64_feature_flags info<aarch64_feature::IDENT>::flag;
> \
> constexpr aarch64_feature_flags info<aarch64_feature::IDENT>::enable;
> \
> @@ -86,6 +94,7 @@ template<aarch64_feature> struct info;
> #include "config/aarch64/aarch64-option-extensions.def"
> #include "config/aarch64/aarch64-arches.def"
> #undef HANDLE
> +#undef AARCH64_OPT_EXTENSION
>
> /* Return the set of all features that would need to be disabled if
> the features in MASK are disabled.
> @@ -106,6 +115,7 @@ get_flags_off (aarch64_feature_flags mask)
> #include "config/aarch64/aarch64-option-extensions.def"
> );
> }
> +#undef AARCH64_OPT_EXTENSION
>
> /* Define root_off_<IDENT> variables for each feature, giving the set of
> features that must be turned off by +noIDENT. This set is not
> transitively
> @@ -114,13 +124,14 @@ get_flags_off (aarch64_feature_flags mask)
> constexpr auto root_off_##IDENT \
> = AARCH64_FL_##IDENT | get_flags EXPLICIT_OFF;
> #include "config/aarch64/aarch64-option-extensions.def"
> +#undef AARCH64_OPT_EXTENSION
>
> /* Define cpu_<NAME> variables for each CPU, giving the transitive
> - closure of all the features that the CPU supports. The CRYPTO bit is just
> - an alias, so explicitly unset it for consistency. */
> + closure of all the features that the CPU supports. The alias flags are
> + explicitly unset for consistency. */
> #define AARCH64_CORE(A, CORE_IDENT, C, ARCH_IDENT, FEATURES, F, G, H, I) \
> constexpr auto cpu_##CORE_IDENT \
> - = (ARCH_IDENT ().enable | get_enable FEATURES) & ~AARCH64_FL_CRYPTO;
> + = (ARCH_IDENT ().enable | get_enable FEATURES) & ~alias_flags;
> #include "config/aarch64/aarch64-cores.def"
>
> /* Define fmv_deps_<NAME> variables for each FMV feature, giving the
> transitive
> @@ -128,8 +139,17 @@ get_flags_off (aarch64_feature_flags mask)
> #define AARCH64_FMV_FEATURE(A, FEAT_NAME, OPT_FLAGS) \
> constexpr auto fmv_deps_##FEAT_NAME = get_enable OPT_FLAGS;
> #include "config/aarch64/aarch64-option-extensions.def"
> +#undef AARCH64_FMV_FEATURE
>
> +#define AARCH64_OPT_EXTENSION_ALIAS(A, IDENT, OPT_FLAGS, D, E, \
> + PREFER_FLAGS, G) \
> + constexpr auto alias_prefer_over_flags_##IDENT = get_flags PREFER_FLAGS;
>
> +#define AARCH64_OPT_EXTENSION(A, IDENT, C, D, E, F)
We could set 'alias_prefer_over_flags_##IDENT = 0' for non-alias flags, so that
we can eliminate the duplicate code in aarch64-common.cc.
> +#include "config/aarch64/aarch64-option-extensions.def"
> +;
> +#undef AARCH64_OPT_EXTENSION_ALIAS
> +#undef AARCH64_OPT_EXTENSION
> }
> }
>
> diff --git a/gcc/config/aarch64/aarch64-option-extensions.def
> b/gcc/config/aarch64/aarch64-option-extensions.def
> index 083515d890d..9d1d7166b17 100644
> --- a/gcc/config/aarch64/aarch64-option-extensions.def
> +++ b/gcc/config/aarch64/aarch64-option-extensions.def
> @@ -25,6 +25,9 @@
> AARCH64_OPT_EXTENSION(NAME, IDENT, REQUIRES, EXPLICIT_ON,
> EXPLICIT_OFF, FEATURE_STRING)
>
> + AARCH64_OPT_EXTENSION_ALIAS(NAME, IDENT, REQUIRES, EXPLICIT_ON,
> + EXPLICIT_OFF, PREFER_OVER, FEATURE_STRING)
> +
> AARCH64_FMV_FEATURE(NAME, FEAT_NAME, IDENT)
>
> - NAME is the name of the extension, represented as a string constant.
> @@ -66,6 +69,10 @@
> - OPT_FLAGS is a list of feature IDENTS that should be enabled (along with
> their transitive dependencies) when the specified FMV feature is
> present.
>
> + - PREFER_OVER is a list of features that need to be present when emitting
> + the list of architecture feature options for the alias option to be
> + preferred instead.
> +
> Where a feature is present as both an extension and a function
> multiversioning feature, and IDENT matches the FEAT_NAME suffix, then
> these
> can be listed here simultaneously using the macro:
> @@ -88,6 +95,13 @@
> EXPLICIT_OFF, FEATURE_STRING)
> #endif
>
> +#ifndef AARCH64_OPT_EXTENSION_ALIAS
> +#define AARCH64_OPT_EXTENSION_ALIAS(NAME, IDENT, REQUIRES, EXPLICIT_ON, \
> + EXPLICIT_OFF, PREFERRED_OVER,
> FEATURE_STRING) \
> +AARCH64_OPT_EXTENSION(NAME, IDENT, REQUIRES, EXPLICIT_ON, EXPLICIT_OFF, \
> + FEATURE_STRING)
> +#endif
> +
> #ifndef AARCH64_FMV_FEATURE
> #define AARCH64_FMV_FEATURE(NAME, FEAT_NAME, OPT_FLAGS)
> #endif
> @@ -134,11 +148,9 @@ AARCH64_FMV_FEATURE("aes", PMULL, (AES))
>
> /* +nocrypto disables AES, SHA2 and SM4, and anything that depends on them
> (such as SHA3 and the SVE2 crypto extensions). */
> -AARCH64_OPT_EXTENSION("crypto", CRYPTO, (AES, SHA2), (), (AES, SHA2, SM4),
> - "aes pmull sha1 sha2")
> +AARCH64_OPT_EXTENSION_ALIAS("crypto", CRYPTO, (AES, SHA2), (), (AES, SHA2,
> SM4),
> + (AES, SHA2), "aes pmull sha1 sha2")
>
> -/* Listing sha3 after crypto means we pass "+aes+sha3" to the assembler
> - instead of "+sha3+crypto". */
> AARCH64_OPT_EXTENSION("sha3", SHA3, (SHA2), (), (), "sha3 sha512")
>
> /* +nofp16 disables an implicit F16FML, even though an implicit F16FML
> @@ -291,4 +303,5 @@ AARCH64_OPT_EXTENSION("cpa", CPA, (), (), (), "")
>
> #undef AARCH64_OPT_FMV_EXTENSION
> #undef AARCH64_OPT_EXTENSION
> +#undef AARCH64_OPT_EXTENSION_ALIAS
> #undef AARCH64_FMV_FEATURE
> diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h
> index 5a1d5a94670..8c3cb60d94b 100644
> --- a/gcc/config/aarch64/aarch64.h
> +++ b/gcc/config/aarch64/aarch64.h
> @@ -179,6 +179,8 @@ enum class aarch64_feature : unsigned char {
> #include "aarch64-option-extensions.def"
> #include "aarch64-arches.def"
> #undef HANDLE
> +#undef AARCH64_OPT_EXTENSION
> +#undef AARCH64_ARCH
>
> /* Define aarch64_isa_mode masks. */
> #define DEF_AARCH64_ISA_MODE(IDENT) \
> --
> 2.34.1
>