This is an archive of the discontinued LLVM Phabricator instance.

Lower invoke statepoints and gc.results tied to them.
ClosedPublic

Authored by igor-laevsky on Feb 19 2015, 7:34 AM.

Details

Summary

This change builds up on http://reviews.llvm.org/D7756

It teaches lowering to correctly handle invoke statepoint and gc results tied to them. Note that we still can not lower gc.results for invoke statepoints.
Also it extracts getCopyFromRegs helper function in SelectionDAGBuilder as we need to be able to customize type of the register exported from basic block during lowering of gc.result.

Diff Detail

Repository
rL LLVM

Event Timeline

igor-laevsky retitled this revision from to Lower invoke statepoints and gc.results tied to them. .
igor-laevsky updated this object.
igor-laevsky edited the test plan for this revision. (Show Details)
igor-laevsky added a reviewer: reames.
igor-laevsky set the repository for this revision to rL LLVM.
igor-laevsky added a subscriber: Unknown Object (MLST).
reames edited edge metadata.Feb 19 2015, 2:37 PM

Comments inline.

You need tests for this.

Also, your code appears to have handling for gc.result even though your description says that's not handled. Which is it?

lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
1048 ↗(On Diff #20296)

I'm a bit uncomfortable signing off on this part of the change since I'm unfamiliar with the details of the codepath. I'll ask that you wait for a signoff from someone more familiar with SelectionDAG as a whole.

lib/CodeGen/SelectionDAG/StatepointLowering.cpp
257 ↗(On Diff #20296)

I'm still confused about why we need this. Why doesn't the standard export mechanism work here? Simply producing the value and letting it be exported normally seems like it would work?

297 ↗(On Diff #20296)

Just to be clear, the reason for this is that CallEnd might start with the eh_label which doesn't have a glue node?

669 ↗(On Diff #20296)

Doesn't this depend on what SDValue we set for a specific instruction? As above, I'm not convinced this is necessary.

Also, CamelCase naming per llvm docs.

igor-laevsky edited edge metadata.

Also, your code appears to have handling for gc.result even though your description says that's not handled. Which is it?

Sorry I meant that we can not handle gc.relocates.

Comments inline.

lib/CodeGen/SelectionDAG/StatepointLowering.cpp
257 ↗(On Diff #20296)

Main problem here is that value we want to export is 'Tmp' which will be deleted few lines later. Therefore we need to export statepoint call itself, but it has different type than the actual call. Default mechanism for exporting values from BasicBlock calculates type of the register from Value* we are trying to export. So we need to create register with correct type manually.

This probably could be wrapped in a helper function or an overload of a 'ExportFromCurrentBlock(Value*)' but it's the only place such problem appears so probably not worth it.

I have added comment describing this.

297 ↗(On Diff #20296)

Yes. DAG root will be eh_label in case of invoke and it will not have glued nodes.

669 ↗(On Diff #20296)

SDValue is live only during processing of a single BasicBlock. We are exporting llvm-ir Value's. And in our case statepoint value has different type than the actual lowered call. This is same problem as in lowerCallFromStatepoint.

Summary of offline conversation.

lib/CodeGen/SelectionDAG/StatepointLowering.cpp
257 ↗(On Diff #20296)

Igor and I talked about this a bit offline. We realized that the heart of the issue here is that we need to export a value whose type does not match the type of the instruction it's associated with. This is a "feature" unique to gc.statepoint.

We think the same issue can be replicated with:

%token = call i32 gc.statepoint....
br label %next

next:

%res = call float gc.result(%token)

Igor is going to investigate and see what it would take to have the export mechanism just handle this case directly.

An alternate approach would be to remove gc.result entirely and just use the result value (if there is one) as the token for gc.result. We could introduce an artificial i32 return when the underlying function has a void return. This may be a better long term approach, but is more churn than we'd prefer right now.

After a bit of investigation and discussions offline it seems like extending current export mechanism to support statepoints is a bit unreasonable. We will need to add hooks in form of:

Type *t;
if (isStatepoint(I))
  t = <underlying call type>
else
  t = <normal type>

In three places:

  1. During InitializeRegForValue in FunctionLowering.
  2. Create correct CopyToReg in CopyValueToVirtualRegister in SelectionDAGBuilder
  3. Create correct CopyFromReg in getValue in SelectionDAGBuilder

This is more invasive compared to the current approach which is just trivial refactoring in SelectionDAGBuilder.
Also this isStatepoint hooks will seem inappropriate in general handling mechanism. Maybe someday when and if there will be more instructions with such problem we will be able to extract common property from them and use it in this checks.

Another approach would be to remove gc.results completely as Philip stated. However this is a bit more work not directly related to this change. I will add TODO concerning this.

reames added a comment.Mar 3 2015, 9:32 AM

You need to add a test.

Once mentioned changes are made, should be good for submission. I would prefer one more updated diff just for an official LGTM.

lib/CodeGen/SelectionDAG/StatepointLowering.cpp
258 ↗(On Diff #20410)

Given our discussion, this comment is wrong and misleading. It's not the fact that "Tmp" is deleted, it's the fact that the type will not match. Please update.

672 ↗(On Diff #20410)

CalleeType per llvm style. Same with others.

igor-laevsky added inline comments.
lib/CodeGen/SelectionDAG/StatepointLowering.cpp
258 ↗(On Diff #20410)

It depends on the view point. For 'Tmp' types actually match. So we can look at the problem either as standart mechanism not knowing about statepoints or as our inability to export correct Value*. Anyway it is probably unnecessary details, I updated the comment.

And the complete test will follow up in the next change - http://reviews.llvm.org/D7798

reames added a comment.Mar 3 2015, 3:12 PM

Igor, my comment about a test was not optional. You can and must test this. A couple of simple invoke tests without relocations should work after this change. Or am I misunderstanding something?

I didn't add code to actually call lowering for invoke statepoints in this change. I was posponing it until the next change (http://reviews.llvm.org/D7798). But anyway I have updated the diff and added a test.

LGTM once test case comments are addressed. You can submit once that's done without further review.

test/CodeGen/X86/statepoint-invoke.ll
1 ↗(On Diff #21228)

Add a target triple.

9 ↗(On Diff #21228)

My experience has been that using labels like this will be a bit fragile. You should consider using something easier to match on like a call to dummy function.

(Alternatively, you could use FileCheck variables.)

This revision was automatically updated to reflect the committed changes.
sanjoy added a subscriber: sanjoy.May 6 2015, 11:01 AM

Minor comments inline.

llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
1030

LLVM Coding style is to use CamelCase starting with a upper case letter -- please change res to Result or something like that.

llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
672

The spacing here looks weird -- can you please run this bit through clang-format?