[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