[cfe-dev] Virtual function call optimization(memoization) questions

Arthur O'Dwyer via cfe-dev cfe-dev at lists.llvm.org
Tue Jun 16 08:26:54 PDT 2020

On Tue, Jun 16, 2020 at 2:31 AM Ninu-Ciprian Marginean via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> I have a virtual function call in a loop. All the time, the same method is
> called:
> https://godbolt.org/z/WFp2rm
> The loop is in method work; the virtual call is to method id.
> We can see that method work gets inlined, but inside the loop, there are
> always two pointer dereferences:
> mov     rax, qword ptr [r14]
> call    qword ptr [rax]
> Since the object referred to by b, never changes to a different object,
> this could(at least in this case), be cached.

I believe that this is a similar problem to what was recently discussed in
the thread titled "[cfe-dev] Smart Pointer Lifetime Optimizations".  In
this case (as in that case), the human programmer knows that the call to
`b->do_id()` does not actually change the value of b's vptr; but the
compiler cannot make that assumption because the C++ Standard technically
permits a virtual method to destroy and re-create `b` with a completely
different dynamic type.

As in the smart-pointer case, Clang provides a "noescape" attribute that
addresses half of the problem, but doesn't provide any "really_const"
attribute that allows the human programmer to say "Look, I promise that
this function call *really does not change* its argument!"  (I think
LLVM's `readonly` attribute would help, but Clang does not expose that
attribute to the C++ programmer.)
I tried slapping all the attributes I could think of onto this member
function — noescape, const, pure — and none of them helped.
Even marking the stack objects as `const` didn't help, which surprises me
in this case:

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20200616/969af1bc/attachment.html>

More information about the cfe-dev mailing list