public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Earnshaw <Richard.Earnshaw@arm.com>
To: gcc-patches@gcc.gnu.org
Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>
Subject: [PATCH 14/30] [arm] Generate a canonical form for -march
Date: Fri, 09 Jun 2017 12:55:00 -0000	[thread overview]
Message-ID: <ca69be1ce71830e56a31b4a656a2501f91b7b753.1497004220.git.Richard.Earnshaw@arm.com> (raw)
In-Reply-To: <cover.1497004220.git.Richard.Earnshaw@arm.com>
In-Reply-To: <cover.1497004220.git.Richard.Earnshaw@arm.com>

[-- Attachment #1: Type: text/plain, Size: 1441 bytes --]


This patch uses the driver and some spec rewrite rules to generate a
canonicalized form of the -march= option.  We want to do this for
several reasons, all relating to making multi-lib selection sane.

1) It can remove redundant extension options to produce a minimal
list.

2) The general syntax of the option permits a plethora of features,
these are permitted in any order.  Canonicalization ensures that there
is a single ordering of the options that are needed.

3) It can use additional options to remove extensions that aren't
relevant, such as removing all features that relate to the FPU when
use of that is disabled.

Once we have this information in a sensible form the multilib rules
can be vastly simplified making for much more understandable Makefile
fragments.

	* common/config/arm/arm-common.c: Define INCLUDE_LIST.
	(configargs.h): Include it.
	(arm_print_hint_for_fpu_option): New function.
	(arm_parse_fpu_option): New function.
	(candidate_extension): New class.
	(arm_canon_for_multilib): New function.
	* config/arm/arm.h (CANON_ARCH_SPEC_FUNCTION): New macro.
	(EXTRA_SPEC_FUNCTIONS): Add CANON_ARCH_SPEC_FUNCTION.
	(ARCH_CANONICAL_SPECS): New macro.
	(DRIVER_SELF_SPECS): Add ARCH_CANONICAL_SPECS.
---
 gcc/common/config/arm/arm-common.c | 354 +++++++++++++++++++++++++++++++++++++
 gcc/config/arm/arm.h               |  19 +-
 2 files changed, 372 insertions(+), 1 deletion(-)


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0014-arm-Generate-a-canonical-form-for-march.patch --]
[-- Type: text/x-patch; name="0014-arm-Generate-a-canonical-form-for-march.patch", Size: 13493 bytes --]

diff --git a/gcc/common/config/arm/arm-common.c b/gcc/common/config/arm/arm-common.c
index 930cfb0..c4ab482 100644
--- a/gcc/common/config/arm/arm-common.c
+++ b/gcc/common/config/arm/arm-common.c
@@ -17,6 +17,7 @@
    along with GCC; see the file COPYING3.  If not see
    <http://www.gnu.org/licenses/>.  */
 
+#define INCLUDE_LIST
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
@@ -305,6 +306,41 @@ arm_parse_arch_option_name (const arch_option *list, const char *optname,
   return NULL;
 }
 
+/* List the premitted architecture option names.  If TARGET is a near
+   miss for an entry, print out the suggested alternative.  */
+static void
+arm_print_hint_for_fpu_option (const char *target)
+{
+  auto_vec<const char*> candidates;
+  for (int i = 0; i < TARGET_FPU_auto; i++)
+    candidates.safe_push (all_fpus[i].name);
+  char *s;
+  const char *hint = candidates_list_and_hint (target, s, candidates);
+  if (hint)
+    inform (input_location, "valid arguments are: %s; did you mean %qs?",
+	    s, hint);
+  else
+    inform (input_location, "valid arguments are: %s", s);
+
+  XDELETEVEC (s);
+}
+
+static const arm_fpu_desc *
+arm_parse_fpu_option (const char *opt)
+{
+  int i;
+
+  for (i = 0; i < TARGET_FPU_auto; i++)
+    {
+      if (strcmp (all_fpus[i].name, opt) == 0)
+	return all_fpus + i;
+    }
+
+  error_at (input_location, "unrecognized -mfpu target: %s", opt);
+  arm_print_hint_for_fpu_option (opt);
+  return NULL;
+}
+
 /* Convert a static initializer array of feature bits to sbitmap
    representation.  */
 void
