Hi,

The attached patch fixes PR 101469.
Tested by the original reporter Rin Okuyama on NetBSD with GCC 10.5.
Applied to master, GCC 11, GCC 12, GCC 13 after 'make all' sanity check.

Cheers,
Oleg


gcc/ChangeLog:

        PR target/101469
        * config/sh/sh.md (peephole2): Handle case where eliminated reg
        is also used by the address of the following memory
operand.

diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 4622dba0121..76e7774cef3 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -10680,6 +10680,45 @@
    && peep2_reg_dead_p (2, operands[1]) && peep2_reg_dead_p (3, operands[0])"
   [(const_int 0)]
 {
+  if (MEM_P (operands[3]) && reg_overlap_mentioned_p (operands[0], operands[3]))
+    {
+      // Take care when the eliminated operand[0] register is part of
+      // the destination memory address.
+      rtx addr = XEXP (operands[3], 0);
+
+      if (REG_P (addr))
+	operands[3] = replace_equiv_address (operands[3], operands[1]);
+
+      else if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0))
+	       && CONST_INT_P (XEXP (addr, 1))
+	       && REGNO (operands[0]) == REGNO (XEXP (addr, 0)))
+	operands[3] = replace_equiv_address (operands[3],
+			    gen_rtx_PLUS (SImode, operands[1], XEXP (addr, 1)));
+
+      else if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0))
+	       && REG_P (XEXP (addr, 1)))
+        {
+          // register + register address  @(R0, Rn)
+          // can change only the Rn in the address, not R0.
+          if (REGNO (operands[0]) == REGNO (XEXP (addr, 0))
+	      && REGNO (XEXP (addr, 0)) != 0)
+	    {
+	      operands[3] = replace_equiv_address (operands[3],
+			    gen_rtx_PLUS (SImode, operands[1], XEXP (addr, 1)));
+	    }
+          else if (REGNO (operands[0]) == REGNO (XEXP (addr, 1))
+		   && REGNO (XEXP (addr, 1)) != 0)
+            {
+	      operands[3] = replace_equiv_address (operands[3],
+			    gen_rtx_PLUS (SImode, XEXP (addr, 0), operands[1]));
+            }
+          else
+            FAIL;
+        }
+      else
+        FAIL;
+    }
+
   emit_insn (gen_addsi3 (operands[1], operands[1], operands[2]));
   sh_peephole_emit_move_insn (operands[3], operands[1]);
 })

Reply via email to