+2019-02-13 Wilco Dijkstra <wdijkstr@arm.com>
+
+ PR target/89190
+ * config/arm/arm.c (ldm_stm_operation_p) Set
+ addr_reg_in_reglist correctly for first register.
+ (load_multiple_sequence): Remove dead base check.
+ (gen_ldm_seq): Correctly set write_back for Thumb-1.
+
2019-02-13 Tamar Christina <tamar.christina@arm.com>
PR target/88847
if (load && (REGNO (reg) == SP_REGNUM) && (REGNO (addr) != SP_REGNUM))
return false;
+ if (regno == REGNO (addr))
+ addr_reg_in_reglist = true;
+
for (; i < count; i++)
{
elt = XVECEXP (op, 0, i);
int unsorted_regs[MAX_LDM_STM_OPS];
HOST_WIDE_INT unsorted_offsets[MAX_LDM_STM_OPS];
int order[MAX_LDM_STM_OPS];
- rtx base_reg_rtx = NULL;
int base_reg = -1;
int i, ldm_case;
if (i == 0)
{
base_reg = REGNO (reg);
- base_reg_rtx = reg;
if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
return 0;
}
*load_offset = unsorted_offsets[order[0]];
}
- if (TARGET_THUMB1
- && !peep2_reg_dead_p (nops, base_reg_rtx))
- return 0;
-
if (unsorted_offsets[order[0]] == 0)
ldm_case = 1; /* ldmia */
else if (TARGET_ARM && unsorted_offsets[order[0]] == 4)
if (TARGET_THUMB1)
{
- gcc_assert (peep2_reg_dead_p (nops, base_reg_rtx));
gcc_assert (ldm_case == 1 || ldm_case == 5);
- write_back = TRUE;
+
+ /* Thumb-1 ldm uses writeback except if the base is loaded. */
+ write_back = true;
+ for (i = 0; i < nops; i++)
+ if (base_reg == regs[i])
+ write_back = false;
+
+ /* Ensure the base is dead if it is updated. */
+ if (write_back && !peep2_reg_dead_p (nops, base_reg_rtx))
+ return false;
}
if (ldm_case == 5)
rtx newbase = TARGET_THUMB1 ? base_reg_rtx : gen_rtx_REG (SImode, regs[0]);
emit_insn (gen_addsi3 (newbase, base_reg_rtx, GEN_INT (offset)));
offset = 0;
- if (!TARGET_THUMB1)
- base_reg_rtx = newbase;
+ base_reg_rtx = newbase;
}
for (i = 0; i < nops; i++)