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. */
#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, \
+ 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
{
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
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)))
{
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)
{
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;
}
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"
+;
+
#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; \
#include "config/aarch64/aarch64-option-extensions.def"
/* 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
constexpr auto fmv_deps_##FEAT_NAME = get_enable OPT_FLAGS;
#include "config/aarch64/aarch64-option-extensions.def"
-
+#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) \
+ constexpr aarch64_feature_flags alias_prefer_over_flags_##IDENT = 0;
+#include "config/aarch64/aarch64-option-extensions.def"
}
}
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.
- 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:
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
/* +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
#undef AARCH64_OPT_FMV_EXTENSION
#undef AARCH64_OPT_EXTENSION
+#undef AARCH64_OPT_EXTENSION_ALIAS
#undef AARCH64_FMV_FEATURE