[Patch AArch64 4/4] Add -moverride tuning command, and wire it up for
authorJames Greenhalgh <james.greenhalgh@arm.com>
Fri, 26 Jun 2015 14:04:12 +0000 (14:04 +0000)
committerJames Greenhalgh <jgreenhalgh@gcc.gnu.org>
Fri, 26 Jun 2015 14:04:12 +0000 (14:04 +0000)
 control of fusion and fma-steering

gcc/

* config/aarch64/aarch64.opt: (override): New.
* doc/invoke.texi (override): Document.
* config/aarch64/aarch64.c (aarch64_flag_desc): New
(aarch64_fusible_pairs): Likewise.
(aarch64_tuning_flags): Likewise.
(aarch64_tuning_override_function): Likewise.
(aarch64_tuning_override_functions): Likewise.
(aarch64_parse_one_option_token): Likewise.
(aarch64_parse_boolean_options): Likewise.
(aarch64_parse_fuse_string): Likewise.
(aarch64_parse_tune_string): Likewise.
(aarch64_parse_one_override_token): Likewise.
(aarch64_parse_override_string): Likewise.
(aarch64_override_options): Parse the -override string if it
is present.

From-SVN: r225018

gcc/ChangeLog
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.opt
gcc/doc/invoke.texi

index bf2d02c8c3c2b935499310ab491ca971a318356d..460e78cbfc6254523fd5713639a08cc57506c2a3 100644 (file)
@@ -1,3 +1,21 @@
+2015-06-26  James Greenhalgh  <james.greenhalgh@arm.com>
+
+       * config/aarch64/aarch64.opt: (override): New.
+       * doc/invoke.texi (override): Document.
+       * config/aarch64/aarch64.c (aarch64_flag_desc): New
+       (aarch64_fusible_pairs): Likewise.
+       (aarch64_tuning_flags): Likewise.
+       (aarch64_tuning_override_function): Likewise.
+       (aarch64_tuning_override_functions): Likewise.
+       (aarch64_parse_one_option_token): Likewise.
+       (aarch64_parse_boolean_options): Likewise.
+       (aarch64_parse_fuse_string): Likewise.
+       (aarch64_parse_tune_string): Likewise.
+       (aarch64_parse_one_override_token): Likewise.
+       (aarch64_parse_override_string): Likewise.
+       (aarch64_override_options): Parse the -override string if it
+       is present.
+
 2015-06-26  James Greenhalgh  <james.greenhalgh@arm.com>
 
        * config/aarch64/aarch64-protos.h (tune_params): Remove
index a11d8568e31d99f31f97e4323c60e05d53b186b3..f130f8dea1da78a8cad86f08ee49816563fc5ed5 100644 (file)
@@ -172,6 +172,36 @@ unsigned long aarch64_isa_flags = 0;
 /* Mask to specify which instruction scheduling options should be used.  */
 unsigned long aarch64_tune_flags = 0;
 
