diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2023-07-14 09:54:20 +0900 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2023-07-14 09:54:20 +0900 |
commit | 4dbb3af1efe55174a714d15c2994cf2842ef8c28 (patch) | |
tree | fbe37b36cbafa83b53448940b4fea891fb24ad1e | |
parent | 3d0ca8b55b9a882b9cc9b02b1d7db6a449be10c4 (diff) | |
download | gcc-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.md | 39 |
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]); }) |