aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleg Endo <olegendo@gcc.gnu.org>2023-07-14 09:54:20 +0900
committerOleg Endo <olegendo@gcc.gnu.org>2023-07-14 09:54:20 +0900
commit4dbb3af1efe55174a714d15c2994cf2842ef8c28 (patch)
treefbe37b36cbafa83b53448940b4fea891fb24ad1e
parent3d0ca8b55b9a882b9cc9b02b1d7db6a449be10c4 (diff)
downloadgcc-4dbb3af1efe55174a714d15c2994cf2842ef8c28.zip
gcc-4dbb3af1efe55174a714d15c2994cf2842ef8c28.tar.gz
gcc-4dbb3af1efe55174a714d15c2994cf2842ef8c28.tar.bz2
SH: Fix PR101496 peephole bug
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.
-rw-r--r--gcc/config/sh/sh.md39
1 files changed, 39 insertions, 0 deletions
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 5cb1795..484a34f 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]);
})