This corrects an error in store_multiple_operation. We're only generating the writeback version of the instruction on Thumb-1, so that's where we must make sure the base register isn't also stored.
The ARMv7 manual is unfortunately not totally clear that this does in fact produce unpredictable results; it seems to suggest that this is the case only for the T2 encoding. Older documentation makes it clear. Tested on arm-eabi{,mthumb}. Bernd
* config/arm/arm.c (store_multiple_sequence): Avoid cases where the base reg is stored iff compiling for Thumb1. * gcc.target/arm/pr49641.c: New test. Index: gcc/config/arm/arm.c =================================================================== --- gcc/config/arm/arm.c (revision 175906) +++ gcc/config/arm/arm.c (working copy) @@ -9950,7 +9950,10 @@ store_multiple_sequence (rtx *operands, /* If it isn't an integer register, then we can't do this. */ if (unsorted_regs[i] < 0 || (TARGET_THUMB1 && unsorted_regs[i] > LAST_LO_REGNUM) - || (TARGET_THUMB2 && unsorted_regs[i] == base_reg) + /* For Thumb1, we'll generate an instruction with update, + and the effects are unpredictable if the base reg is + stored. */ + || (TARGET_THUMB1 && unsorted_regs[i] == base_reg) || (TARGET_THUMB2 && unsorted_regs[i] == SP_REGNUM) || unsorted_regs[i] > 14) return 0; Index: gcc/testsuite/gcc.target/arm/pr49641.c =================================================================== --- gcc/testsuite/gcc.target/arm/pr49641.c (revision 0) +++ gcc/testsuite/gcc.target/arm/pr49641.c (revision 0) @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-mthumb -O2" } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-final { scan-assembler-not "stmia\[\\t \]*r3!\[^\\n]*r3" } } */ +typedef struct { + void *t1, *t2, *t3; +} z; +extern volatile int y; +static inline void foo(z *x) { + x->t1 = &x->t2; + x->t2 = ((void *)0); + x->t3 = &x->t1; +} +extern z v; +void bar (void) { + y = 0; + foo(&v); +}