@@ -405,6 +441,324 @@ arm_parse_option_features (sbitmap isa, const cpu_arch_option *target,
     }
 }
 
+class candidate_extension
+{
+public:
+  const cpu_arch_extension *extension;
+  sbitmap isa_bits;
+  bool required;
+
+  candidate_extension (const cpu_arch_extension *ext, sbitmap bits)
+    : extension (ext), isa_bits (bits), required (true)
+    {}
+  ~candidate_extension ()
+    {
+      sbitmap_free (isa_bits);
+    }
+};
+
+/* Generate a canonical representation of the -march option from the
+   current -march string (if given) and other options on the command
+   line that might affect the architecture.  This aids multilib selection
+   by ensuring that:
+   a) the option is always present
+   b) only the minimal set of options are used
+   c) when there are multiple extensions, they are in a consistent order.
+
+   The options array consists of couplets of information where the
+   first item in each couplet is the string describing which option
+   name was selected (arch, cpu, fpu) and the second is the value
+   passed for that option.  */
+const char *
+arm_canon_arch_option (int argc, const char **argv)
+{
+  const char *arch = NULL;
+  const char *cpu = NULL;
+  const char *fpu = NULL;
+  const char *abi = NULL;
+  static char *canonical_arch = NULL;
+
+  /* Just in case we're called more than once.  */
+  if (canonical_arch)
+    {
+      free (canonical_arch);
+      canonical_arch = NULL;
+    }
+
+  if (argc & 1)
+    fatal_error (input_location,
+		 "%%:canon_for_mlib takes 1 or more pairs of parameters");
+
+  while (argc)
+    {
+      if (strcmp (argv[0], "arch") == 0)
+	arch = argv[1];
+      else if (strcmp (argv[0], "cpu") == 0)
+	cpu = argv[1];
+      else if (strcmp (argv[0], "fpu") == 0)
+	fpu = argv[1];
+      else if (strcmp (argv[0], "abi") == 0)
+	abi = argv[1];
+      else
+	fatal_error (input_location,
+		     "unrecognized operand to %%:canon_for_mlib");
+
+      argc -= 2;
+      argv += 2;
+    }
+
+  auto_sbitmap target_isa (isa_num_bits);
+  auto_sbitmap base_isa (isa_num_bits);
+  auto_sbitmap fpu_isa (isa_num_bits);
+
+  bitmap_clear (fpu_isa);
+
+  const arch_option *selected_arch = NULL;
+
+  /* At least one of these must be defined by either the specs or the
+     user.  */
+  gcc_assert (cpu || arch);
+
+  if (!fpu)
+    fpu = FPUTYPE_DEFAULT;
+
+  if (!abi)
+    {
+      if (TARGET_DEFAULT_FLOAT_ABI == ARM_FLOAT_ABI_SOFT)
+	abi = "soft";
+      else if (TARGET_DEFAULT_FLOAT_ABI == ARM_FLOAT_ABI_SOFTFP)
+	abi = "softfp";
+      else if (TARGET_DEFAULT_FLOAT_ABI == ARM_FLOAT_ABI_HARD)
+	abi = "hard";
+    }
+
+  /* First build up a bitmap describing the target architecture.  */
+  if (arch)
+    {
+      selected_arch = arm_parse_arch_option_name (all_architectures,
+						  "-march", arch);
+
+      if (selected_arch == NULL)
+	return "";
+
+      arm_initialize_isa (target_isa, selected_arch->common.isa_bits);
+      arm_parse_option_features (target_isa, &selected_arch->common,
+				 strchr (arch, '+'));
+      if (fpu && strcmp (fpu, "auto") != 0)
+	{
+	  /* We assume that architectures do not have any FPU bits
+	     enabled by default.  If they did, we would need to strip
+	     these out first.  */
+	  const arm_fpu_desc *target_fpu = arm_parse_fpu_option (fpu);
+	  if (target_fpu == NULL)
+	    return "";
+
+	  arm_initialize_isa (fpu_isa, target_fpu->isa_bits);
+	  bitmap_ior (target_isa, target_isa, fpu_isa);
+	}
+    }
+  else if (cpu)
+    {
+      const cpu_option *selected_cpu
+	= arm_parse_cpu_option_name (all_cores, "-mcpu", cpu);
+
+      if (selected_cpu == NULL)
+	return "";
+
+      arm_initialize_isa (target_isa, selected_cpu->common.isa_bits);
+      arm_parse_option_features (target_isa, &selected_cpu->common,
+				 strchr (cpu, '+'));
+      if (fpu && strcmp (fpu, "auto") != 0)
+	{
+	  /* The easiest and safest way to remove the default fpu
+	     capabilities is to look for a '+no..' option that removes
+	     the base FPU bit (isa_bit_VFPv2).  If that doesn't exist
+	     then the best we can do is strip out all the bits that
+	     might be part of the most capable FPU we know about,
+	     which is "crypto-neon-fp-armv8".  */
+	  bool default_fpu_found = false;
+	  if (selected_cpu->common.extensions)
+	    {
+	      const cpu_arch_extension *ext;
+	      for (ext = selected_cpu->common.extensions; ext->name != NULL;
+		   ++ext)
+		{
+		  if (ext->remove
+		      && check_isa_bits_for (ext->isa_bits, isa_bit_VFPv2))
+		    {
+		      arm_initialize_isa (fpu_isa, ext->isa_bits);
+		      bitmap_and_compl (target_isa, target_isa, fpu_isa);
+		      default_fpu_found = true;
+		    }
+		}
+
+	    }
+
+	  if (!default_fpu_found)
+	    {
+	      arm_initialize_isa
+		(fpu_isa,
+		 all_fpus[TARGET_FPU_crypto_neon_fp_armv8].isa_bits);
+	      bitmap_and_compl (target_isa, target_isa, fpu_isa);
+	    }
+
+	  const arm_fpu_desc *target_fpu = arm_parse_fpu_option (fpu);
+	  if (target_fpu == NULL)
+	    return "";
+
+	  arm_initialize_isa (fpu_isa, target_fpu->isa_bits);
+	  bitmap_ior (target_isa, target_isa, fpu_isa);
+	}
+
+      selected_arch = all_architectures + selected_cpu->arch;
+    }
+
+  /* If we have a soft-float ABI, disable the FPU.  */
+  if (abi && strcmp (abi, "soft") == 0)
+    {
+      /* Clearing the VFPv2 bit is sufficient to stop any extention that
+	 builds on the FPU from matching.  */
+      bitmap_clear_bit (target_isa, isa_bit_VFPv2);
+    }
+
+  /* If we don't have a selected architecture by now, something's
+     badly wrong.  */
+  gcc_assert (selected_arch);
+
+  arm_initialize_isa (base_isa, selected_arch->common.isa_bits);
+
+  /* Architecture has no extension options, so just return the canonical
+     architecture name.  */
+  if (selected_arch->common.extensions == NULL)
+    return selected_arch->common.name;
+
+  /* We're only interested in extension bits.  */
+  bitmap_and_compl (target_isa, target_isa, base_isa);
+
+  /* There are no extensions needed.  Just return the canonical architecture
+     name.  */
+  if (bitmap_empty_p (target_isa))
+    return selected_arch->common.name;
+
+  /* What is left is the architecture that the compiler will target.  We
+     now need to map that back into a suitable option+features list.
+
+     The list is built in two passes.  First we scan every additive
+     option feature supported by the architecture.  If the option
+     provides a subset of the features we need we add it to the list
+     of candidates.  We then scan backwards over the list of
+     candidates and if we find a feature that adds nothing to one that
+     was later in the list we mark it as redundant.  The result is a
+     minimal list of required features for the target
+     architecture.  */
+
+  std::list<candidate_extension *> extensions;
+
+  auto_sbitmap target_isa_unsatisfied (isa_num_bits);
+  bitmap_copy (target_isa_unsatisfied, target_isa);
+
+  sbitmap isa_bits = NULL;
+  for (const cpu_arch_extension *cand = selected_arch->common.extensions;
+       cand->name != NULL;
+       cand++)
+    {
+      if (cand->remove || cand->alias)
+	continue;
+
+      if (isa_bits == NULL)
+	isa_bits = sbitmap_alloc (isa_num_bits);
+
+      arm_initialize_isa (isa_bits, cand->isa_bits);
+      if (bitmap_subset_p (isa_bits, target_isa))
+	{
+	  extensions.push_back (new candidate_extension (cand, isa_bits));
+	  bitmap_and_compl (target_isa_unsatisfied, target_isa_unsatisfied,
+			    isa_bits);
+	  isa_bits = NULL;
+	}
+    }
+
+  /* There's one extra case to consider, which is that the user has
+     specified an FPU that is less capable than this architecture
+     supports.  In that case the code above will fail to find a
+     suitable feature.  We handle this by scanning the list of options
+     again, matching the first option that provides an FPU that is
+     more capable than the selected FPU.
+
+     Note that the other case (user specified a more capable FPU than
+     this architecture supports) should end up selecting the most
+     capable FPU variant that we do support.  This is sufficient for
+     multilib selection.  */
+
+  if (bitmap_bit_p (target_isa_unsatisfied, isa_bit_VFPv2)
+      && bitmap_bit_p (fpu_isa, isa_bit_VFPv2))
+    {
+      std::list<candidate_extension *>::iterator ipoint = extensions.begin ();
+
+      for (const cpu_arch_extension *cand = selected_arch->common.extensions;
+	   cand->name != NULL;
+	   cand++)
+	{
+	  if (cand->remove || cand->alias)
+	    continue;
+
+	  if (isa_bits == NULL)
+	    isa_bits = sbitmap_alloc (isa_num_bits);
+
+	  /* We need to keep the features in canonical order, so move the
+	     insertion point if this feature is a candidate.  */
+	  if (ipoint != extensions.end ()
+	      && (*ipoint)->extension == cand)
+	    ++ipoint;
+
+	  arm_initialize_isa (isa_bits, cand->isa_bits);
+	  if (bitmap_subset_p (fpu_isa, isa_bits))
+	    {
+	      extensions.insert (ipoint,
+				 new candidate_extension (cand, isa_bits));
+	      isa_bits = NULL;
+	      break;
+	    }
+	}
+    }
+
+  if (isa_bits)
+    sbitmap_free (isa_bits);
+
+  bitmap_clear (target_isa);
+  size_t len = 1;
+  for (std::list<candidate_extension *>::reverse_iterator riter
+	 = extensions.rbegin ();
+       riter != extensions.rend (); ++riter)
+    {
+      if (bitmap_subset_p ((*riter)->isa_bits, target_isa))
+	(*riter)->required = false;
+      else
+	{
+	  bitmap_ior (target_isa, target_isa, (*riter)->isa_bits);
+	  len += strlen ((*riter)->extension->name) + 1;
+	}
+    }
+
+  canonical_arch
+    = (char *) xmalloc (len + strlen (selected_arch->common.name));
+
+  strcpy (canonical_arch, selected_arch->common.name);
+
+  for (std::list<candidate_extension *>::iterator iter = extensions.begin ();
+       iter != extensions.end (); ++iter)
+    {
+      if ((*iter)->required)
+	{
+	  strcat (canonical_arch, "+");
+	  strcat (canonical_arch, (*iter)->extension->name);
+	}
+      delete (*iter);
+    }
+
+  return canonical_arch;
+}
+
 #undef ARM_CPU_NAME_LENGTH
 
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index 590755e..dea3d0a 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -2250,9 +2250,15 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 # define MCPU_MTUNE_NATIVE_SPECS ""
 #endif
 
