[LLVMdev] Missed devirtualization opportunities

John McCall rjmccall at apple.com
Thu Oct 14 10:04:48 PDT 2010


On Oct 14, 2010, at 5:08 AM, Kenneth Uildriks wrote:
> On Wed, Oct 13, 2010 at 11:16 PM, Nick Lewycky <nicholas at mxc.ca> wrote:
>> Kenneth Uildriks wrote:
>>> 
>>> On Wed, Oct 13, 2010 at 12:45 AM, Nick Lewycky<nicholas at mxc.ca>  wrote:
>>>> 
>>>> Kenneth Uildriks wrote:
>>>>>> 
>>>>>> You're right, I hadn't thought this through. The whole point of making
>>>>>> them
>>>>>> local is to say that "I'm sure these callees won't modify that memory"
>>>>>> regardless of what functions actually get called, even indirectly. We
>>>>>> can't
>>>>>> know that they won't modify the vptr in advance, so invariant doesn't
>>>>>> work
>>>>>> here. Making it non-local just means that we would need to know the
>>>>>> static
>>>>>> call graph, which we don't because we haven't devirtualized yet so all
>>>>>> the
>>>>>> calls are indirect.
>>>>>> Nick
>>>>> 
>>>>> So that means you're now saying that llvm.invariant.end ought to be
>>>>> left the way it is, right?
>>>> 
>>>> I have no idea how to make use of llvm.invariant to help
>>>> devirtualization.
>>>> If no use or other use case for them can be found, maybe they should be
>>>> removed.
>>> 
>>> Apply invariant to the vtpr as long as the corresponding instance
>>> pointer is in use within a function.  With an invariant vtpr (and
>>> better invariant support, and a front-end that uses it),
>>> devirtualization happens more or less automatically with
>>> -std-compile-opts.
>> 
>> That's not valid. Each function called through the pointer could change the
>> vptr. Yes, you can do this in a defined way in C++, for example, by calling
>> the destructor and then placement-new'ing an object of a derived type with
>> the same size in its place.
> 
> But unless you placement-new'd an object of the exact same type in its
> place, you're not allowed to use the original pointer to make any more
> virtual calls on it.  At least that's how I understand John's message
> from a few days ago.

Correct.  Basically, the standard lets us assume that — if we know the dynamic
type of an object at a certain point for some reason — that dynamic
type is fixed when accessed through that pointer.

Like the type-aliasing rules, this is probably one of those things that we need
to be a little careful about taking advantage of, because even conscientious
users are going to write their code around assumptions of what a
"reasonable compiler" is going to optimize.

John.



More information about the llvm-dev mailing list