From: Artemiy Volkov <arte...@synopsys.com>

Consider the following (RISC-V) instruction pair:

mul s6,a1,a2
add s6,a4,s6

Without this patch, while handling the second instruction, (a) the
existing chain for s6 will first be closed (upon the terminate_write
action for the input operand), then (b) a new one will be opened (upon
the mark_write action for the output operand).  This will likely lead to
the two output operands being different physical registers, breaking the
single-output property required for some macro-op fusion pairs.

This patch, using the single_output_fused_pair_p () predicate introduced
earlier, changes the regrename behavior for such pairs to append the
input and the output operands to the existing chain (as if both actions
were mark_read), instead of breaking the current renaming chain and
starting a new one.  This ensures that the output operands of both fused
instructions are kept in the same hard register, and that the
single-output property of the insn pair is preserved.

gcc/ChangeLog:

        * regrename.cc (scan_rtx_reg): Handle fused insn pairs.

Signed-off-by: Artemiy Volkov <arte...@synopsys.com>
---
 gcc/regrename.cc | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/gcc/regrename.cc b/gcc/regrename.cc
index 7de88812e4c..cb03c1d71dd 100644
--- a/gcc/regrename.cc
+++ b/gcc/regrename.cc
@@ -1117,6 +1117,12 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class 
cl, enum scan_actions act
   unsigned this_regno = REGNO (x);
   int this_nregs = REG_NREGS (x);
 
+  /* Do not process write actions for the second instruction of
+     a macro-fused pair of two single_sets.  */
+  if ((action == mark_write || action == terminate_write)
+       && single_output_fused_pair_p (insn))
+    return;
+
   if (action == mark_write)
     {
       if (type == OP_OUT)
@@ -1153,7 +1159,9 @@ scan_rtx_reg (rtx_insn *insn, rtx *loc, enum reg_class 
cl, enum scan_actions act
       return;
     }
 
-  if ((type == OP_OUT) != (action == terminate_write || action == mark_access))
+  if ((type == OP_OUT) != (action == terminate_write || action == mark_access)
+       && ! (type == OP_OUT && action == mark_read
+             && single_output_fused_pair_p (insn)))
     return;
 
   for (p = &open_chains; *p;)
-- 
2.43.0

Reply via email to