c/7500: invalid assemly output with -O2 flag
rgohita@hotmail.com
rgohita@hotmail.com
Mon Aug 5 09:36:00 GMT 2002
>Number: 7500
>Category: c
>Synopsis: invalid assemly output with -O2 flag
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: unassigned
>State: open
>Class: wrong-code
>Submitter-Id: net
>Arrival-Date: Mon Aug 05 09:36:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Igor Mikhailov
>Release: 2.95.2 - 3.1
>Organization:
>Environment:
Linux Redhat 6.2, gcc cross-compiler for ARM
>Description:
This bug exists in gcc compilers from at least 2.95.2 to 3.1
The compilers were build for different ARM machines, with elf or coff format, with the same result.
The flags used for compilation were: -Wall -mcpu=<I've tried several, arm7tdmi is one of them>
It builds invalid code in case of -O2 optimization flag, however with -O1 flag the built code is completely Ok.
In the attached file, the wrong code is generated for is_same_ops() function. Normally, it should return 0, since the a and b variables are not the same according to the conditions. However, with the -O2 flag the function
is_same_ops returns 1.
>How-To-Repeat:
arm-gcc -O[1,2] -Wall -c assembly_bug.c
I'd like to show you the assembly code of the function, first for the -02
flag, next for the -01:
Invalid code:
00000000 <_is_same_ops>:
0: e1a0c00d mov r12, sp
4: e92dd800 stmdb sp!, {r11, r12, lr, pc}
8: e24cb004 sub r11, r12, #4 ; 0x4
c: e3a0c000 mov r12, #0 ; 0x0
10: e5902004 ldr r2, [r0, #4]
14: e5913004 ldr r3, [r1, #4]
18: e1520003 cmp r2, r3
1c: 1a000008 bne 44 <L3>
20: e5913000 ldr r3, [r1]
24: e5902000 ldr r2, [r0]
28: e3130007 tst r3, #7 ; 0x7
2c: e2122007 ands r2, r2, #7 ; 0x7
30: 13a02001 movne r2, #1 ; 0x1
34: 13a01000 movne r1, #0 ; 0x0
38: 03a01001 moveq r1, #1 ; 0x1
3c: e052c001 subs r12, r2, r1
40: 13a0c001 movne r12, #1 ; 0x1
Valid code
00000000 <_is_same_ops>:
0: e1a0c00d mov r12, sp
4: e92dd800 stmdb sp!, {r11, r12, lr, pc}
8: e24cb004 sub r11, r12, #4 ; 0x4
c: e3a0c000 mov r12, #0 ; 0x0
10: e5902004 ldr r2, [r0, #4]
14: e5913004 ldr r3, [r1, #4]
18: e1520003 cmp r2, r3
1c: 1a000008 bne 44 <L3>
20: e5903000 ldr r3, [r0]
24: e2133007 ands r3, r3, #7 ; 0x7
28: 13a03001 movne r3, #1 ; 0x1
2c: e5912000 ldr r2, [r1]
30: e3120007 tst r2, #7 ; 0x7
34: 13a02000 movne r2, #0 ; 0x0
38: 03a02001 moveq r2, #1 ; 0x1
3c: e053c002 subs r12, r3, r2
40: 13a0c001 movne r12, #1 ; 0x1
As you can see in the invalid dump, after the command at offset 0x28 the
result of the tst command is destroyed by the ands command, hence the result
will be right only in 50% of the cases:).
In the second dump however, after the ands command (offset 0x24), the correct
action is taken - the result is stored in r3.
>Fix:
The only work-around is to use -O1 instead of -O2.
>Release-Note:
>Audit-Trail:
>Unformatted:
----gnatsweb-attachment----
Content-Type: text/plain; name="assembly_bug.c"
Content-Disposition: inline; filename="assembly_bug.c"
#define ERECVALL 0x7
typedef struct {
int op;
int fd;
} file_ops_t;
static int is_same_ops(file_ops_t *esc1, file_ops_t *esc2)
{
return esc1->fd == esc2->fd &&
!(esc1->op & ERECVALL) == !(esc2->op & ERECVALL);
}
int main(void)
{
file_ops_t a, b;
int i;
a.fd = 3;
a.op = 0x10;
b.fd = 3;
b.op = 0x3;
i = is_same_ops(&a, &b);
return 0;
}
More information about the Gcc-bugs
mailing list