Broken branch code for simple condition (conditional code always executed!)
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Linaro GCC |
Invalid
|
Undecided
|
Unassigned |
Bug Description
I've created minimal test-case based on my original code, it looks like that:
writel(0x2, &offsets[0]);
if (rev == 0x4) {
writel(0x8, &offsets[16]);
}
When using Linaro gcc with -Os I get a bugged object. The second "writel" is always executed, not just for (rev == 0x4) and it's first argument is calculated in some weird way.
I incorrectly reported this problem to gcc team yesterday:
http://
but it has appeared to be Linaro-specific bug, it doesn't happen with original gcc.
I noticed this when using OpenWrt, so to make sure it's also present in original Linaro gcc I compiled it on my own (gcc-linaro-
0: 24020002 li v0,2
4: 24030004 li v1,4
8: aca20000 sw v0,0(a1)
c: 10830002 beq a0,v1,18 <test+0x18>
10: 24020008 li v0,8
14: 8ca20040 lw v0,64(a1)
18: aca20040 sw v0,64(a1)
1c: 03e00008 jr ra
20: 00000000 nop
As you can see, instruction at offset 0x18 is always executed. This is wrong.
I also compiled original gcc (gcc-4.6.4.tar.bz2) with the same binutils (binutils-
00000000 <test>:
0: 24020002 li v0,2
4: aca20000 sw v0,0(a1)
8: 24020004 li v0,4
c: 14820002 bne a0,v0,18 <test+0x18>
10: 24020008 li v0,8
14: aca20040 sw v0,64(a1)
18: 03e00008 jr ra
1c: 00000000 nop
This is exactly what I expected. After first writel (instruction at offset 0x4) a0 is compared with v0 (which contains 0x4). In case they are not equal (a0 != 4) code jumps to 0x18, which is a simple function return.
Changed in gcc-linaro: | |
status: | New → Invalid |
I'm attaching test.o compiled with mipsel- linaro- linux-gnu- gcc. This gcc comes from gcc-linaro- 4.6-2012. 12.tar. bz2.