gen_exp has code to detect when the same operand is used multiple
times.  It ensures that second and subsequent uses call copy_rtx,
to enforce correct unsharing.

However, for historical reasons that aren't clear to me, this was
skipped for a define_insn unless the define_insn was a parallel.
It was also skipped for a single define_expand instruction,
regardless of its contents.

This meant that a single parallel instruction was treated differently
between define_insn (where sharing rules were followed) and
define_expand (where sharing rules weren't followed).  define_splits
and define_peephole2s followed the sharing rules in all cases.

This patch makes everything follow the sharing rules.  The code
it touches will be removed by the proposed bytecode-based expansion,
which will use its own tracking when enforcing sharing rules.
However, it seemed better for staging and bisection purposes
to make this change first.

gcc/
        * genemit.cc (generator::used): Update comment.
        (generator::gen_exp): Remove handling of null unused arrays.
        (gen_insn, gen_expand): Always pass a used array.
        (output_add_clobbers): Note why the used array is null here.
---
 gcc/genemit.cc | 27 ++++++++++++---------------
 1 file changed, 12 insertions(+), 15 deletions(-)

diff --git a/gcc/genemit.cc b/gcc/genemit.cc
index df2b319fd23..a7e49a24506 100644
--- a/gcc/genemit.cc
+++ b/gcc/genemit.cc
@@ -78,9 +78,9 @@ struct generator
   /* The type of subroutine that we're expanding.  */
   rtx_code subroutine_type;
 
-  /* If nonnull, index N indicates that the original operand N has already
-     been used to replace a MATCH_OPERATOR or MATCH_DUP, and so any further
-     replacements must make a copy.  */
+  /* Index N indicates that the original operand N has already been used to
+     replace a MATCH_OPERATOR or MATCH_DUP, and so any further replacements
+     must make a copy.  */
   char *used;
 
   /* The construct that we're expanding.  */
@@ -135,15 +135,12 @@ generator::gen_exp (rtx x)
     {
     case MATCH_OPERAND:
     case MATCH_DUP:
-      if (used)
+      if (used[XINT (x, 0)])
        {
-         if (used[XINT (x, 0)])
-           {
-             fprintf (file, "copy_rtx (operands[%d])", XINT (x, 0));
-             return;
-           }
-         used[XINT (x, 0)] = 1;
+         fprintf (file, "copy_rtx (operands[%d])", XINT (x, 0));
+         return;
        }
+      used[XINT (x, 0)] = 1;
       fprintf (file, "operands[%d]", XINT (x, 0));
       return;
 
@@ -505,10 +502,7 @@ gen_insn (const md_rtx_info &info, FILE *file)
   /* Output code to construct and return the rtl for the instruction body.  */
 
   rtx pattern = add_implicit_parallel (XVEC (insn, 1));
-  /* ??? This is the traditional behavior, but seems suspect.  */
-  char *used = (XVECLEN (insn, 1) == 1
-               ? NULL
-               : XCNEWVEC (char, stats.num_generator_args));
+  char *used = XCNEWVEC (char, stats.num_generator_args);
   fprintf (file, "  return ");
   generator (DEFINE_INSN, used, info, file).gen_exp (pattern);
   fprintf (file, ";\n}\n\n");
@@ -555,10 +549,12 @@ gen_expand (const md_rtx_info &info, FILE *file)
       && stats.max_opno >= stats.max_dup_opno
       && XVECLEN (expand, 1) == 1)
     {
+      used = XCNEWVEC (char, stats.num_operand_vars);
       fprintf (file, "  return ");
-      generator (DEFINE_EXPAND, NULL, info, file)
+      generator (DEFINE_EXPAND, used, info, file)
        .gen_exp (XVECEXP (expand, 1, 0));
       fprintf (file, ";\n}\n\n");
+      XDELETEVEC (used);
       return;
     }
 
@@ -717,6 +713,7 @@ output_add_clobbers (const md_rtx_info &info, FILE *file)
        {
          fprintf (file, "      XVECEXP (pattern, 0, %d) = ", i);
          rtx clobbered_value = RTVEC_ELT (clobber->pattern, i);
+         /* Pass null for USED since there are no operands.  */
          generator (clobber->code, NULL, info, file)
            .gen_exp (clobbered_value);
          fprintf (file, ";\n");
-- 
2.43.0

Reply via email to