http://gcc.gnu.org/bugzilla/show_bug.cgi?id=54414
Bug #: 54414 Summary: ARM:mis-compiled prologue/epilogue on cortex-m0 when optimizing with -Os Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: target AssignedTo: unassig...@gcc.gnu.org ReportedBy: amker.ch...@gmail.com For the case of pr45070.c as below: /* PR45070 */ extern void abort(void); struct packed_ushort { unsigned short ucs; } __attribute__((packed)); struct source { int pos, length; int flag; }; static void __attribute__((noinline)) fetch(struct source *p) { p->length = 128; } static struct packed_ushort __attribute__((noinline)) next(struct source *p) { struct packed_ushort rv; if (p->pos >= p->length) { if (p->flag) { p->flag = 0; fetch(p); return next(p); } p->flag = 1; rv.ucs = 0xffff; return rv; } rv.ucs = 0; return rv; } int main(void) { struct source s; int i; s.pos = 0; s.length = 0; s.flag = 0; for (i = 0; i < 16; i++) { struct packed_ushort rv = next(&s); if ((i == 0 && rv.ucs != 0xffff) || (i > 0 && rv.ucs != 0)) abort(); } return 0; } Compile with below options: $ arm-none-eabi-gcc -mthumb -mcpu=cortex-m0 -Os pr45070.c -o pr45070.S The generated assembly code for function next is like: next: push {r0, r1, r2, r3, r4, lr} ldr r2, [r0] ldr r3, [r0, #4] mov r4, r0 cmp r2, r3 blt .L3 ldr r2, [r0, #8] cmp r2, #0 beq .L4 mov r3, #0 str r3, [r0, #8] add r0, r0, #4 bl fetch.isra.0 mov r0, r4 bl next mov r3, sp sxth r0, r0 strb r0, [r3] lsr r0, r0, #8 strb r0, [r3, #1] mov r3, sp ldrh r2, [r3] b .L6 .L4: mov r3, #1 str r3, [r0, #8] neg r2, r3 b .L6 .L3: mov r2, #0 .L6: add r3, sp, #12 strh r2, [r3] add r3, sp, #12 ldrb r0, [r3, #1] ldrb r2, [r3] lsl r0, r0, #8 orr r0, r2 @ sp needed for prologue pop {r1, r2, r3, r4, pc} The pc register is restored with wong value.