genopinit: Split init_all_optabs [PR113575]

Message ID 77b98581-e3ac-4288-8ee0-f31416b95323@gmail.com
State Accepted
Headers
Series genopinit: Split init_all_optabs [PR113575] |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Robin Dapp Jan. 26, 2024, 8:16 a.m. UTC
  Hi,

init_all_optabs initializes > 10000 patterns for riscv targets.  This
leads to pathological situations in dataflow analysis (which can occur
with many adjacent stores).
To alleviate this this patch makes genopinit split the init_all_optabs
function into several init_optabs_xx functions that each initialize 1000
patterns.

With this change insn-opinit.cc's compilation time is reduced from 4+
minutes to 1:30 and memory consumption decreases from 1.2G to 630M.

Bootstrapped and regtested on x86 and aarch64 (where we do split) and
on power10 (where we don't).  Regtested on riscv.

Regards
 Robin

gcc/ChangeLog:

	PR other/113575

	* genopinit.cc (main): Split init_all_optabs into functions
	of 1000 patterns each.
---
 gcc/genopinit.cc | 43 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 38 insertions(+), 5 deletions(-)
  

Comments

Richard Biener Jan. 26, 2024, 12:21 p.m. UTC | #1
On Fri, Jan 26, 2024 at 9:17 AM Robin Dapp <rdapp.gcc@gmail.com> wrote:
>
> Hi,
>
> init_all_optabs initializes > 10000 patterns for riscv targets.  This
> leads to pathological situations in dataflow analysis (which can occur
> with many adjacent stores).
> To alleviate this this patch makes genopinit split the init_all_optabs
> function into several init_optabs_xx functions that each initialize 1000
> patterns.
>
> With this change insn-opinit.cc's compilation time is reduced from 4+
> minutes to 1:30 and memory consumption decreases from 1.2G to 630M.
>
> Bootstrapped and regtested on x86 and aarch64 (where we do split) and
> on power10 (where we don't).  Regtested on riscv.

OK.

Thanks,
Richard.

> Regards
>  Robin
>
> gcc/ChangeLog:
>
>         PR other/113575
>
>         * genopinit.cc (main): Split init_all_optabs into functions
>         of 1000 patterns each.
> ---
>  gcc/genopinit.cc | 43 ++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 38 insertions(+), 5 deletions(-)
>
> diff --git a/gcc/genopinit.cc b/gcc/genopinit.cc
> index 88ccafa5b2c..d8682b2a9ad 100644
> --- a/gcc/genopinit.cc
> +++ b/gcc/genopinit.cc
> @@ -367,11 +367,44 @@ main (int argc, const char **argv)
>      fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
>    fprintf (s_file, "};\n\n");
>
> -  fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
> -  fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
> -  for (i = 0; patterns.iterate (i, &p); ++i)
> -    fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
> -  fprintf (s_file, "}\n\n");
> +  /* Some targets like riscv have a large number of patterns.  In order to
> +     prevent pathological situations in dataflow analysis split the init
> +     function into separate ones that initialize 1000 patterns each.  */
> +
> +  const int patterns_per_function = 1000;
> +
> +  if (patterns.length () > patterns_per_function)
> +    {
> +      unsigned num_init_functions
> +       = patterns.length () / patterns_per_function + 1;
> +      for (i = 0; i < num_init_functions; i++)
> +       {
> +         fprintf (s_file, "static void\ninit_optabs_%02d "
> +                  "(struct target_optabs *optabs)\n{\n", i);
> +         fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
> +         unsigned start = i * patterns_per_function;
> +         unsigned end = MIN (patterns.length (),
> +                             (i + 1) * patterns_per_function);
> +         for (j = start; j < end; ++j)
> +           fprintf (s_file, "  ena[%u] = HAVE_%s;\n", j, patterns[j].name);
> +         fprintf (s_file, "}\n\n");
> +       }
> +
> +      fprintf (s_file, "void\ninit_all_optabs "
> +              "(struct target_optabs *optabs)\n{\n");
> +      for (i = 0; i < num_init_functions; ++i)
> +       fprintf (s_file, "  init_optabs_%02d (optabs);\n", i);
> +      fprintf (s_file, "}\n\n");
> +    }
> +  else
> +    {
> +      fprintf (s_file, "void\ninit_all_optabs "
> +              "(struct target_optabs *optabs)\n{\n");
> +      fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
> +      for (i = 0; patterns.iterate (i, &p); ++i)
> +       fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
> +      fprintf (s_file, "}\n\n");
> +    }
>
>    fprintf (s_file,
>            "/* Returns TRUE if the target supports any of the partial vector\n"
> --
> 2.43.0
  

Patch

diff --git a/gcc/genopinit.cc b/gcc/genopinit.cc
index 88ccafa5b2c..d8682b2a9ad 100644
--- a/gcc/genopinit.cc
+++ b/gcc/genopinit.cc
@@ -367,11 +367,44 @@  main (int argc, const char **argv)
     fprintf (s_file, "  { %#08x, CODE_FOR_%s },\n", p->sort_num, p->name);
   fprintf (s_file, "};\n\n");
 
-  fprintf (s_file, "void\ninit_all_optabs (struct target_optabs *optabs)\n{\n");
-  fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
-  for (i = 0; patterns.iterate (i, &p); ++i)
-    fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
-  fprintf (s_file, "}\n\n");
+  /* Some targets like riscv have a large number of patterns.  In order to
+     prevent pathological situations in dataflow analysis split the init
+     function into separate ones that initialize 1000 patterns each.  */
+
+  const int patterns_per_function = 1000;
+
+  if (patterns.length () > patterns_per_function)
+    {
+      unsigned num_init_functions
+	= patterns.length () / patterns_per_function + 1;
+      for (i = 0; i < num_init_functions; i++)
+	{
+	  fprintf (s_file, "static void\ninit_optabs_%02d "
+		   "(struct target_optabs *optabs)\n{\n", i);
+	  fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
+	  unsigned start = i * patterns_per_function;
+	  unsigned end = MIN (patterns.length (),
+			      (i + 1) * patterns_per_function);
+	  for (j = start; j < end; ++j)
+	    fprintf (s_file, "  ena[%u] = HAVE_%s;\n", j, patterns[j].name);
+	  fprintf (s_file, "}\n\n");
+	}
+
+      fprintf (s_file, "void\ninit_all_optabs "
+	       "(struct target_optabs *optabs)\n{\n");
+      for (i = 0; i < num_init_functions; ++i)
+	fprintf (s_file, "  init_optabs_%02d (optabs);\n", i);
+      fprintf (s_file, "}\n\n");
+    }
+  else
+    {
+      fprintf (s_file, "void\ninit_all_optabs "
+	       "(struct target_optabs *optabs)\n{\n");
+      fprintf (s_file, "  bool *ena = optabs->pat_enable;\n");
+      for (i = 0; patterns.iterate (i, &p); ++i)
+	fprintf (s_file, "  ena[%u] = HAVE_%s;\n", i, p->name);
+      fprintf (s_file, "}\n\n");
+    }
 
   fprintf (s_file,
 	   "/* Returns TRUE if the target supports any of the partial vector\n"