Andrew Carlotti <andrew.carlo...@arm.com> writes:
> This adds initial support for function multiversioning on aarch64 using
> the target_version and target_clones attributes.  This loosely follows
> the Beta specification in the ACLE [1], although with some differences
> that still need to be resolved (possibly as follow-up patches).
>
> Existing function multiversioning implementations are broken in various
> ways when used across translation units.  This includes placing
> resolvers in the wrong translation units, and using symbol mangling that
> callers to unintentionally bypass the resolver in some circumstances.
> Fixing these issues for aarch64 will require modifications to our ACLE
> specification.  It will also require further adjustments to existing
> middle end code, to facilitate different mangling and resolver
> placement while preserving existing target behaviours.
>
> The list of function multiversioning features specified in the ACLE is
> also inconsistent with the list of features supported in target option
> extensions.  I intend to resolve some or all of these inconsistencies at
> a later stage.
>
> The target_version attribute is currently only supported in C++, since
> this is the only frontend with existing support for multiversioning
> using the target attribute.  On the other hand, this patch happens to
> enable multiversioning with the target_clones attribute in Ada and D, as
> well as the entire C family, using their existing frontend support.
>
> This patch also does not support the following aspects of the Beta
> specification:
>
> - The target_clones attribute should allow an implicit unlisted
>   "default" version.
> - There should be an option to disable function multiversioning at
>   compile time.
> - Unrecognised target names in a target_clones attribute should be
>   ignored (with an optional warning).  This current patch raises an
>   error instead.
>
> [1] 
> https://github.com/ARM-software/acle/blob/main/main/acle.md#function-multi-versioning
>
> ---
>
> I believe the support present in this patch correctly handles function
> multiversioning within a single translation unit for all features in the ACLE
> specification with option extension support.
>
> Is it ok to push this patch in its current state? I'd then continue working on
> incremental improvements to the supported feature extensions and the ABI 
> issues
> in followup patches, along with corresponding changes and improvements to the
> ACLE specification.
>
>
> gcc/ChangeLog:
>
>       * config/aarch64/aarch64-feature-deps.h (fmv_deps_<FEAT_NAME>):
>       Define aarch64_feature_flags mask foreach FMV feature.
>       * config/aarch64/aarch64-option-extensions.def: Use new macros
>       to define FMV feature extensions.
>       * config/aarch64/aarch64.cc (aarch64_option_valid_attribute_p):
>       Check for target_version attribute after processing target
>       attribute.
>       (aarch64_fmv_feature_data): New.
>       (aarch64_parse_fmv_features): New.
>       (aarch64_process_target_version_attr): New.
>       (aarch64_option_valid_version_attribute_p): New.
>       (get_feature_mask_for_version): New.
>       (compare_feature_masks): New.
>       (aarch64_compare_version_priority): New.
>       (build_ifunc_arg_type): New.
>       (make_resolver_func): New.
>       (add_condition_to_bb): New.
>       (dispatch_function_versions): New.
>       (aarch64_generate_version_dispatcher_body): New.
>       (aarch64_get_function_versions_dispatcher): New.
>       (aarch64_common_function_versions): New.
>       (aarch64_mangle_decl_assembler_name): New.
>       (TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P): New implementation.
>       (TARGET_OPTION_EXPANDED_CLONES_ATTRIBUTE): New implementation.
>       (TARGET_OPTION_FUNCTION_VERSIONS): New implementation.
>       (TARGET_COMPARE_VERSION_PRIORITY): New implementation.
>       (TARGET_GENERATE_VERSION_DISPATCHER_BODY): New implementation.
>       (TARGET_GET_FUNCTION_VERSIONS_DISPATCHER): New implementation.
>       (TARGET_MANGLE_DECL_ASSEMBLER_NAME): New implementation.
>       * config/aarch64/aarch64.h (TARGET_HAS_FMV_TARGET_ATTRIBUTE):
>       Set target macro.
>       * config/arm/aarch-common.h (enum aarch_parse_opt_result): Add
>         new value to report duplicate FMV feature.
>       * common/config/aarch64/cpuinfo.h: New file.
>
> libgcc/ChangeLog:
>
>       * config/aarch64/cpuinfo.c (enum CPUFeatures): Move to shared
>         copy in gcc/common
>
> gcc/testsuite/ChangeLog:
>
>       * gcc.target/aarch64/options_set_17.c: Reorder expected flags.
>       * gcc.target/aarch64/cpunative/native_cpu_0.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_13.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_16.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_17.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_18.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_19.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_20.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_21.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_22.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_6.c: Ditto.
>       * gcc.target/aarch64/cpunative/native_cpu_7.c: Ditto.

Looks good, thanks.  OK for trunk with one trivial fix:

> [...]
> +/* Implement TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P.  This is used to
> +   process attribute ((target_version ("..."))).  */
> +
> +static bool
> +aarch64_option_valid_version_attribute_p (tree fndecl, tree, tree args, int)
> +{
> +  struct cl_target_option cur_target;
> +  bool ret;
> +  tree new_target;
> +  tree existing_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
> +
> +  /* Save the current target options to restore at the end.  */
> +  cl_target_option_save (&cur_target, &global_options, &global_options_set);
> +
> +  /* If fndecl already has some target attributes applied to it, unpack
> +     them so that we add this attribute on top of them, rather than
> +     overwriting them.  */
> +  if (existing_target)
> +    {
> +      struct cl_target_option *existing_options
> +     = TREE_TARGET_OPTION (existing_target);
> +
> +      if (existing_options)
> +     cl_target_option_restore (&global_options, &global_options_set,
> +                               existing_options);
> +    }
> +  else
> +    cl_target_option_restore (&global_options, &global_options_set,
> +                           TREE_TARGET_OPTION (target_option_current_node));
> +
> +  ret = aarch64_process_target_version_attr (args);
> +
> +  /* Set up any additional state.  */
> +  if (ret)
> +    {
> +      aarch64_override_options_internal (&global_options);
> +      new_target = build_target_option_node (&global_options,
> +                                          &global_options_set);
> +    }
> +  else
> +    new_target = NULL;
> +
> +  if (fndecl && ret)
> +    {
> +      DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;
> +    }

Formatting nit: should be:

  if (fndecl && ret)
    DECL_FUNCTION_SPECIFIC_TARGET (fndecl) = new_target;

without the braces.

Richard

Reply via email to