https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79619
Bug ID: 79619
Summary: store via pointer obtained from alternate address
space offset 0 dropped
Product: gcc
Version: 6.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: target
Assignee: unassigned at gcc dot gnu.org
Reporter: roland at gnu dot org
CC: rth at gcc dot gnu.org
Target Milestone: ---
Target: x86_64-elf
Given this test code:
void bug(void) {
*(*(char*__seg_fs*)0) = 1;
}
void nobug(void) {
*(*(char*__seg_fs*)0) = 1;
*(*(char*__seg_fs*)8) = 1;
}
I get this:
.text
.globl bug
.type bug, @function
bug:
.LFB0:
.cfi_startproc
rep ret
.cfi_endproc
.LFE0:
.size bug, .-bug
.globl nobug
.type nobug, @function
nobug:
.LFB1:
.cfi_startproc
movq %fs:0, %rax
movb $1, (%rax)
movq %fs:8, %rax
movb $1, (%rax)
ret
.cfi_endproc
.LFE1:
.size nobug, .-nobug
.ident "GCC: (GNU) 6.2.0"
x86_64 GCC at -O1 or better silently elides the store in bug. My guess is that
it's deciding *(TYPE __seg_fs*)0 constitutes a null pointer dereference and is
therefore UB so screw everybody. But alternate-address-space 0 is not a null
pointer, it's just like any other alternate-address-space pointer value and
should not be treated specially. (Except that if you wanted to "know" that the
target ABI is that %fs:0 == %fs.base, then you can optimize
(*(char*__seg_fs*)0)[n] accesses to direct "%fs:n"; LLVM does this for x86-64
glibc-based targets. But that's a missed optimization opportunity unrelated to
this bug.)
But note how the mere presence of a different alternate-address-space reference
not at zero in the same function (nobug) makes it emit both stores! Definitely
fishy.
Maybe related to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66768 but that's
beyond my ken.