[cfe-dev] Potential missed optimization - unnecessary reload of vtable ptr inside loop body

John McCall via cfe-dev cfe-dev at lists.llvm.org
Thu Mar 8 12:15:33 PST 2018



> On Mar 8, 2018, at 2:59 PM, Alex Wang <aw1621107 at gmail.com> wrote:
> 
> 
>> On Mar 7, 2018, at 8:18 PM, John McCall <rjmccall at apple.com> wrote:
>> 
>> 
>> 
>>> On Mar 7, 2018, at 1:41 PM, Alex Wang via cfe-dev <cfe-dev at lists.llvm.org> wrote:
>>> 
>>> Hello all!
>>> 
>>> I posted a question about a potential missed optimization to llvm-dev, but was
>>> directed here since it concerned more C++-specific bits of code. Previous
>>> conversion can be found at [0] and [1].
>>> 
>>> The code in question is here: https://godbolt.org/g/ec5cP7
>>> 
>>> My main question here is about assembly lines 24 and 46, where I think the
>>> vtable pointer for the Rect object is being reloaded every iteration of the
>>> loop. nbjoerg on #llvm said that's due to the possibility of placement new being
>>> used somewhere inside the called function, but I'm not entirely sure that
>>> placement new can change what vtable the vtable pointer points to.
>>> 
>>> (I'm new to this language lawyering stuff, so please let me know what I mess up)
>>> 
>>> As far as I understand, paragraph 8 of 6.6.3 [basic.life] in the most recent
>>> draft of the standard says that references or names of an object that has been
>>> "replaced" by placement new are only "redirected" to the new object if the new
>>> object is the same type and no other class derives from that type; otherwise,
>>> the reference/name refers to an object whose lifetime has ended. Thus, any uses
>>> of the "this" pointer after a member function is called are only valid if the
>>> placement new'd object is the same type, and so has the same vtable, which means
>>> the vtable pointer does not have to be reloaded.
>>> 
>>> The example for point 6.5 of paragraph 6 of 6.6.3 sort of supports this
>>> interpretation, since calling B::mutate() changes the type of *this, which
>>> causes pb to point to an object whose lifetime has ended, and further method
>>> calls through pb result in undefined behavior.
>>> 
>>> Is this reasoning correct? ICC 18, Clang trunk, Clang 5.0, GCC 7.3, GCC trunk,
>>> and MSVC 19 all perform the reload, so I'm guessing I'm wrong, but I'm not sure
>>> how.
>> 
>> Your reasoning is right, but it's proven to be very difficult to write a reliable general
>> optimization that only triggers on the wrong cases and not when, say, constructing
> 
> Wrong cases? Guessing you meant right cases?

Yes, sorry.

>> different base-class subobjects of a class.  Our optimization can be enabled with
>> -fstrict-vtable-pointers, but it's still experimental.
> 
> Even when dealing with constructing/destructing objects, I thought that the
> object's type/vtable pointer effectively changes only between the base
> constructor finishing and the next constructor starting, or vice-versa for
> destruction. So even if full devirtualization isn't possible, the vtable pointer
> could still be hoisted out of loops.

Yes, absolutely.  I'm just describing the issues that I understand to make the analysis
difficult, not saying that it's impossible.

> Is that kind of optimization just too
> specific to spend time on, compared to the benefits from getting
> -fstrict-vtable-pointers implemented correctly?

I think everybody agrees that this is likely to be an extremely powerful optimization.

> Also, if I were interested in enabling this flag in my codebase, are there any
> issues beyond the ones listed in this 2015 Nov. email [0]?

Hopefully the people working on the optimization can answer that.

John.

> 
> Thanks,
> Alex
> 
>    [0]: http://lists.llvm.org/pipermail/llvm-dev/2015-November/092384.html
> 
>> 
>> John.
>> 
>>> 
>>> If the vtable pointer reload is required, is there a way to indicate to Clang
>>> that such a reload will not be necessary, even though the compiler can't verify
>>> that (sort of like __restrict)? I tried adding [[gnu::pure]] to the function
>>> declarations and definitions, but the vtable pointer reload remained. Does Clang
>>> take [[gnu::pure]]/[[gnu::const]] into account for code generation/optimization?
>>> 
>>> Thanks for the help!
>>> 
>>> Alex
>>> 
>>>  [0]: http://lists.llvm.org/pipermail/llvm-dev/2018-February/121439.html
>>>  [1]: http://lists.llvm.org/pipermail/llvm-dev/2018-March/121486.html
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at lists.llvm.org
>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
> 




More information about the cfe-dev mailing list