This is an archive of the discontinued LLVM Phabricator instance.

WholeProgramDevirt: Add any unsuccessful llvm.type.checked.load devirtualizations to the list of llvm.type.test users.
ClosedPublic

Authored by pcc on Feb 9 2017, 7:28 PM.

Details

Summary

Any unsuccessful llvm.type.checked.load devirtualizations will be translated
into uses of llvm.type.test, so we need to add the resulting llvm.type.test
intrinsics to the function summaries so that the LowerTypeTests pass will
export them.

Depends on D29782

Event Timeline

pcc created this revision.Feb 9 2017, 7:28 PM
pcc updated this revision to Diff 87949.Feb 9 2017, 7:36 PM
  • Rename the yaml input file to export.yaml so that I can use it in an upcoming change

Why llvm.type.checked.load is not documented in LangRef?

mehdi_amini added inline comments.Feb 12 2017, 2:01 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1090

Might be worth adding a one line comment to describe this block

1142

I'm still not sure what/why this is done. What happens in which phase?
What is the LowerTypeTests pass exporting exactly, and for which consumer?

pcc added inline comments.Feb 13 2017, 12:57 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

Essentially this is applying the same transformation to the summary as we would make to the function itself with regular LTO.

In the exporting phase we need to figure out how each llvm.type.checked.load intrinsic will be lowered. There are two cases:

  1. (not devirtualized) emit a regular virtual call and an llvm.type.test
  2. (devirtualized) emit a devirtualized call without an llvm.type.test

This change is necessary to correctly handle case 1. By adding the type ID to the list of type tests, we cause the exporting LowerTypeTests pass to export the summary information for that type ID (i.e. it will fill in the TypeTestResolution field in TypeIdSummary). That information will be consumed by the importing LowerTypeTests pass in the thin backend, after the importing WholeProgramDevirt pass has transformed the llvm.type.checked.load into an llvm.type.test (based on the WholeProgramDevirtResolution's Indir resolution for the type ID).

In case 2 the TypeCheckedLoadUsers vector will be cleared (see D29811) so this code will end up not adding the type test to the summary.

mehdi_amini added inline comments.Feb 13 2017, 1:44 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

I think I may just get it now, but still not totally sure: the llvm.type.test in case 1 is useful for CFI only right?

pcc added inline comments.Feb 13 2017, 1:46 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

Correct.

mehdi_amini added inline comments.Feb 13 2017, 2:10 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

OK, so I'd really like that anything that is done for CFI is clearly identified/documented as such (when in a context that deals with devirt), otherwise it makes it hard to understand what's going on without having both in mind.
It is absolutely non-intuitive to me when reviewing (or for a reader of) WholeProgramDevirt.cpp that these specific actions are performed only for CFI purpose (technically we should be able to *not* do these when CFI isn't enabled by the way).

pcc added inline comments.Feb 13 2017, 2:25 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

I would have thought that the references to "llvm.type.checked.load" would have made this clear enough (per the langref link mentioned earlier, the intrinsic is specific to CFI). But okay, I'll try to put something here with a summary of how llvm.type.checked.load intrinsics are handled by this pass.

mehdi_amini added inline comments.Feb 13 2017, 2:45 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1142

You don't need to put a lot of description, I was imagining just having "CFI-only" appearing somewhere, like:

// If we are exporting and any (CFI-specific) llvm.type.checked.load intrinsics
//...

Or

// For CFI purpose, if we are exporting and any llvm.type.checked.load intrinsics
//...

It seems obvious to me *now* that the "checked" in the name of the intrinsic refers to CFI, but at first glance I was trying to related this to devirtualization, and especially to some kind of guarded speculative devirtualization (which didn't make sense here, but was enough to get me confused).

pcc updated this revision to Diff 88279.Feb 13 2017, 5:03 PM

Depends on D29744

  • Refresh, address review comments
pcc marked an inline comment as done.Feb 13 2017, 5:03 PM
pcc marked an inline comment as done.Feb 24 2017, 11:11 AM

Ping.

tejohnson added inline comments.Mar 2 2017, 11:51 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1068–1072

I guess the early return here was for the case when there could not be any devirtualization - suggest adding a comment that in the Export case we still need to go through and handle the non-devirtualized llvm.type.checked.load intrinsics.

1127–1130

Is it worth skipping this check in the case where we previously had an early return above, but now will come through here in the Export case?

1141

How do we know which were not devirtualized? We fall through to here even after the above code which does devirtualizaton.

pcc updated this revision to Diff 90549.Mar 3 2017, 4:15 PM
pcc marked an inline comment as done.
  • Address review comments
pcc added inline comments.Mar 3 2017, 4:16 PM
llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
1127–1130

If we would have early returned before, we will need to run this check in order to try to export any type IDs. There is no code to handle exporting right now, but it will be added separately later (see D29811).

1141

The idea is that if devirtualization was successful we will clear the TypeCheckedLoadUsers vector. I have added a comment explaining this.

tejohnson accepted this revision.Mar 3 2017, 4:47 PM

LGTM
Thanks for adding all the comments, that is helpful!

This revision is now accepted and ready to land.Mar 3 2017, 4:47 PM
This revision was automatically updated to reflect the committed changes.
grimar added a subscriber: grimar.Mar 10 2017, 2:50 AM
grimar added inline comments.
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
1114 ↗(On Diff #90556)

Had to add brackets to compile this under MSVS2015, please see r297451.
I am not sure I did correct thing commiting the change though, http://llvm.org/docs/GettingStartedVS.html says:
"You will need Visual Studio 2015 or higher, with the latest Update installed.", and I don't thing I have any updates installed.
That is the only place in whole LLVM which does not compile for me now though.

pcc added inline comments.Mar 10 2017, 12:05 PM
llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
1114 ↗(On Diff #90556)

Looks good, thanks for the fix.