One slightly awkward part about emitting the generator function
bodies is that:

* define_insn and define_expand routines have a separate argument for
  each operand, named "operand0" upwards.

* define_split and define_peephole2 routines take a pointer to an array,
  named "operands".

* the C++ preparation code for expands, splits and peephole2s uses an
  array called "operands" to refer to the operands.

* the automatically-generated code uses individual "operand<N>"
  variables to refer to the operands.

So define_expands have to store the incoming arguments into an operands
array before the md file's C++ code, then copy the operands array back
to the individual variables before the automatically-generated code.
splits and peephole2s have to copy the incoming operands array to
individual variables after the md file's C++ code, creating more
local variables that are live across calls to rtx_alloc.

This patch tries to simplify things by making the whole function
body use the operands array in preference to individual variables.
define_insns and define_expands store their arguments to the array
on entry.

This would have pros and cons on its own, but having a single array
helps with future efforts to reduce the duplication between gen_*
functions.

Doing this tripped a warning in stormy16.md about writing beyond
the end of the array.  The negsi2 C++ code writes to operands[2]
even though the pattern has no operand 2.

gcc/
        * genemit.cc (gen_rtx_scratch, gen_exp): Use operands[%d] rather than
        operand%d.
        (start_gen_insn): Store the incoming arguments to an operands array.
        (gen_expand, gen_split): Remove copies into and out of the operands
        array.
        * config/stormy16/stormy16.md (negsi): Remove redundant assignment.
---
 gcc/genemit.cc | 61 ++++++++++++++++----------------------------------
 1 file changed, 19 insertions(+), 42 deletions(-)

diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index 90f36e293b4..cdc098f19b8 100644
--- a/gcc/genemit.cc
+++ b/gcc/genemit.cc
@@ -71,7 +71,7 @@ gen_rtx_scratch (rtx x, enum rtx_code subroutine_type, FILE 
*file)
 {
   if (subroutine_type == DEFINE_PEEPHOLE2)
     {
-      fprintf (file, "operand%d", XINT (x, 0));
+      fprintf (file, "operands[%d]", XINT (x, 0));
     }
   else
     {
@@ -108,21 +108,21 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used,
        {
          if (used[XINT (x, 0)])
            {
-             fprintf (file, "copy_rtx (operand%d)", XINT (x, 0));
+             fprintf (file, "copy_rtx (operands[%d])", XINT (x, 0));
              return;
            }
          used[XINT (x, 0)] = 1;
        }
-      fprintf (file, "operand%d", XINT (x, 0));
+      fprintf (file, "operands[%d]", XINT (x, 0));
       return;
 
     case MATCH_OP_DUP:
       fprintf (file, "gen_rtx_fmt_");
       for (i = 0; i < XVECLEN (x, 1); i++)
        fprintf (file, "e");
-      fprintf (file, " (GET_CODE (operand%d), ", XINT (x, 0));
+      fprintf (file, " (GET_CODE (operands[%d]), ", XINT (x, 0));
       if (GET_MODE (x) == VOIDmode)
-       fprintf (file, "GET_MODE (operand%d)", XINT (x, 0));
+       fprintf (file, "GET_MODE (operands[%d])", XINT (x, 0));
       else
        fprintf (file, "%smode", GET_MODE_NAME (GET_MODE (x)));
       for (i = 0; i < XVECLEN (x, 1); i++)
@@ -137,7 +137,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used,
       fprintf (file, "gen_rtx_fmt_");
       for (i = 0; i < XVECLEN (x, 2); i++)
        fprintf (file, "e");
-      fprintf (file, " (GET_CODE (operand%d)", XINT (x, 0));
+      fprintf (file, " (GET_CODE (operands[%d])", XINT (x, 0));
       fprintf (file, ", %smode", GET_MODE_NAME (GET_MODE (x)));
       for (i = 0; i < XVECLEN (x, 2); i++)
        {
@@ -149,7 +149,7 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used,
 
     case MATCH_PARALLEL:
     case MATCH_PAR_DUP:
-      fprintf (file, "operand%d", XINT (x, 0));
+      fprintf (file, "operands[%d]", XINT (x, 0));
       return;
 
     case MATCH_SCRATCH:
@@ -437,14 +437,22 @@ start_gen_insn (FILE *file, const char *name, const 
pattern_stats &stats)
   fprintf (file, "rtx\ngen_%s (", name);
   if (stats.num_generator_args)
     for (int i = 0; i < stats.num_generator_args; i++)
-      if (i)
-       fprintf (file, ",\n\trtx operand%d ATTRIBUTE_UNUSED", i);
-      else
-       fprintf (file, "rtx operand%d ATTRIBUTE_UNUSED", i);
+      fprintf (file, "%srtx operand%d", i == 0 ? "" : ", ", i);
   else
     fprintf (file, "void");
   fprintf (file, ")\n");
   fprintf (file, "{\n");
+  if (stats.num_generator_args)
+    {
+      fprintf (file, "   rtx operands[%d] ATTRIBUTE_UNUSED = {",
+              stats.num_operand_vars);
+      for (int i = 0; i < stats.num_generator_args; i++)
+       fprintf (file, "%s operand%d", i == 0 ? "" : ",", i);
+      fprintf (file, " };\n");
+    }
+  else if (stats.num_operand_vars != 0)
+    fprintf (file, "  rtx operands[%d] ATTRIBUTE_UNUSED;\n",
+            stats.num_operand_vars);
 }
 
 /* Generate the `gen_...' function for a DEFINE_INSN.  */
@@ -496,7 +504,6 @@ static void
 gen_expand (const md_rtx_info &info, FILE *file)
 {
   struct pattern_stats stats;
-  int i;
   char *used;
 
   /* Find out how many operands this function has.  */
@@ -523,10 +530,6 @@ gen_expand (const md_rtx_info &info, FILE *file)
       return;
     }
 
-  /* For each operand referred to only with MATCH_DUPs,
-     make a local variable.  */
-  for (i = stats.num_generator_args; i <= stats.max_dup_opno; i++)
-    fprintf (file, "  rtx operand%d;\n", i);
   fprintf (file, "  rtx_insn *_val = 0;\n");
   fprintf (file, "  start_sequence ();\n");
 
@@ -539,12 +542,6 @@ gen_expand (const md_rtx_info &info, FILE *file)
   if (XSTR (expand, 3) && *XSTR (expand, 3))
     {
       fprintf (file, "  {\n");
-      if (stats.num_operand_vars > 0)
-       fprintf (file, "    rtx operands[%d];\n", stats.num_operand_vars);
-
-      /* Output code to copy the arguments into `operands'.  */
-      for (i = 0; i < stats.num_generator_args; i++)
-       fprintf (file, "    operands[%d] = operand%d;\n", i, i);
 
       /* Output the special code to be executed before the sequence
         is generated.  */
@@ -558,16 +555,6 @@ gen_expand (const md_rtx_info &info, FILE *file)
        }
       emit_c_code (XSTR (expand, 3), can_fail_p, XSTR (expand, 0), file);
 
-      /* Output code to copy the arguments back out of `operands'
-        (unless we aren't going to use them at all).  */
-      if (XVEC (expand, 1) != 0)
-       {
-         for (i = 0; i <= MAX (stats.max_opno, stats.max_dup_opno); i++)
-           {
-             fprintf (file, "    operand%d = operands[%d];\n", i, i);
-             fprintf (file, "    (void) operand%d;\n", i);
-           }
-       }
       fprintf (file, "  }\n");
     }
 
@@ -606,7 +593,6 @@ static void
 gen_split (const md_rtx_info &info, FILE *file)
 {
   struct pattern_stats stats;
-  int i;
   rtx split = info.def;
   const char *const name =
     ((GET_CODE (split) == DEFINE_PEEPHOLE2) ? "peephole2" : "split");
@@ -639,8 +625,6 @@ gen_split (const md_rtx_info &info, FILE *file)
   fprintf (file, "{\n");
 
   /* Declare all local variables.  */
-  for (i = 0; i < stats.num_operand_vars; i++)
-    fprintf (file, "  rtx operand%d;\n", i);
   fprintf (file, "  rtx_insn *_val = NULL;\n");
 
   if (GET_CODE (split) == DEFINE_PEEPHOLE2)
@@ -663,13 +647,6 @@ gen_split (const md_rtx_info &info, FILE *file)
   if (XSTR (split, 3))
     emit_c_code (XSTR (split, 3), true, name, file);
 
-  /* Output code to copy the arguments back out of `operands'  */
-  for (i = 0; i < stats.num_operand_vars; i++)
-    {
-      fprintf (file, "  operand%d = operands[%d];\n", i, i);
-      fprintf (file, "  (void) operand%d;\n", i);
-    }
-
   gen_emit_seq (XVEC (split, 2), used, info, file);
 
   /* Call `get_insns' to make a list of all the
-- 
2.43.0

Reply via email to