[Bug c/98190] New: GCC 11.0 miscompiles code using _Bool when inlining: bfxil instruction misused?
vstinner at redhat dot com
gcc-bugzilla@gcc.gnu.org
Tue Dec 8 00:22:52 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98190
Bug ID: 98190
Summary: GCC 11.0 miscompiles code using _Bool when inlining:
bfxil instruction misused?
Product: gcc
Version: 11.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: vstinner at redhat dot com
Target Milestone: ---
Created attachment 49704
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49704&action=edit
bug_bool.c reproducer
GCC 11 miscompiles attached bug_bool.c on AArch64 with -O1:
* Using -O0, memory_richcompare() returns 1 as expected
* Using -O1 or higher, memory_richcompare() returns 0 => BUG
"bfxil w4, w6, #0, #8" instruction is used to extend a single byte registry
(w6) into a larger registry (w4). It works for w4 when it's equal to 0. But it
doesn't with "bfxil w5, w6, #0, #8" when w5 is not equal to 0. Sorry, I don't
know AArch64, I cannot help too much.
$ gcc bug_bool.c -o bug_bool -O0 && ./bug_bool
equal = 1
$ gcc bug_bool.c -o bug_bool -O1 && ./bug_bool
equal = 0
* gcc (GCC) 11.0.0 20201204 (Red Hat 11.0.0-0) (Fedora:
gcc-11.0.0-0.7.fc34.aarch64)
* Fedora Rawhide (Linux 5.10.0-0.rc6.90.fc34.aarch64)
If _Bool is replaced with "char", the code works as expected. GCC optimizes
_Bool differently.
=== GCC -O1 ===
Dump of assembler code for function cmp_base2:
// w4 = 0
// w5 = 0xbb0aebc39d5f8094
0x00000000004005e8 <+0>: cmp w2, #0x0
0x00000000004005ec <+4>: b.le 0x400628 <cmp_base2+64>
0x00000000004005f0 <+8>: mov x3, #0x0 // #0
0x00000000004005f4 <+12>: ldrb w6, [x0, x3] // w6=1
0x00000000004005f8 <+16>: bfxil w4, w6, #0, #8 // w4=1
0x00000000004005fc <+20>: ldrb w6, [x1, x3] // w6=1
0x0000000000400600 <+24>: bfxil w5, w6, #0, #8 // w5=0x9d5f8001
0x0000000000400604 <+28>: cmp w4, w5 // 1 is not equal to
0x9d5f8001 !
0x0000000000400608 <+32>: b.ne 0x400620 <cmp_base2+56> // b.any
0x000000000040060c <+36>: add x3, x3, #0x1
0x0000000000400610 <+40>: cmp w2, w3
0x0000000000400614 <+44>: b.gt 0x4005f4 <cmp_base2+12>
0x0000000000400618 <+48>: mov w0, #0x1 // #1
0x000000000040061c <+52>: b 0x400624 <cmp_base2+60>
0x0000000000400620 <+56>: mov w0, #0x0 // #0
0x0000000000400624 <+60>: ret
0x0000000000400628 <+64>: mov w0, #0x1 // #1
0x000000000040062c <+68>: b 0x400624 <cmp_base2+60>
Dump of assembler code for function memory_richcompare:
0x0000000000400630 <+0>: stp x29, x30, [sp, #-32]!
0x0000000000400634 <+4>: mov x29, sp
0x0000000000400638 <+8>: mov w0, #0x1 // #1
0x000000000040063c <+12>: str w0, [sp, #24]
0x0000000000400640 <+16>: ldr w2, [sp, #24]
0x0000000000400644 <+20>: adrp x0, 0x400000
0x0000000000400648 <+24>: add x0, x0, #0x770
0x000000000040064c <+28>: mov x1, x0
0x0000000000400650 <+32>: bl 0x4005e8 <cmp_base2>
0x0000000000400654 <+36>: ldp x29, x30, [sp], #32
0x0000000000400658 <+40>: ret
=== GCC -O0 ===
(gdb) disassemble cmp_base2
Dump of assembler code for function cmp_base2:
0x00000000004005e8 <+0>: sub sp, sp, #0x30
0x00000000004005ec <+4>: str x0, [sp, #24]
0x00000000004005f0 <+8>: str x1, [sp, #16]
0x00000000004005f4 <+12>: str w2, [sp, #12]
0x00000000004005f8 <+16>: str wzr, [sp, #44]
0x00000000004005fc <+20>: b 0x400668 <cmp_base2+128>
0x0000000000400600 <+24>: ldr x0, [sp, #24]
0x0000000000400604 <+28>: ldrb w0, [x0]
0x0000000000400608 <+32>: strb w0, [sp, #39]
0x000000000040060c <+36>: ldr x0, [sp, #16]
0x0000000000400610 <+40>: ldrb w0, [x0]
0x0000000000400614 <+44>: strb w0, [sp, #38]
0x0000000000400618 <+48>: ldrb w1, [sp, #39]
0x000000000040061c <+52>: ldrb w0, [sp, #38]
0x0000000000400620 <+56>: cmp w1, w0
0x0000000000400624 <+60>: cset w0, eq // eq = none
0x0000000000400628 <+64>: and w0, w0, #0xff
0x000000000040062c <+68>: str w0, [sp, #40]
0x0000000000400630 <+72>: ldr w0, [sp, #40]
0x0000000000400634 <+76>: cmp w0, #0x0
0x0000000000400638 <+80>: b.gt 0x400644 <cmp_base2+92>
0x000000000040063c <+84>: ldr w0, [sp, #40]
0x0000000000400640 <+88>: b 0x40067c <cmp_base2+148>
0x0000000000400644 <+92>: ldr x0, [sp, #24]
0x0000000000400648 <+96>: add x0, x0, #0x1
0x000000000040064c <+100>: str x0, [sp, #24]
0x0000000000400650 <+104>: ldr x0, [sp, #16]
0x0000000000400654 <+108>: add x0, x0, #0x1
0x0000000000400658 <+112>: str x0, [sp, #16]
0x000000000040065c <+116>: ldr w0, [sp, #44]
0x0000000000400660 <+120>: add w0, w0, #0x1
0x0000000000400664 <+124>: str w0, [sp, #44]
0x0000000000400668 <+128>: ldr w1, [sp, #44]
0x000000000040066c <+132>: ldr w0, [sp, #12]
0x0000000000400670 <+136>: cmp w1, w0
0x0000000000400674 <+140>: b.lt 0x400600 <cmp_base2+24> // b.tstop
0x0000000000400678 <+144>: mov w0, #0x1 // #1
0x000000000040067c <+148>: add sp, sp, #0x30
0x0000000000400680 <+152>: ret
Dump of assembler code for function memory_richcompare:
0x0000000000400684 <+0>: stp x29, x30, [sp, #-32]!
0x0000000000400688 <+4>: mov x29, sp
0x000000000040068c <+8>: adrp x0, 0x400000
0x0000000000400690 <+12>: add x0, x0, #0x7c0
0x0000000000400694 <+16>: str x0, [sp, #24]
0x0000000000400698 <+20>: mov w0, #0x1 // #1
0x000000000040069c <+24>: str w0, [sp, #16]
0x00000000004006a0 <+28>: ldr w0, [sp, #16]
0x00000000004006a4 <+32>: mov w2, w0
0x00000000004006a8 <+36>: ldr x1, [sp, #24]
0x00000000004006ac <+40>: ldr x0, [sp, #24]
0x00000000004006b0 <+44>: bl 0x4005e8 <cmp_base2>
0x00000000004006b4 <+48>: ldp x29, x30, [sp], #32
0x00000000004006b8 <+52>: ret
Note: bug discovered in Python on Fedora Rawhide when running test_buffer:
https://bugs.python.org/issue42587
More information about the Gcc-bugs
mailing list