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: [email protected]
ReportedBy: [email protected]
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.