https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88714
--- Comment #36 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Furthermore, nothing really guarantees you it must match, gen_operands_ldrd_strd doesn't call plus_constant, it calls mem_ok_for_ldrd_strd on each mem and subtracts the offsets. So, probably a helper that does exactly that should be used in the condition of the define_insns. That already calls arm_legitimate_address_p too. mem_ok_for_lrdr_strd is broken too: else if (GET_CODE (addr) == PLUS || GET_CODE (addr) == MINUS) { *base = XEXP (addr, 0); *offset = XEXP (addr, 1); return (REG_P (*base) && CONST_INT_P (*offset)); } The handling of MINUS that way makes no sense. If it wants to handle MINUS, offset should be HOST_WIDE_INT rather than rtx and it should do: else if (GET_CODE (addr) == PLUS && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) { *base = XEXP (addr, 0); *offset = INTVAL (XEXP (addr, 1)); return true; } else if (GET_CODE (addr) == MINUS && REG_P (XEXP (addr, 0)) && CONST_INT_P (XEXP (addr, 1))) { *base = XEXP (addr, 0); *offset = -UINTVAL (XEXP (addr, 1)); return true; } or just don't try to handle MINUS at all, MINUS with CONST_INT as op2 is not canonical with the exception of HOST_WIDE_INT_MIN, but that is not possible for SImode.