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
          Reporter: nathan at gcc dot
  Target Milestone: ---

Created attachment 44268
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.

        cmpq    $0, _ZZ6singlevE6object(%rip)
        je      .L15   ;; the only test
        subq    $8, %rsp
        call    _Z11single_slowv  ; the one call
        movq    %rax, _ZZ6singlevE6object(%rip)
        addq    $8, %rsp

        subq    $8, %rsp
        movq    _ZZ6singlevE6object(%rip), %rdi
        testq   %rdi, %rdi  ;; test one.
        je      .L20
        call    _Z8want_fooR3Foo
        movq    _ZZ6singlevE6object(%rip), %rdi
        testq   %rdi, %rdi  ;; test two
        je      .L21
        addq    $8, %rsp
        jmp     _Z8want_fooR3Foo
        call    _Z11single_slowv
        movq    %rax, %rdi
        movq    %rax, _ZZ6singlevE6object(%rip)
        jmp     .L17
        call    _Z11single_slowv
        movq    %rax, _ZZ6singlevE6object(%rip)
        movq    %rax, %rdi
        addq    $8, %rsp
        jmp     _Z8want_fooR3Foo

Reply via email to