https://gcc.gnu.org/g:02c3910f75ddae52dd59775bf9a6c4452bbdd0ac

commit r16-782-g02c3910f75ddae52dd59775bf9a6c4452bbdd0ac
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Wed May 21 10:01:29 2025 +0100

    genemit: Consistently use operand arrays in gen_* functions
    
    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.
    
    gcc/
            * genemit.cc (gen_rtx_scratch, gen_exp): Use operands[%d] rather 
than
            operand%d.
            (start_gen_insn): Mark the incoming arguments as const and store
            them to an operands array.
            (gen_expand, gen_split): Remove copies into and out of the operands
            array.

Diff:
---
 gcc/genemit.cc | 61 ++++++++++++++++++----------------------------------------
 1 file changed, 19 insertions(+), 42 deletions(-)

diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index 90f36e293b4b..ed87f1a903d3 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, "%sconst rtx 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

Reply via email to