From: Richard Sandiford <richard.sandiford@arm.com>
To: Andrew Carlotti <andrew.carlotti@arm.com>
Cc: gcc-patches@gcc.gnu.org, ebotcazou@libertysurf.fr,
poulhies@adacore.com, ibuclaw@gdcproject.org,
jason@redhat.com, nathan@acm.org, rguenther@suse.de,
richard.earnshaw@arm.com
Subject: Re: [PATCH v2 4/5] Add support for target_version attribute
Date: Wed, 29 Nov 2023 17:53:56 +0000 [thread overview]
Message-ID: <mptfs0oh2dn.fsf@arm.com> (raw)
In-Reply-To: <372e1dfb-af4f-e92b-09aa-952b7b52f195@e124511.cambridge.arm.com> (Andrew Carlotti's message of "Fri, 17 Nov 2023 02:55:02 +0000")
Andrew Carlotti <andrew.carlotti@arm.com> writes:
> This patch adds support for the "target_version" attribute to the middle
> end and the C++ frontend, which will be used to implement function
> multiversioning in the aarch64 backend.
>
> On targets that don't use the "target" attribute for multiversioning,
> there is no conflict between the "target" and "target_clones"
> attributes. This patch therefore makes the mutual exclusion in
> C-family, D and Ada conditonal upon the value of the
> expanded_clones_attribute target hook.
>
> The "target_version" attribute is only added to C++ in this patch,
> because this is currently the only frontend which supports
> multiversioning using the "target" attribute. Support for the
> "target_version" attribute will be extended to C at a later date.
>
> Targets that currently use the "target" attribute for function
> multiversioning (i.e. i386 and rs6000) are not affected by this patch.
>
> Ok for master?
>
> gcc/ChangeLog:
>
> * attribs.cc (decl_attributes): Pass attribute name to target.
> (is_function_default_version): Update comment to specify
> incompatibility with target_version attributes.
> * cgraphclones.cc (cgraph_node::create_version_clone_with_body):
> Call valid_version_attribute_p for target_version attributes.
> * target.def (valid_version_attribute_p): New hook.
> (expanded_clones_attribute): New hook.
> * doc/tm.texi.in: Add new hooks.
> * doc/tm.texi: Regenerate.
> * multiple_target.cc (create_dispatcher_calls): Remove redundant
> is_function_default_version check.
> (expand_target_clones): Use target hook for attribute name.
> * targhooks.cc (default_target_option_valid_version_attribute_p):
> New.
> * targhooks.h (default_target_option_valid_version_attribute_p):
> New.
> * tree.h (DECL_FUNCTION_VERSIONED): Update comment to include
> target_version attributes.
>
> gcc/c-family/ChangeLog:
>
> * c-attribs.cc (CLONES_USES_TARGET): New macro.
> (attr_target_exclusions): Use new macro.
> (attr_target_clones_exclusions): Ditto, and add target_version.
> (attr_target_version_exclusions): New.
> (c_common_attribute_table): Add target_version.
> (handle_target_version_attribute): New.
>
> gcc/ada/ChangeLog:
>
> * gcc-interface/utils.cc (CLONES_USES_TARGET): New macro.
> (attr_target_exclusions): Use new macro.
> (attr_target_clones_exclusions): Ditto.
>
> gcc/d/ChangeLog:
>
> * d-attribs.cc (CLONES_USES_TARGET): New macro.
> (attr_target_exclusions): Use new macro.
> (attr_target_clones_exclusions): Ditto.
>
> gcc/cp/ChangeLog:
>
> * decl2.cc (check_classfn): Update comment to include
> target_version attributes.
>
>
> diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
> index e33a63948cebdeafc3abcdd539a35141969ad978..8850943cb3326568b4679a73405f50487aa1b7c6 100644
> --- a/gcc/ada/gcc-interface/utils.cc
> +++ b/gcc/ada/gcc-interface/utils.cc
> @@ -143,16 +143,21 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
> { NULL, false, false, false },
> };
>
> +#define CLONES_USES_TARGET \
> + (strcmp (targetm.target_option.expanded_clones_attribute, \
> + "target") == 0)
> +
Sorry for the slower review on this part. I was hoping inspiration
would strike for a way to resolve this, but it hasn't, so:
The codebase usually avoids static variables that need dynamic
initialisation. So although macros are not the preferred way of
doing things, I think one is probably appropriate here. How about:
TARGET_HAS_FMV_TARGET_ATTRIBUTE
with the default being true, and with AArch64 defining it to false?
This would replace the expanded_clones_attribute hook, with:
const char *new_attr_name = targetm.target_option.expanded_clones_attribute;
becoming:
const char *new_attr_name = (TARGET_HAS_FMV_TARGET_ATTRIBUTE
? "target" : "target_version");
I realise this is anything but elegant, but I think it's probably
the least worst option, given where we are.
> static const struct attribute_spec::exclusions attr_target_exclusions[] =
> {
> - { "target_clones", true, true, true },
> + { "target_clones", CLONES_USES_TARGET, CLONES_USES_TARGET,
> + CLONES_USES_TARGET },
> { NULL, false, false, false },
> };
>
> static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
> {
> { "always_inline", true, true, true },
> - { "target", true, true, true },
> + { "target", CLONES_USES_TARGET, CLONES_USES_TARGET, CLONES_USES_TARGET },
> { NULL, false, false, false },
> };
>
> diff --git a/gcc/attribs.cc b/gcc/attribs.cc
> index f9fd258598914ce2112ecaaeaad6c63cd69a44e2..27533023ef5c481ba085c2f0c605dfb992987b3e 100644
> --- a/gcc/attribs.cc
> +++ b/gcc/attribs.cc
> @@ -657,7 +657,8 @@ decl_attributes (tree *node, tree attributes, int flags,
> options to the attribute((target(...))) list. */
> if (TREE_CODE (*node) == FUNCTION_DECL
> && current_target_pragma
> - && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
> + && targetm.target_option.valid_attribute_p (*node,
> + get_identifier("target"),
Formatting nit: should be a space before ("target")
> current_target_pragma, 0))
> {
> tree cur_attr = lookup_attribute ("target", attributes);
> @@ -1241,8 +1242,9 @@ make_dispatcher_decl (const tree decl)
> return func_decl;
> }
>
> -/* Returns true if decl is multi-versioned and DECL is the default function,
> - that is it is not tagged with target specific optimization. */
> +/* Returns true if DECL is multi-versioned using the target attribute, and this
> + is the default version. This function can only be used for targets that do
> + not support the "target_version" attribute. */
>
> bool
> is_function_default_version (const tree decl)
> diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
> index b3b41ef123a0f171f57acb1b7f7fdde716428c00..8e33b7c3f4a9e7dcaa299eeff0eea92240f7ef0a 100644
> --- a/gcc/c-family/c-attribs.cc
> +++ b/gcc/c-family/c-attribs.cc
> @@ -149,6 +149,7 @@ static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
> static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
> static tree handle_assume_attribute (tree *, tree, tree, int, bool *);
> static tree handle_target_attribute (tree *, tree, tree, int, bool *);
> +static tree handle_target_version_attribute (tree *, tree, tree, int, bool *);
> static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
> static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
> static tree ignore_attribute (tree *, tree, tree, int, bool *);
> @@ -228,16 +229,29 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
> ATTR_EXCL (NULL, false, false, false),
> };
>
> +#define CLONES_USES_TARGET \
> + (strcmp (targetm.target_option.expanded_clones_attribute, \
> + "target") == 0)
> +
> static const struct attribute_spec::exclusions attr_target_exclusions[] =
> {
> - ATTR_EXCL ("target_clones", true, true, true),
> + ATTR_EXCL ("target_clones", CLONES_USES_TARGET, CLONES_USES_TARGET,
> + CLONES_USES_TARGET),
> ATTR_EXCL (NULL, false, false, false),
> };
>
> static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
> {
> ATTR_EXCL ("always_inline", true, true, true),
> - ATTR_EXCL ("target", true, true, true),
> + ATTR_EXCL ("target", CLONES_USES_TARGET, CLONES_USES_TARGET,
> + CLONES_USES_TARGET),
> + ATTR_EXCL ("target_version", true, true, true),
> + ATTR_EXCL (NULL, false, false, false),
> +};
> +
> +static const struct attribute_spec::exclusions attr_target_version_exclusions[] =
> +{
> + ATTR_EXCL ("target_clones", true, true, true),
Just FTR: I suppose this should also include "target" if there is ever
a port that uses "target" and "target_version" for the same thing, but
there's no need to predict that case.
> ATTR_EXCL (NULL, false, false, false),
> };
>
> @@ -505,6 +519,9 @@ const struct attribute_spec c_common_attribute_table[] =
> { "target", 1, -1, true, false, false, false,
> handle_target_attribute,
> attr_target_exclusions },
> + { "target_version", 1, 1, true, false, false, false,
> + handle_target_version_attribute,
> + attr_target_version_exclusions },
> { "target_clones", 1, -1, true, false, false, false,
> handle_target_clones_attribute,
> attr_target_clones_exclusions },
> @@ -5670,6 +5687,25 @@ handle_target_attribute (tree *node, tree name, tree args, int flags,
> return NULL_TREE;
> }
>
> +/* Handle a "target_version" attribute. */
> +
> +static tree
> +handle_target_version_attribute (tree *node, tree name, tree args, int flags,
> + bool *no_add_attrs)
> +{
> + /* Ensure we have a function type. */
> + if (TREE_CODE (*node) != FUNCTION_DECL)
> + {
> + warning (OPT_Wattributes, "%qE attribute ignored", name);
> + *no_add_attrs = true;
> + }
> + else if (!targetm.target_option.valid_version_attribute_p (*node, name, args,
> + flags))
> + *no_add_attrs = true;
> +
> + return NULL_TREE;
> +}
> +
> /* Handle a "target_clones" attribute. */
>
> static tree
> diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
> index 29d28ef895a73a223695cbb86aafbc845bbe7688..8af6b23d8c0306920e0fdcb3559ef047a16689f4 100644
> --- a/gcc/cgraphclones.cc
> +++ b/gcc/cgraphclones.cc
> @@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see
> #include "tree-eh.h"
> #include "tree-cfg.h"
> #include "tree-inline.h"
> +#include "attribs.h"
> #include "dumpfile.h"
> #include "gimple-pretty-print.h"
> #include "alloc-pool.h"
> @@ -1048,7 +1049,17 @@ cgraph_node::create_version_clone_with_body
> location_t saved_loc = input_location;
> tree v = TREE_VALUE (target_attributes);
> input_location = DECL_SOURCE_LOCATION (new_decl);
> - bool r = targetm.target_option.valid_attribute_p (new_decl, NULL, v, 1);
> + bool r;
> + tree name_id = get_attribute_name (target_attributes);
> + const char* name_str = IDENTIFIER_POINTER (name_id);
Formatting nit, sorry, but: "const char* name_str".
> + if (strcmp (name_str, "target") == 0)
> + r = targetm.target_option.valid_attribute_p (new_decl, name_id, v, 1);
> + else if (strcmp (name_str, "target_version") == 0)
> + r = targetm.target_option.valid_version_attribute_p (new_decl, name_id,
> + v, 1);
> + else
> + gcc_assert(false);
gcc_unreachable ();
LGTM otherwise, thanks.
Richard
> +
> input_location = saved_loc;
> if (!r)
> return NULL;
> diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> index 9e666e5eecee07ae7c742c3a2b27e85899945c4e..e607aa14d284d545d122e04b0eae1247fd301882 100644
> --- a/gcc/cp/decl2.cc
> +++ b/gcc/cp/decl2.cc
> @@ -832,8 +832,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
> tree c2 = get_constraints (fndecl);
>
> /* While finding a match, same types and params are not enough
> - if the function is versioned. Also check version ("target")
> - attributes. */
> + if the function is versioned. Also check for different target
> + specific attributes. */
> if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
> TREE_TYPE (TREE_TYPE (fndecl)))
> && compparms (p1, p2)
> diff --git a/gcc/d/d-attribs.cc b/gcc/d/d-attribs.cc
> index c0dc0e24ded871c136e54e5527e901d16cfa5ceb..7fe68565e70dd1124aac63601416dad68600a34e 100644
> --- a/gcc/d/d-attribs.cc
> +++ b/gcc/d/d-attribs.cc
> @@ -126,16 +126,22 @@ static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
> ATTR_EXCL (NULL, false, false, false),
> };
>
> +#define CLONES_USES_TARGET \
> + (strcmp (targetm.target_option.expanded_clones_attribute, \
> + "target") == 0)
> +
> static const struct attribute_spec::exclusions attr_target_exclusions[] =
> {
> - ATTR_EXCL ("target_clones", true, true, true),
> + ATTR_EXCL ("target_clones", CLONES_USES_TARGET, CLONES_USES_TARGET,
> + CLONES_USES_TARGET),
> ATTR_EXCL (NULL, false, false, false),
> };
>
> static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
> {
> ATTR_EXCL ("always_inline", true, true, true),
> - ATTR_EXCL ("target", true, true, true),
> + ATTR_EXCL ("target", CLONES_USES_TARGET, CLONES_USES_TARGET,
> + CLONES_USES_TARGET),
> ATTR_EXCL (NULL, false, false, false),
> };
>
> diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
> index d83ca73b1aff90d3c181436afedc162b977a4158..6f6b133803f4574fcf0112b1385eec861112ddd5 100644
> --- a/gcc/doc/tm.texi
> +++ b/gcc/doc/tm.texi
> @@ -10644,6 +10644,23 @@ the function declaration to hold a pointer to a target-specific
> @code{struct cl_target_option} structure.
> @end deftypefn
>
> +@deftypefn {Target Hook} bool TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P (tree @var{fndecl}, tree @var{name}, tree @var{args}, int @var{flags})
> +This hook is called to parse @code{attribute(target_version("..."))},
> +which allows setting target-specific options on individual function versions.
> +These function-specific options may differ
> +from the options specified on the command line. The hook should return
> +@code{true} if the options are valid.
> +
> +The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in
> +the function declaration to hold a pointer to a target-specific
> +@code{struct cl_target_option} structure.
> +@end deftypefn
> +
> +@deftypevr {Target Hook} {const char *} TARGET_OPTION_EXPANDED_CLONES_ATTRIBUTE
> +Contains the name of the attribute used for the version description string
> +when expanding clones for a function with the target_clones attribute.
> +@end deftypevr
> +
> @deftypefn {Target Hook} void TARGET_OPTION_SAVE (struct cl_target_option *@var{ptr}, struct gcc_options *@var{opts}, struct gcc_options *@var{opts_set})
> This hook is called to save any additional target-specific information
> in the @code{struct cl_target_option} structure for function-specific
> diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
> index 3d3ae12cc2ff62025b1138430de501a33961fd90..149c88f627be20a9a35ead2eaebdb704e51927fa 100644
> --- a/gcc/doc/tm.texi.in
> +++ b/gcc/doc/tm.texi.in
> @@ -7028,6 +7028,10 @@ on this implementation detail.
>
> @hook TARGET_OPTION_VALID_ATTRIBUTE_P
>
> +@hook TARGET_OPTION_VALID_VERSION_ATTRIBUTE_P
> +
> +@hook TARGET_OPTION_EXPANDED_CLONES_ATTRIBUTE
> +
> @hook TARGET_OPTION_SAVE
>
> @hook TARGET_OPTION_RESTORE
> diff --git a/gcc/multiple_target.cc b/gcc/multiple_target.cc
> index a2ed048d7dd28ec470953fcd8a0dc86817e4b7dc..3db57c2b13d612a37240d9dcf58ad21b2286633c 100644
> --- a/gcc/multiple_target.cc
> +++ b/gcc/multiple_target.cc
> @@ -66,10 +66,6 @@ create_dispatcher_calls (struct cgraph_node *node)
> {
> ipa_ref *ref;
>
> - if (!DECL_FUNCTION_VERSIONED (node->decl)
> - || !is_function_default_version (node->decl))
> - return;
> -
> if (!targetm.has_ifunc_p ())
> {
> error_at (DECL_SOURCE_LOCATION (node->decl),
> @@ -377,6 +373,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
> return false;
> }
>
> + const char *new_attr_name = targetm.target_option.expanded_clones_attribute;
> cgraph_function_version_info *decl1_v = NULL;
> cgraph_function_version_info *decl2_v = NULL;
> cgraph_function_version_info *before = NULL;
> @@ -392,7 +389,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
> char *attr = attrs[i];
>
> /* Create new target clone. */
> - tree attributes = make_attribute ("target", attr,
> + tree attributes = make_attribute (new_attr_name, attr,
> DECL_ATTRIBUTES (node->decl));
>
> char *suffix = XNEWVEC (char, strlen (attr) + 1);
> @@ -430,7 +427,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
> XDELETEVEC (attr_str);
>
> /* Setting new attribute to initial function. */
> - tree attributes = make_attribute ("target", "default",
> + tree attributes = make_attribute (new_attr_name, "default",
> DECL_ATTRIBUTES (node->decl));
> DECL_ATTRIBUTES (node->decl) = attributes;
> node->local = false;
> diff --git a/gcc/target.def b/gcc/target.def
> index 0996da0f71a85f8217a41ceb08de8b21087e4ed9..1d2e0d8bf03a8b949ec636e6a78a111308d3dd71 100644
> --- a/gcc/target.def
> +++ b/gcc/target.def
> @@ -6533,6 +6533,31 @@ the function declaration to hold a pointer to a target-specific\n\
> bool, (tree fndecl, tree name, tree args, int flags),
> default_target_option_valid_attribute_p)
>
> +/* Function to validate the attribute((target_version(...))) strings. If
> + the option is validated, the hook should also fill in
> + DECL_FUNCTION_SPECIFIC_TARGET in the function decl node. */
> +DEFHOOK
> +(valid_version_attribute_p,
> + "This hook is called to parse @code{attribute(target_version(\"...\"))},\n\
> +which allows setting target-specific options on individual function versions.\n\
> +These function-specific options may differ\n\
> +from the options specified on the command line. The hook should return\n\
> +@code{true} if the options are valid.\n\
> +\n\
> +The hook should set the @code{DECL_FUNCTION_SPECIFIC_TARGET} field in\n\
> +the function declaration to hold a pointer to a target-specific\n\
> +@code{struct cl_target_option} structure.",
> + bool, (tree fndecl, tree name, tree args, int flags),
> + default_target_option_valid_version_attribute_p)
> +
> +/* Attribute to be used when expanding clones for functions with
> + target_clones attribute. */
> +DEFHOOKPOD
> +(expanded_clones_attribute,
> + "Contains the name of the attribute used for the version description string\n\
> +when expanding clones for a function with the target_clones attribute.",
> + const char *, "target")
> +
> /* Function to save any extra target state in the target options structure. */
> DEFHOOK
> (save,
> diff --git a/gcc/targhooks.h b/gcc/targhooks.h
> index 189549cb1c742c37c17623141989b492a7c2b2f8..ff2957fd9fd8389e23992281b35e8e5467072f7d 100644
> --- a/gcc/targhooks.h
> +++ b/gcc/targhooks.h
> @@ -192,6 +192,7 @@ extern bool default_hard_regno_scratch_ok (unsigned int);
> extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
> extern bool default_new_address_profitable_p (rtx, rtx_insn *, rtx);
> extern bool default_target_option_valid_attribute_p (tree, tree, tree, int);
> +extern bool default_target_option_valid_version_attribute_p (tree, tree, tree, int);
> extern bool default_target_option_pragma_parse (tree, tree);
> extern bool default_target_can_inline_p (tree, tree);
> extern bool default_update_ipa_fn_target_info (unsigned int &, const gimple *);
> diff --git a/gcc/targhooks.cc b/gcc/targhooks.cc
> index 4f5b240f8d65eeeaf73418c9f1e2c2684b257cfa..b693352d7eae555912477b6e431dd9c016105007 100644
> --- a/gcc/targhooks.cc
> +++ b/gcc/targhooks.cc
> @@ -1789,7 +1789,19 @@ default_target_option_valid_attribute_p (tree ARG_UNUSED (fndecl),
> int ARG_UNUSED (flags))
> {
> warning (OPT_Wattributes,
> - "target attribute is not supported on this machine");
> + "%<target%> attribute is not supported on this machine");
> +
> + return false;
> +}
> +
> +bool
> +default_target_option_valid_version_attribute_p (tree ARG_UNUSED (fndecl),
> + tree ARG_UNUSED (name),
> + tree ARG_UNUSED (args),
> + int ARG_UNUSED (flags))
> +{
> + warning (OPT_Wattributes,
> + "%<target_version%> attribute is not supported on this machine");
>
> return false;
> }
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 086b55f0375435d53a1604b6659da4f19fce3d17..d7841af19b20b0dc0ae28b433d5150e9c4763eff 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -3500,8 +3500,8 @@ extern vec<tree, va_gc> **decl_debug_args_insert (tree);
> (FUNCTION_DECL_CHECK (NODE)->function_decl.function_specific_optimization)
>
> /* In FUNCTION_DECL, this is set if this function has other versions generated
> - using "target" attributes. The default version is the one which does not
> - have any "target" attribute set. */
> + to support different architecture feature sets, e.g. using "target" or
> + "target_version" attributes. */
> #define DECL_FUNCTION_VERSIONED(NODE)\
> (FUNCTION_DECL_CHECK (NODE)->function_decl.versioned_function)
>
next prev parent reply other threads:[~2023-11-29 17:53 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-17 2:49 [PATCH v2 0/5] target_version and aarch64 function multiversioning Andrew Carlotti
2023-11-17 2:51 ` [PATCH v2[1/5] aarch64: Add cpu feature detection to libgcc Andrew Carlotti
2023-11-20 15:46 ` Richard Sandiford
2023-12-04 10:31 ` Andrew Carlotti
2023-11-17 2:53 ` [PATCH v2 2/5] c-family: Simplify attribute exclusion handling Andrew Carlotti
2023-11-19 21:45 ` Jeff Law
2023-11-17 2:54 ` [PATCH v2 3/5] ada: Improve " Andrew Carlotti
2023-11-17 10:45 ` Marc Poulhiès
2023-11-17 11:15 ` Andrew Carlotti
2023-11-20 8:26 ` Marc Poulhiès
2023-11-17 2:55 ` [PATCH v2 4/5] Add support for target_version attribute Andrew Carlotti
2023-11-29 17:53 ` Richard Sandiford [this message]
2023-12-04 11:14 ` Andrew Carlotti
2023-11-17 2:56 ` [PATCH v2 5/5] aarch64: Add function multiversioning support Andrew Carlotti
2023-11-24 16:22 ` Richard Sandiford
2023-12-04 13:23 ` Andrew Carlotti
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=mptfs0oh2dn.fsf@arm.com \
--to=richard.sandiford@arm.com \
--cc=andrew.carlotti@arm.com \
--cc=ebotcazou@libertysurf.fr \
--cc=gcc-patches@gcc.gnu.org \
--cc=ibuclaw@gdcproject.org \
--cc=jason@redhat.com \
--cc=nathan@acm.org \
--cc=poulhies@adacore.com \
--cc=rguenther@suse.de \
--cc=richard.earnshaw@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).