[backport gcc-4.9/trunk r198091 + r19803, fixes regression from r188738 ] List-Archive: From: "Greta Yorsh" Subject: [PATCH, ARM] Fix PR56797 Date: Fri, 19 Apr 2013 10:34:49 +0100 Fix PR56797 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56797 The problem is that peephole optimizer thinks it can generate an ldm, but the pattern for ldm no longer matches, because after r188738 it requires that if one of the destination registers is SP then the base register must be SP, and it's not SP in the test case. The test case fails on armv5t but doesn't fail on armv6t2 or armv7-a because peephole doesn't trigger there (because there is a different epilogue sequence). It looks like a latent problem for other architecture or CPUs. This patch adds this condition to the peephole optimizer. No regression on qemu for arm-none-eabi and fixes the test reported in the PR. I couldn't minimize the test sufficiently to include it in the testsuite. Ok for trunk? Thanks, Greta gcc/ 2013-04-19 Greta Yorsh * config/arm/arm.c (load_multiple_sequence, ldm_stm_operation_p): Fix spelling in two comments. 2013-04-19 Greta Yorsh PR target/56797 * config/arm/arm.c (load_multiple_sequence): Require SP as base register for loads if SP is in the register list. --- gcc-4.8.0/gcc/config/arm/arm.c.~1~ 2013-03-11 12:48:34.000000000 +0100 +++ gcc-4.8.0/gcc/config/arm/arm.c 2013-04-20 13:32:16.309636371 +0200 @@ -10443,7 +10443,7 @@ ldm_stm_operation_p (rtx op, bool load, /* Don't allow SP to be loaded unless it is also the base register. It guarantees that SP is reset correctly when an LDM instruction - is interruptted. Otherwise, we might end up with a corrupt stack. */ + is interrupted. Otherwise, we might end up with a corrupt stack. */ if (load && (REGNO (reg) == SP_REGNUM) && (REGNO (addr) != SP_REGNUM)) return false; @@ -10707,6 +10707,13 @@ load_multiple_sequence (rtx *operands, i || (i != nops - 1 && unsorted_regs[i] == base_reg)) return 0; + /* Don't allow SP to be loaded unless it is also the base + register. It guarantees that SP is reset correctly when + an LDM instruction is interrupted. Otherwise, we might + end up with a corrupt stack. */ + if (unsorted_regs[i] == SP_REGNUM && base_reg != SP_REGNUM) + return 0; + unsorted_offsets[i] = INTVAL (offset); if (i == 0 || unsorted_offsets[i] < unsorted_offsets[order[0]]) order[0] = i;