This is an archive of the discontinued LLVM Phabricator instance.

WholeProgramDevirt: print remarks with devirtualized method names.
ClosedPublic

Authored by krasin on Aug 5 2016, 12:23 PM.

Details

Summary

Chrome on Linux uses WholeProgramDevirt for speed ups, and it's
important to detect regressions on both sides: the toolchain,
if fewer methods get devirtualized after an update, and Chrome,
if an innocently looking change caused many hot methods become
virtual again.

The need to track devirtualized methods is not Chrome-specific,
but it's probably the only user of the pass at this time.

Diff Detail

Event Timeline

krasin updated this revision to Diff 66991.Aug 5 2016, 12:23 PM
krasin retitled this revision from to WholeProgramDevirt: print remarks with devirtualized method names..
krasin updated this object.
krasin added a reviewer: kcc.
kcc accepted this revision.Aug 5 2016, 12:43 PM
kcc edited edge metadata.

LGTM with a nit

lib/Transforms/IPO/WholeProgramDevirt.cpp
614

maybe "const std::vector &" ?

This revision is now accepted and ready to land.Aug 5 2016, 12:43 PM
krasin updated this revision to Diff 66997.Aug 5 2016, 12:52 PM
krasin edited edge metadata.

Add const.

krasin marked an inline comment as done.Aug 5 2016, 12:52 PM
krasin closed this revision.Aug 5 2016, 12:52 PM
This revision was automatically updated to reflect the committed changes.
mehdi_amini added inline comments.
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
615 ↗(On Diff #66998)

For the fully devirtualized case, we do it only if F is not overridden, i.e. if every Target has the same Target.Fn. It means your loop will print "devirtualized " + Name many times without good purpose.

620 ↗(On Diff #66998)

Avoid std::string, please use Twine instead.

835 ↗(On Diff #66998)

This is incorrect: you'll report "devirtualized" where it may not.

krasin added a comment.Aug 5 2016, 2:11 PM

Mehdi,

thank you for your comments. Would it be okay to send similar CLs for your review, while Peter is on vacation?

llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
615 ↗(On Diff #66998)

I observed that, and it does not really hurt (unlike the issue below). At the same time, it would be nice to print them only once. Any suggestions about the best way to do it?

620 ↗(On Diff #66998)

Thanks, will do in a follow up CL (soon; today).

835 ↗(On Diff #66998)

Can you please give an example? I currently don't see why would that be the case, but I have an indirect confirmation that I indeed print more than actually devirtualized.

thank you for your comments. Would it be okay to send similar CLs for your review, while Peter is on vacation?

Sure.

llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
615 ↗(On Diff #66998)

Yes: remove the loop and peak only the first elt :)
The name of the function emitTargetsRemarks is also a bit generic for what it does.

835 ↗(On Diff #66998)

This is first because tryVirtualConstProp does not perform straight devirtualization like trySingleImplDevirt, so you'll report a "devirtualized" function while only one of the call (or none, the return value is lying here...) may be actually devirtualized.

You may be able to emit more accurate information by moving this into the loop that is commented // Rewrite each call to a load from OffsetByte/OffsetBit. line 594.

krasin added inline comments.Aug 5 2016, 3:03 PM
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
615 ↗(On Diff #66998)

Hm... I actually added some debug prints and compiled my little program that I use to play with these remarks (http://pastebin.com/yww92KZm):

remark: devirt.cc:62:23: devirtualized call
remark: devirt.cc:34:0: i=0 devirtualized A::isOfType(ObjectType) const
remark: devirt.cc:46:0: i=1 devirtualized D::isOfType(ObjectType) const
remark: devirt.cc:58:23: devirtualized call
remark: devirt.cc:34:0: i=0 devirtualized A::isOfType(ObjectType) const
remark: devirt.cc:40:0: i=1 devirtualized B::isOfType(ObjectType) const
remark: devirt.cc:51:0: i=2 devirtualized C::isOfType(ObjectType) const
remark: devirt.cc:46:0: i=3 devirtualized D::isOfType(ObjectType) const

While there're some dups, but they are from different emitTargetsRemarks invocations (as the program has two call sites), so I will need to keep a set of already reported methods to avoid them.

This is also the case where virtual const propagation takes place.

For the reference, the command line I used:

clang++ -fuse-ld=lld -o lala devirt.cc -std=c++11 -flto -fvisibility=hidden -fwhole-program-vtables  -Wl,-mllvm,-pass-remarks=wholeprogramdevirt -Wl,--lto-O1  -Wl,-save-temps -g -O2 -fsanitize-stats -fsanitize=cfi-vcall 2>&1 | c++filt
835 ↗(On Diff #66998)

Thank you for the hints. Let's focus on the other issue (dups) first, and then I will update this comment.

krasin added inline comments.Aug 5 2016, 3:26 PM
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
615 ↗(On Diff #66998)

After adding a virtual method with a single implementation, I've got the suggested behavior:

remark: devirt.cc:60:8: devirtualized call
remark: devirt.cc:20:0: i=0 devirtualized Base::singlePrint()
remark: devirt.cc:20:0: i=1 devirtualized Base::singlePrint()
remark: devirt.cc:20:0: i=2 devirtualized Base::singlePrint()
remark: devirt.cc:20:0: i=3 devirtualized Base::singlePrint()

We should definitely suppress such duplicates, as it's possible to do without creating a set.

krasin added inline comments.Aug 5 2016, 3:33 PM
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
835 ↗(On Diff #66998)

Okay, I see the problem. Thanks a ton for spotting it!

krasin added inline comments.Aug 9 2016, 12:13 AM
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
620 ↗(On Diff #66998)

For the record: the follow up CL is https://reviews.llvm.org/D23297