This is an archive of the discontinued LLVM Phabricator instance.

Emit invariant.group.barrier when using union field
ClosedPublic

Authored by Prazek on Apr 7 2017, 2:48 PM.

Details

Summary

We need to emit barrier if the union field
is CXXRecordDecl because it might have vptrs. The testcode
was wrongly devirtualized. It also proves that having different
groups for different dynamic types is not sufficient.

Diff Detail

Repository
rL LLVM

Event Timeline

Prazek created this revision.Apr 7 2017, 2:48 PM
rjmccall added inline comments.Apr 17 2017, 8:37 AM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

Checking for v-table pointers recursively isn't really that difficult, but if you really don't want to do that, please at least check for non-POD-ness or something so that this isn't kicking in for literally every struct type.

Prazek added inline comments.Apr 17 2017, 10:25 AM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

ok, I am also planning to fix this in the later patch, because the same problem arise when comparing 2 pointers to dynamic classe.
I would like to have a bit in CXXRecordDecl to remember if it has any vptr inside that would calculate durring the construction.
My biggest fear is that if I won't cache it then it will be very slow.

rjmccall added inline comments.Apr 17 2017, 12:30 PM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

We could repeat this work from scratch on every single union field access done by IRGen and it would still be way, way faster than doing anything extra on every record definition in the program. The latter is done orders of magnitude more frequently than the former.

Prazek added inline comments.Apr 17 2017, 1:57 PM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

This is a good point, and actually I don't need to check if class holds any vptrs for the example I refered (comparing 2 pointers).
Hovewer I still need to do it when someone casts pointer to class holding vptrs to something that doesn't hold vptrs, and any pointer casts are much more frequent than Record declarations.

rjmccall added inline comments.Apr 17 2017, 10:55 PM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

What are you planning to do if someone casts to a pointer to incomplete type?

I am concerned that what these problems are really telling us is that this representation is not very good.

Prazek added inline comments.Apr 18 2017, 4:05 AM
lib/CodeGen/CGExpr.cpp
3517 ↗(On Diff #94569)

In this case we also need to add the barrier. I might be wrong, but I think this in general should be pretty rare and even more rare if it would limit the devirtualization.
For example cases like:

Derived *d;
(Base*)d;

will not limit devirtualization if Derived is complete type (because base will be also).

The other thing is that with my recent patches, adding more barriers will not limit any memory optimizations.

Prazek updated this revision to Diff 96254.Apr 21 2017, 3:42 PM
  • Checking for vptrs
Prazek marked 6 inline comments as done.Apr 21 2017, 3:43 PM

For now I will check if it has any vptrs. It will be probably soon stored in the CXXRecordDecl because it will be used much more frequently when generating barriers for pointer casts.

Prazek updated this revision to Diff 96255.Apr 21 2017, 3:44 PM
  • format
Prazek updated this revision to Diff 96312.Apr 23 2017, 9:43 AM
  • Inserting barrier with -O0
rjmccall added inline comments.May 26 2017, 7:43 AM
lib/CodeGen/CGExpr.cpp
3530 ↗(On Diff #96312)

You need to recurse into base classes (to check their fields), and if you write this to take a QualType you won't have to eagerly extract RD below.

3517 ↗(On Diff #94569)

You don't need the .getTypePtr() here.

Prazek updated this revision to Diff 100533.May 27 2017, 8:03 AM
  • changed to QualType, now it is much cleaner
Prazek marked 2 inline comments as done.May 27 2017, 8:04 AM
Prazek added inline comments.
lib/CodeGen/CGExpr.cpp
3530 ↗(On Diff #96312)

Cool, thanks for the tip

rjmccall accepted this revision.May 28 2017, 3:43 PM

Looks great, thanks. One request for additional tests, but feel free to commit when that's ready.

test/CodeGenCXX/strict-vtable-pointers.cpp
258 ↗(On Diff #100533)

Please include test cases involving classes that only have a virtual pointer in a field of a base class — e.g. something that inherits from HoldingVirtuals. And be sure to cover both normal and virtual inheritance.

This revision is now accepted and ready to land.May 28 2017, 3:43 PM
Prazek marked 3 inline comments as done.May 29 2017, 10:12 AM
rjmccall added inline comments.May 31 2017, 6:01 PM
test/CodeGenCXX/strict-vtable-pointers.cpp
263 ↗(On Diff #100621)

"virtual" applies to an individual base, not to all following bases. You need "virtual HoldingVirtuals" here.

Although, come to think of it, having a virtual base should already ensure that the class has a v-table, even if it has no other reason for one. (You should add a test for that!)

Prazek updated this revision to Diff 100977.Jun 1 2017, 1:35 AM
Prazek marked an inline comment as done.

Extra test

rjmccall accepted this revision.Jun 1 2017, 9:58 AM

Thanks, LGTM.

This revision was automatically updated to reflect the committed changes.