This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/86132] New: Failure to elide condition known to be non-null
- From: "nathan at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 13 Jun 2018 11:15:49 +0000
- Subject: [Bug middle-end/86132] New: Failure to elide condition known to be non-null
- Auto-submitted: auto-generated
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86132
Bug ID: 86132
Summary: Failure to elide condition known to be non-null
Product: gcc
Version: 8.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: middle-end
Assignee: unassigned at gcc dot gnu.org
Reporter: nathan at gcc dot gnu.org
Target Milestone: ---
Created attachment 44268
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44268&action=edit
test case
x86_64 linux target using trunk:
trunk/obj/x86_64/gcc/cc1plus jay.ii -O3
Both single_slow() and single() implement a cache of an object that is
expensive to construct. We know if we call either once, subsequent calls will
return the same value -- can the compiler tell? (Ignore the problem of
operator new throwing, that's not important, alternatives that cannot thtor
show the same problem).
Yes and no. a() is optimized down to a single inlined call of single(). b()
is not so fortunate and contains two inlined calls of single().
single_slow() is annotated to return non-null. but its internals could well be
opaque. single() is inlineable, and expected to be so.
Thus the value propagator should be able to determine that the assignment to
single::object of the result of single_slow(), assigns a non-null value. It
manages to do this in the a() case, but not the b() case. My guess is it
thinks that the call to want_foo(Foo &) could affect the value of
single::object. But that's not possible. It's function-local, its address
does not escape, and it has a single assignment only reachable when it is NULL.
_Z1av:
cmpq $0, _ZZ6singlevE6object(%rip)
je .L15 ;; the only test
ret
.L15:
subq $8, %rsp
call _Z11single_slowv ; the one call
movq %rax, _ZZ6singlevE6object(%rip)
addq $8, %rsp
ret
_Z1bv:
subq $8, %rsp
movq _ZZ6singlevE6object(%rip), %rdi
testq %rdi, %rdi ;; test one.
je .L20
.L17:
call _Z8want_fooR3Foo
movq _ZZ6singlevE6object(%rip), %rdi
testq %rdi, %rdi ;; test two
je .L21
addq $8, %rsp
jmp _Z8want_fooR3Foo
.L20:
call _Z11single_slowv
movq %rax, %rdi
movq %rax, _ZZ6singlevE6object(%rip)
jmp .L17
.L21:
call _Z11single_slowv
movq %rax, _ZZ6singlevE6object(%rip)
movq %rax, %rdi
addq $8, %rsp
jmp _Z8want_fooR3Foo