[llvm-dev] [cfe-dev] RFC: Emitting empty invariant group for vtable loads

Richard Smith via llvm-dev llvm-dev at lists.llvm.org
Wed Jan 25 18:28:46 PST 2017


On 25 January 2017 at 15:03, Hal Finkel via cfe-dev <cfe-dev at lists.llvm.org>
wrote:

> Hi Piotr,
>
> I think makes sense. Modulo bitcasts, the invariant is identified by a
> particular pointer SSA value. Given that you can't sensibly have two
> nonequivalent invariants associated with the same pointer SSA value
> simultaneously, there's no need to also identify the invariant with a
> metadata string as well. When we need a new "identifier" for the pointed-to
> value, we get one using invariant.group.barrier.
>

As I recall, the original motivation for the identifier was to support
cases where the "invariant" region's value changes and then changes back
(remember that invariant.group does not imply the storage doesn't change,
just that a particular set of loads and stores witness the same value):

struct A { void *vptr; /*...*/ };
struct B { void *vptr; /*...*/ };
union U { A a; B b; };

void f(U *u) {
  // #1, load A vptr
  load u->a.vptr, !invariant "A::vptr"
  // #2, change union member to B ...
  store u->b.vptr, !invariant "B::vptr"
  // #3, change union member back to A ...
  f(u); // performs: store u->a.vptr, !invariant "A::vptr"
  // #4, load A vptr again, can be forwarded from #1 but not from #2
  load u->a.vptr, !invariant "A::vptr"
}

However, I don't immediately see a way in which the C++ object model would
require us to track multiple distinct groups of loads and stores, so if it
isn't useful to be able to do that outside of C++ vptr / const member
invariant tracking, I think we can remove it.

>  -Hal
>
> On 01/24/2017 01:39 PM, Piotr Padlewski via llvm-dev wrote:
>
> Hi,
> I would really like to hear some feedback about this.
>
> Piotr
>
> 2017-01-20 17:07 GMT+01:00 Piotr Padlewski <piotr.padlewski at gmail.com>:
>
>> Hi all,
>>
>> I would like to propose a new way clang would decorate vtable loads in
>> order to handle devirtualization better.
>>
>> I've added *llvm-dev* also, because this can start a discussion about
>> changing invariant.group to just invariant.
>>
>> PDF version of this RFC can be found here:
>>
>> https://drive.google.com/file/d/0B72TmzNsY6Z8ZmpOUnB5dDZfSFU
>> /view?usp=sharing
>>
>> Background:
>>
>> Initial old design:
>>
>> http://lists.llvm.org/pipermail/cfe-dev/2015-July/044227.html
>>
>> My talk from LLVM Dev Meeting
>>
>> http://llvm.org/devmtg/2016-11/#talk6
>> The problem
>>
>> Clang with -fstrict-vtable-pointers decorates vtable loads with metadata
>> corresponding to mangled pointer type name like:
>>
>> void g(A& a){    a.foo(); }
>>
>> define void @_Z1gR1A(%struct.A* dereferenceable(8) %a)
>> local_unnamed_addr #0 { entry:  %0 = bitcast %struct.A* %a to void (%
>> struct.A*)***  %vtable = load void (%struct.A*)**, void (%struct.A*)*** %
>> 0, !invariant.group !7  %1 = load void (%struct.A*)*, void (%struct.A*)**
>> %vtable  tail call void %1(%struct.A* nonnull %a)  ret void } !7 = !{!
>> "_ZTS1A"}
>>
>> This works well if the pointer type doesn’t change, but when it does,
>> devirtualization might not happen like here:
>>
>> struct A {    A();    virtual void foo(); }; struct B : A{    B();
>> virtual void foo(); }; void g(A& a){    a.foo();    a.foo(); } void
>> clobber(A&); void f() {      B b;      clobber(b);      g(b); }
>>
>> The other problem is that when we combine 2 instructions with different
>> invariant.group metadata, then we pick one of them, because for now we can
>> have only single !invariant.group metadata.
>> The solution
>>
>> I had some initial ideas how it can be solved, like
>>
>>    1.
>>
>>    introducing multi invariant groups
>>    2.
>>
>>    having sub invariant groups - like inheritance, so we could figure
>>    out that one group is subgroup of another
>>    3.
>>
>>    decorating all loads with base pointer MD (doesn’t work with multiple
>>    inheritance)
>>
>> I consulted my ideas with Krzysztof Pszeniczny, and he proposed something
>> much simpler: we can decorate every invariant.group md with empty metadata.
>>
>> This should work because the lifetime of the object is strictly defined
>> by invariant.group.barrier.
>>
>> If this holds, we can start discussion about if it makes sense to keep
>> invariant groups, and instead have just “invariant”, that would be
>> equivalent to having invariant.group with the same metadata.
>>
>> Do you have some thoughts about this approach? I don’t have a
>> mathematical proof, but I am confident that it should be valid.
>>
> _______________________________________________
> LLVM Developers mailing listllvm-dev at lists.llvm.orghttp://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
> --
> Hal Finkel
> Lead, Compiler Technology and Programming Languages
> Leadership Computing Facility
> Argonne National Laboratory
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170125/de4f87a0/attachment.html>


More information about the llvm-dev mailing list