+/* Support for command line parsing of boolean flags in the tuning
+   structures.  */
+struct aarch64_flag_desc
+{
+  const char* name;
+  unsigned int flag;
+};
+
+#define AARCH64_FUSION_PAIR(name, internal_name, y) \
+  { name, AARCH64_FUSE_##internal_name },
+static const struct aarch64_flag_desc aarch64_fusible_pairs[] =
+{
+  { "none", AARCH64_FUSE_NOTHING },
+#include "aarch64-fusion-pairs.def"
+  { "all", AARCH64_FUSE_ALL },
+  { NULL, AARCH64_FUSE_NOTHING }
+};
+#undef AARCH64_FUION_PAIR
+
+#define AARCH64_EXTRA_TUNING_OPTION(name, internal_name, y) \
+  { name, AARCH64_EXTRA_TUNE_##internal_name },
+static const struct aarch64_flag_desc aarch64_tuning_flags[] =
+{
+  { "none", AARCH64_EXTRA_TUNE_NONE },
+#include "aarch64-tuning-flags.def"
+  { "all", AARCH64_EXTRA_TUNE_ALL },
+  { NULL, AARCH64_EXTRA_TUNE_NONE }
+};
+#undef AARCH64_EXTRA_TUNING_OPTION
+
 /* Tuning parameters.  */
 
 static const struct cpu_addrcost_table generic_addrcost_table =
@@ -454,6 +484,24 @@ static const struct tune_params xgene1_tunings =
   (AARCH64_EXTRA_TUNE_NONE)    /* tune_flags.  */
 };
 
+/* Support for fine-grained override of the tuning structures.  */
+struct aarch64_tuning_override_function
+{
+  const char* name;
+  void (*parse_override)(const char*, struct tune_params*);
+};
+
+static void aarch64_parse_fuse_string (const char*, struct tune_params*);
+static void aarch64_parse_tune_string (const char*, struct tune_params*);
+
+static const struct aarch64_tuning_override_function
+aarch64_tuning_override_functions[] =
+{
+  { "fuse", aarch64_parse_fuse_string },
+  { "tune", aarch64_parse_tune_string },
+  { NULL, NULL }
+};
+
 /* A processor implementing AArch64.  */
 struct processor
 {
@@ -7230,6 +7278,178 @@ aarch64_parse_tune (void)
   return;
 }
 
+/* Parse TOKEN, which has length LENGTH to see if it is an option
+   described in FLAG.  If it is, return the index bit for that fusion type.
+   If not, error (printing OPTION_NAME) and return zero.  */
+
+static unsigned int
+aarch64_parse_one_option_token (const char *token,
+                               size_t length,
+                               const struct aarch64_flag_desc *flag,
+                               const char *option_name)
+{
+  for (; flag->name != NULL; flag++)
+    {
+      if (length == strlen (flag->name)
+         && !strncmp (flag->name, token, length))
+       return flag->flag;
+    }
+
+  error ("unknown flag passed in -moverride=%s (%s)", option_name, token);
+  return 0;
+}
+
+/* Parse OPTION which is a comma-separated list of flags to enable.
+   FLAGS gives the list of flags we understand, INITIAL_STATE gives any
+   default state we inherit from the CPU tuning structures.  OPTION_NAME
+   gives the top-level option we are parsing in the -moverride string,
+   for use in error messages.  */
+
+static unsigned int
+aarch64_parse_boolean_options (const char *option,
+                              const struct aarch64_flag_desc *flags,
+                              unsigned int initial_state,
+                              const char *option_name)
+{
+  const char separator = '.';
+  const char* specs = option;
+  const char* ntoken = option;
+  unsigned int found_flags = initial_state;
+
+  while ((ntoken = strchr (specs, separator)))
+    {
+      size_t token_length = ntoken - specs;
+      unsigned token_ops = aarch64_parse_one_option_token (specs,
+                                                          token_length,
+                                                          flags,
+                                                          option_name);
+      /* If we find "none" (or, for simplicity's sake, an error) anywhere
+        in the token stream, reset the supported operations.  So:
+
+          adrp+add.cmp+branch.none.adrp+add
+
+          would have the result of turning on only adrp+add fusion.  */
+      if (!token_ops)
+       found_flags = 0;
+
+      found_flags |= token_ops;
+      specs = ++ntoken;
+    }
+
+  /* We ended with a comma, print something.  */
+  if (!(*specs))
+    {
+      error ("%s string ill-formed\n", option_name);
+      return 0;
+    }
+
+  /* We still have one more token to parse.  */
+  size_t token_length = strlen (specs);
+  unsigned token_ops = aarch64_parse_one_option_token (specs,
+                                                      token_length,
+                                                      flags,
+                                                      option_name);
+   if (!token_ops)
+     found_flags = 0;
+
+  found_flags |= token_ops;
+  return found_flags;
+}
+
+/* Support for overriding instruction fusion.  */
+
+static void
+aarch64_parse_fuse_string (const char *fuse_string,
+                           struct tune_params *tune)
+{
+  tune->fusible_ops = aarch64_parse_boolean_options (fuse_string,
+                                                    aarch64_fusible_pairs,
+                                                    tune->fusible_ops,
+                                                    "fuse=");
+}
+
+/* Support for overriding other tuning flags.  */
+
+static void
+aarch64_parse_tune_string (const char *tune_string,
+                           struct tune_params *tune)
+{
+  tune->extra_tuning_flags
+    = aarch64_parse_boolean_options (tune_string,
+                                    aarch64_tuning_flags,
+                                    tune->extra_tuning_flags,
+                                    "tune=");
+}
+
+/* Parse TOKEN, which has length LENGTH to see if it is a tuning option
+   we understand.  If it is, extract the option string and handoff to
+   the appropriate function.  */
+
+void
+aarch64_parse_one_override_token (const char* token,
+                                 size_t length,
+                                 struct tune_params *tune)
+{
+  const struct aarch64_tuning_override_function *fn
+    = aarch64_tuning_override_functions;
+
+  const char *option_part = strchr (token, '=');
+  if (!option_part)
+    {
+      error ("tuning string missing in option (%s)", token);
+      return;
+    }
+
+  /* Get the length of the option name.  */
+  length = option_part - token;
+  /* Skip the '=' to get to the option string.  */
+  option_part++;
+
+  for (; fn->name != NULL; fn++)
+    {
+      if (!strncmp (fn->name, token, length))
+       {
+         fn->parse_override (option_part, tune);
+         return;
+       }
+    }
+
+  error ("unknown tuning option (%s)",token);
+  return;
+}
+
+/* Parse STRING looking for options in the format:
+     string    :: option:string
+     option    :: name=substring
+     name      :: {a-z}
+     substring :: defined by option.  */
+
+static void
+aarch64_parse_override_string (const char* input_string,
+                              struct tune_params* tune)
+{
+  const char separator = ':';
+  size_t string_length = strlen (input_string) + 1;
+  char *string_root = (char *) xmalloc (sizeof (*string_root) * string_length);
+  char *string = string_root;
+  strncpy (string, input_string, string_length);
+  string[string_length - 1] = '\0';
+
+  char* ntoken = string;
+
+  while ((ntoken = strchr (string, separator)))
+    {
+      size_t token_length = ntoken - string;
+      /* Make this substring look like a string.  */
+      *ntoken = '\0';
+      aarch64_parse_one_override_token (string, token_length, tune);
+      string = ++ntoken;
+    }
+
+  /* One last option to parse.  */
+  aarch64_parse_one_override_token (string, strlen (string), tune);
+  free (string_root);
+}
 
 /* Implement TARGET_OPTION_OVERRIDE.  */
 
@@ -7294,6 +7514,10 @@ aarch64_override_options (void)
   aarch64_tune_params = *(selected_tune->tune);
   aarch64_architecture_version = selected_cpu->architecture_version;
 
+  if (aarch64_override_tune_string)
+    aarch64_parse_override_string (aarch64_override_tune_string,
+                                  &aarch64_tune_params);
+
   if (aarch64_fix_a53_err835769 == 2)
     {
 #ifdef TARGET_FIX_ERR_A53_835769_DEFAULT
index 6d72ac26dd19f1aebfd4781bf257a4a12e23342c..98ef9f6be9d70b8555de198d44a1fd327933355b 100644 (file)
@@ -111,6 +111,10 @@ mabi=
 Target RejectNegative Joined Enum(aarch64_abi) Var(aarch64_abi) Init(AARCH64_ABI_DEFAULT)
 -mabi=ABI      Generate code that conforms to the specified ABI
 
+moverride=
+Target RejectNegative ToLower Joined Var(aarch64_override_tune_string)
+-moverride=STRING      Power users only! Override CPU optimization parameters
+
 Enum
 Name(aarch64_abi) Type(int)
 Known AArch64 ABIs (for use with the -mabi= option):
index 053dd5dc2cf5115f39d36ee356f51ab962024a4e..844d7edaecf2bc6642324ad8513f7c2add0ee486 100644 (file)
@@ -12525,6 +12525,15 @@ Enable Privileged Access Never support.
 Enable Limited Ordering Regions support.
 @item rdma
 Enable ARMv8.1 Advanced SIMD instructions.
+
+@item -moverride=@var{string}
+@opindex master
+Override tuning decisions made by the back-end in response to a
+@option{-mtune=} switch.  The syntax, semantics, and accepted values
+for @var{string} in this option are not guaranteed to be consistent
+across releases.
+
+This option is only intended to be useful when developing GCC.
 @end table
 
 That is, @option{crypto} implies @option{simd} implies @option{fp}.