https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95663
Bug ID: 95663
Summary: static_cast checks for null even when the pointer is
dereferenced
Product: gcc
Version: 10.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: jzwinck at gmail dot com
Target Milestone: ---
Consider this C++ code:
struct Base1
{
int x;
};
struct Base2
{
int y;
};
struct Derived : Base1, Base2
{
int get_y() const { return y; }
};
int field(Base2* base)
{
return static_cast<Derived*>(base)->y;
}
int getter(Base2* base)
{
return static_cast<Derived*>(base)->get_y();
}
Both field() and getter() produce this with -O2 or -O3:
test rdi, rdi
je .L2
mov eax, DWORD PTR [rdi]
ret
.L2:
mov eax, DWORD PTR ds:4
ud2
That's fair, it traps if we dereference a null pointer. But I need the best
performance and don't want the null check, so I add
-fno-isolate-erroneous-paths-dereference and see:
lea rax, [rdi-4]
test rdi, rdi
cmovne rdi, rax
mov eax, DWORD PTR [rdi+4]
ret
If I read that correctly, it checks if the pointer is null so it can
dereference 0x4 instead of 0x0. That's hardly an improvement over the naive
and optimal code:
mov eax, DWORD PTR [rdi]
ret
Which is what Clang generates for field() in all versions through 10, and for
getter() up to 3.6 (3.7 through 10 generate a cmovne like GCC with no-isolate).
I tried adding __attribute__((nonnull)) to the function declarations, but it
didn't help.
Live demo: https://godbolt.org/z/XnhZoz