Hi Wilco,
On 2/13/19 12:42 PM, Wilco Dijkstra wrote:
ping
From: Wilco Dijkstra
Sent: 04 February 2019 14:59
To: GCC Patches
Cc: nd; Kyrylo Tkachov
Subject: [PATCH][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.
Bootstrap OK on armhf, testsuite passes. OK for commit?
Ok.
Thanks,
Kyrill
ChangeLog:
2019-02-04 Wilco Dijkstra <wdijk...@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.
PR target/89190
* gcc.target/arm/pr89190.c: New test.
--
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index
16e22eed871ca34d56c83c334688e5a95970638e..c4c9b4a667100d81d918196713e40b01ee232ee2
100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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++)
diff --git a/gcc/testsuite/gcc.target/arm/pr89190.c
b/gcc/testsuite/gcc.target/arm/pr89190.c
new file mode 100644
index
0000000000000000000000000000000000000000..e622d7081ed01a6318e2c4b3e07598d495bd7e0f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr89190.c
@@ -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;
+}