+const char *arm_canon_arch_option (int argc, const char **argv);
+
+#define CANON_ARCH_SPEC_FUNCTION		\
+  { "canon_arch", arm_canon_arch_option },
+
 # define EXTRA_SPEC_FUNCTIONS			\
   MCPU_MTUNE_NATIVE_FUNCTIONS			\
   ASM_CPU_SPEC_FUNCTIONS			\
+  CANON_ARCH_SPEC_FUNCTION			\
   TARGET_MODE_SPEC_FUNCTIONS
 
 /* Automatically add -mthumb for Thumb-only targets if mode isn't specified
@@ -2264,7 +2270,18 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
 #define TARGET_MODE_SPECS						\
   " %{!marm:%{!mthumb:%:target_mode_check(%{march=*:arch %*;mcpu=*:cpu %*;:})}}"
 
-#define DRIVER_SELF_SPECS MCPU_MTUNE_NATIVE_SPECS TARGET_MODE_SPECS
+/* Generate a canonical string to represent the architecture selected.  */
+#define ARCH_CANONICAL_SPECS				\
+  " -march=%:canon_arch(%{mcpu=*: cpu %*} "		\
+  "                     %{march=*: arch %* %<march=*} "	\
+  "                     %{mfpu=*: fpu %*} "		\
+  "                     %{mfloat-abi=*: abi %*}) "
+
+#define DRIVER_SELF_SPECS			\
+  MCPU_MTUNE_NATIVE_SPECS			\
+  TARGET_MODE_SPECS				\
+  ARCH_CANONICAL_SPECS
+
 #define TARGET_SUPPORTS_WIDE_INT 1
 
 /* For switching between functions with different target attributes.  */

  parent reply	other threads:[~2017-06-09 12:55 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-09 12:54 [PATCH 00/30] [ARM] Reworking the -mcpu, -march and -mfpu options Richard Earnshaw
2017-06-09 12:54 ` [PATCH 24/30] [arm][linux-eabi] Ensure all multilib variables are reset Richard Earnshaw
2017-06-09 12:54 ` [PATCH 25/30] [arm][phoenix] reset all multilib variables Richard Earnshaw
2017-06-09 12:54 ` [PATCH 29/30] [arm][doc] Document new -march= syntax Richard Earnshaw
2017-06-09 12:54 ` [PATCH 12/30] [arm] Allow new extended syntax CPU and architecture names during configure Richard Earnshaw
2017-06-09 12:54 ` [PATCH 02/30] [arm] Rewrite -march and -mcpu options for passing to the assembler Richard Earnshaw
2017-06-09 12:54 ` [PATCH 06/30] [arm] Add default FPUs for CPUs Richard Earnshaw
2017-06-09 12:54 ` [PATCH 05/30] [arm] Add architectural options Richard Earnshaw
2017-06-09 12:54 ` [PATCH 10/30] [arm] Use standard option parsing code for detecting thumb-only targets Richard Earnshaw
2017-06-09 12:54 ` [PATCH 04/30] [arm] Allow +opt on arbitrary cpu and architecture specifications Richard Earnshaw
2017-06-13 17:14   ` Richard Earnshaw (lists)
2017-06-09 12:54 ` [PATCH 17/30] [arm] Make 'auto' the default FPU selection option Richard Earnshaw
2017-06-09 12:54 ` [PATCH 18/30] [arm] Rewrite t-aprofile using new selector methodology Richard Earnshaw
2017-06-09 12:54 ` [PATCH 28/30] [arm] Add a few missing architecture extension options Richard Earnshaw
2017-06-09 12:54 ` [PATCH 23/30] [arm][rtems] Update t-rtems for new option framework Richard Earnshaw
2017-06-09 13:03   ` Sebastian Huber
2017-06-09 12:55 ` [PATCH 03/30] [arm] Don't pass -mfpu=auto through to the assembler Richard Earnshaw
2017-06-09 12:55 ` [PATCH 19/30] [arm] Explicitly set .fpu in cmse_nonsecure_call.S Richard Earnshaw
2017-06-09 12:55 ` [PATCH 20/30] [genmultilib] Allow explicit periods to be escaped in MULTILIB_REUSE Richard Earnshaw
2017-06-09 12:55 ` [PATCH 30/30] [arm][doc] Document changes to -mcpu, -mtune and -mfpu Richard Earnshaw
2017-06-09 22:19   ` Gerald Pfeifer
2017-06-09 12:55 ` Richard Earnshaw [this message]
2017-06-13 17:25   ` [PATCH 14/30] [arm] Generate a canonical form for -march Richard Earnshaw (lists)
2017-06-09 12:55 ` [PATCH 21/30] [arm][testsuite] Use -march=armv7-a+fp when testing hard-float ABI Richard Earnshaw
2017-06-09 12:55 ` [PATCH 26/30] [arm] Rework multlib builds for symbianelf Richard Earnshaw
2017-06-09 12:55 ` [PATCH 15/30] [arm] Make -mfloat-abi=softfp work when there are no FPU instructions Richard Earnshaw
2017-06-09 12:55 ` [PATCH 09/30] [ARM] Move cpu and architecture option name parsing code to arm-common.c Richard Earnshaw
2017-06-13 17:19   ` Richard Earnshaw (lists)
2017-06-09 12:55 ` [PATCH 16/30] [arm] Update basic multilib configuration Richard Earnshaw
2017-06-09 12:55 ` [PATCH 22/30] [arm] Rewrite t-rmprofile multilib specification Richard Earnshaw
2017-06-09 12:55 ` [PATCH 07/30] [build] Make sbitmap code available to the driver programs Richard Earnshaw
2017-06-14 14:35   ` Richard Earnshaw (lists)
2017-06-16  8:03     ` Richard Biener
2017-06-09 12:55 ` [PATCH 01/30] [arm] Use strings for -march, -mcpu and -mtune options Richard Earnshaw
2017-06-13 13:23   ` Christophe Lyon
2017-06-13 15:33     ` Richard Earnshaw (lists)
2017-06-13 17:11   ` Richard Earnshaw (lists)
2017-06-09 12:55 ` [PATCH 11/30] [arm] Allow CPU and architecture extensions to be defined as aliases Richard Earnshaw
2017-06-09 12:55 ` [PATCH 27/30] [arm][fuchsia] Rework multilib support Richard Earnshaw
2017-06-09 12:55 ` [PATCH 13/30] [arm] Force a CPU default in the config args defaults list Richard Earnshaw
2017-06-09 12:55 ` [PATCH 08/30] [arm] Split CPU, architecture and tuning data tables Richard Earnshaw
2017-06-13 17:17   ` Richard Earnshaw (lists)
2017-06-09 22:45 ` [PATCH 00/30] [ARM] Reworking the -mcpu, -march and -mfpu options Christophe Lyon
2017-06-09 23:27   ` Richard Earnshaw (lists)
2017-06-12 11:49     ` Christophe Lyon
2017-06-12 14:34       ` Richard Earnshaw (lists)
2017-06-12 17:11         ` Joseph Myers
2017-06-12 21:27           ` Richard Earnshaw (lists)
2017-06-13  9:40             ` Richard Earnshaw (lists)
2017-06-13 10:29               ` Joseph Myers
2017-06-13 15:26         ` Richard Earnshaw (lists)
2017-06-13 16:08           ` Christophe Lyon
2017-06-12 11:48 ` Nathan Sidwell
2017-06-13 17:27 ` [PATCH 31/30] [arm] Mark -marm and -mthumb as being inverse options Richard Earnshaw (lists)
2017-06-13 17:29 ` [PATCH 32/30][arm][testsuite] Fix neon-thumb2-move.c test Richard Earnshaw (lists)
2017-06-14 14:27   ` [PATCH 32/30][arm][testsuite] Fix various tests Richard Earnshaw (lists)
2017-06-14 19:26     ` Christophe Lyon
2017-06-13 17:36 ` [PATCH 00/30] [ARM] Reworking the -mcpu, -march and -mfpu options Richard Earnshaw (lists)
2017-06-14  9:08   ` Christophe Lyon
2017-06-14 10:21     ` Richard Earnshaw (lists)
2017-06-16 21:11   ` Richard Earnshaw
2017-06-16 21:16     ` Ramana Radhakrishnan

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=ca69be1ce71830e56a31b4a656a2501f91b7b753.1497004220.git.Richard.Earnshaw@arm.com \
    --to=richard.earnshaw@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    /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).