@@ -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++)
new file mode 100644
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_arch_v8m_base_ok } */
+/* { dg-options "-O2" } */
+/* { dg-add-options arm_arch_v8m_base } */
+
+long long a;
+int b, c;
+int d(int e, int f) { return e << f; }
+void g() {
+ long long h;
+ char i = d(b >= 7, 2);
+ c = i == 0 ?: 1 / i;
+ h = c && a ?: c + a;
+ b = h;
+}