[ARM] Fix Thumb-1 ldm (PR89190)

This patch fixes an ICE in the Thumb-1 LDM peepholer.  Thumb-1 LDMs
always update the base register except if the base is loaded.
The current implementation rejects LDMs where the base is not dead,
however this doesn't exclude the case where the base is loaded as
well as dead.  Fix this by explicitly checking whether the base is
loaded.  Also enable LDMs which load the first register.

    gcc/
	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.

    testsuite/
	PR target/89190
	* gcc.target/arm/pr89190.c: New test.

From-SVN: r268848
This commit is contained in:
Wilco Dijkstra 2019-02-13 16:22:25 +00:00 committed by Wilco Dijkstra
parent 6174de7c40
commit 125b98b127
3 changed files with 27 additions and 10 deletions

View File

@ -1,3 +1,11 @@
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

View File

@ -13191,6 +13191,9 @@ ldm_stm_operation_p (rtx op, bool load, machine_mode mode,
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);
@ -13385,7 +13388,6 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
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;
@ -13430,7 +13432,6 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
if (i == 0)
{
base_reg = REGNO (reg);
base_reg_rtx = reg;
if (TARGET_THUMB1 && base_reg > LAST_LO_REGNUM)
return 0;
}
@ -13489,10 +13490,6 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *saved_order,
*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)
@ -13868,9 +13865,17 @@ gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
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)
@ -13878,8 +13883,7 @@ gen_ldm_seq (rtx *operands, int nops, bool sort_regs)
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++)

View File

@ -1,3 +1,8 @@
2019-02-13 Wilco Dijkstra <wdijkstr@arm.com>
PR target/89190
* gcc.target/arm/pr89190.c: New test.
2019-02-13 David Malcolm <dmalcolm@redhat.com>
PR c++/89036