]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
SH: Fix PR101496 peephole bug
authorOleg Endo <olegendo@gcc.gnu.org>
Fri, 14 Jul 2023 00:54:20 +0000 (09:54 +0900)
committerOleg Endo <olegendo@gcc.gnu.org>
Fri, 14 Jul 2023 00:54:20 +0000 (09:54 +0900)
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.

gcc/config/sh/sh.md

index 5cb179548256e2ea6c24b0f2db9062b4963bcc7c..484a34fe443837fba813bb7ca432a7a45f9ae0d8 100644 (file)
    && 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]);
 })