This is an archive of the discontinued LLVM Phabricator instance.

[CoroSplit] Handle argument being the frame pointer
ClosedPublic

Authored by nikic on Mar 24 2022, 2:35 AM.

Details

Summary

If the frame pointer is an argument of the original pointer (which happens with opaque pointers), then we currently first replace the argument with undef, which will prevent later replacement of the old frame pointer with the new one.

Fix this by replacing arguments with some dummy instructions first, and then replacing those with undef later. This gives us a chance to replace the frame pointer before it becomes undef.

This is a big ugly, but I couldn't think of a better solution.

Fixes https://github.com/llvm/llvm-project/issues/54523.

Diff Detail

Event Timeline

nikic created this revision.Mar 24 2022, 2:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 2:35 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
nikic requested review of this revision.Mar 24 2022, 2:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptMar 24 2022, 2:35 AM

I am not familiar with retcon coroutines and opaque pointers. But I am surprised for the sentence If the frame pointer is an argument of the original pointer (which happens with opaque pointers). May I ask where we would make it possible to make the FramePtr to be the argument of the original function with opaque pointers?

nikic added a comment.Mar 24 2022, 2:48 AM

I am not familiar with retcon coroutines and opaque pointers. But I am surprised for the sentence If the frame pointer is an argument of the original pointer (which happens with opaque pointers). May I ask where we would make it possible to make the FramePtr to be the argument of the original function with opaque pointers?

Without opaque pointers, the frame pointer is a bitcast of the argument. With opaque pointers, the bitcast is not present, and it's directly the argument. So without opaque pointers, the old frame pointer first becomes bitcast undef and then gets replaced with the new frame pointer later. With opaque pointers it becomes undef, which cannot be correctly replaced. This patch tries to artificially add a dummy bitcast to make the replacement work correctly.

ChuanqiXu added a subscriber: rjmccall.

I am not familiar with retcon coroutines and opaque pointers. But I am surprised for the sentence If the frame pointer is an argument of the original pointer (which happens with opaque pointers). May I ask where we would make it possible to make the FramePtr to be the argument of the original function with opaque pointers?

Without opaque pointers, the frame pointer is a bitcast of the argument. With opaque pointers, the bitcast is not present, and it's directly the argument. So without opaque pointers, the old frame pointer first becomes bitcast undef and then gets replaced with the new frame pointer later. With opaque pointers it becomes undef, which cannot be correctly replaced. This patch tries to artificially add a dummy bitcast to make the replacement work correctly.

Oh I guess I understand the problem. The design of retcon ABI allows the user to specify the address of the coroutine frame. So it is possible that the frame is the argument of the original function indeed. Then I found true problem here is that the comment in https://github.com/llvm/llvm-project/blob/be5c3ca7fbaec90fff004af54d3cd5f6c30a9664/llvm/lib/Transforms/Coroutines/CoroSplit.cpp#L874-L876 is invalided. The arguments here shouldn't contain users.

So I believe the problem might be in splitRetconCoroutine. It replaces CoroBegin before cloning. (We treat the value returned by CoroBegin as the frame generally). But it replaces CoroBegin with the argument this time so that the argument still owns the user. So here is the problem. My solution is to replace CoroBegin later after the cloning. I sent https://reviews.llvm.org/D122383. And I add @rjmccall . He is the author of the retcon lowering. Maybe he could give further helps.

ChuanqiXu accepted this revision.Mar 30 2022, 7:07 PM

Given the discussions in D122383, let's pursue this one.

This revision is now accepted and ready to land.Mar 30 2022, 7:07 PM
rjmccall added inline comments.Mar 30 2022, 9:48 PM
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
874–884

Please explain why we need to do this in the comment, so that future maintainers aren't forced to track the commit all the way back to this conversation to understand it. And then the comment on the replacement later can just be something like "all uses of the arguments should have been resolved by this point, so we can safely remove the dummy values".

878

Is it really okay to add an unparented instruction to the value map?

nikic updated this revision to Diff 419353.Mar 31 2022, 12:58 AM

Update comments

nikic added inline comments.Mar 31 2022, 12:59 AM
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
878

At least I'm not aware of any issues that would cause. Parenting it would be a bit awkward here, as the function is completely empty at this point (doesn't have any basic blocks to insert into).

rjmccall accepted this revision.Mar 31 2022, 11:04 AM

LGTM

llvm/lib/Transforms/Coroutines/CoroSplit.cpp
878

Ah, yes, somehow I missed that this was in clone-specific code. Alright, if it's not causing problems, I guess we can do this.

This revision was landed with ongoing or failed builds.Apr 1 2022, 3:38 AM
This revision was automatically updated to reflect the committed changes.