This is an archive of the discontinued LLVM Phabricator instance.

[coro async] Add code to support dynamic aligment of over-aligned types in async frames
ClosedPublic

Authored by aschwaighofer on May 31 2022, 12:02 PM.

Details

Summary

Async context frames are allocated with a maximum alignment. If a type
requests an alignment bigger than that dynamically align the address
in the frame.

Diff Detail

Event Timeline

aschwaighofer created this revision.May 31 2022, 12:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 31 2022, 12:02 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
aschwaighofer requested review of this revision.May 31 2022, 12:02 PM
Herald added a project: Restricted Project. · View Herald TranscriptMay 31 2022, 12:02 PM
rjmccall added inline comments.May 31 2022, 1:02 PM
llvm/lib/Transforms/Coroutines/CoroFrame.cpp
1588

Surely just doing AI->getAlignment() - 1 is simpler.

Can we trust AI->getAlignment() to be the same value as the alignment we used when computing the frame layout?

aschwaighofer added inline comments.May 31 2022, 3:02 PM
llvm/lib/Transforms/Coroutines/CoroFrame.cpp
1588

Surely just doing AI->getAlignment() - 1 is simpler.

LLVM's constant folder saved my bacon there, but yes. I will fix.

Can we trust AI->getAlignment() to be the same value as the alignment we used when computing the frame layout?

Yes. For Allocas we pass AI->getAlign() to addField as the FieldAlignment which is then used to compute the layout. FieldAlignment is only set in the addField function if it has not been set (it is a MaybeAlign optional).

Fields.push_back({FieldSize, Offset, Ty, 0, *FieldAlignment, TyAlignment,   
                  DynamicAlignBuffer});

This is rather memory-inefficient, and it's quite a shame that the ABI was defined such as not to pass-down a "context_alignment" field next to "context_size" in the async_function_pointer struct, so that the allocator can DTRT. Oh well...

Address comment.

This is rather memory-inefficient, and it's quite a shame that the ABI was defined such as not to pass-down a "context_alignment" field next to "context_size" in the async_function_pointer struct, so that the allocator can DTRT. Oh well...

Increasing the size of async function pointers and complicating the allocation logic are not free. The max alignment used by the ABI is 16 bytes, and the Swift frontend does not normally request alignments larger than that, and I wouldn't expect the places that *do* request it to typically need to persist values across an async suspension (vectorization, for example, generally loses a lot of its punch if you've got calls in the middle of your vectorized kernel), so we're talking about pretty rarified circumstances here; I think the trade-off made by the ABI is appropriate.

I would guess that whatever code pattern triggered this bug does not in fact need the value to persist a value across the suspension, and someone we're just failing to put it on the stack.

Add asserts that the dynamic alignment frame information when constructing the
frame matches the alloca.

rjmccall added inline comments.Jun 2 2022, 11:01 AM
llvm/lib/Transforms/Coroutines/CoroFrame.cpp
1797

These three sites all need to be A.NeedsDynamicAlignment in case the original alloca is over-aligned, right? Should we just make GetFramePointer take a const Field & so that this falls out?

aschwaighofer added inline comments.Jun 2 2022, 12:46 PM
llvm/lib/Transforms/Coroutines/CoroFrame.cpp
1797

I relied on the fact that for async ABI we won't get here. (line 1751)

I will rewrite it as you said so that this is not a ticking time bomb (though the asserts I added would catch that)

Simplify logic whether a frame access needs dynamic alignment.

rjmccall accepted this revision.Jun 2 2022, 2:01 PM

LGTM

llvm/lib/Transforms/Coroutines/CoroFrame.cpp
1797

Ah, okay.

This revision is now accepted and ready to land.Jun 2 2022, 2:01 PM
This revision was landed with ongoing or failed builds.Jun 3 2022, 7:07 AM
This revision was automatically updated to reflect the committed changes.