This is an archive of the discontinued LLVM Phabricator instance.

[FunctionAttrs] Account for memory effects of inalloca/preallocated
ClosedPublic

Authored by nikic on Oct 12 2022, 8:27 AM.

Details

Summary

The code for inferring memory attributes on arguments claims that inalloca/preallocated arguments are always clobbered: https://github.com/llvm/llvm-project/blob/d71ad4108056d685f48407447095d8d92fd7685d/llvm/lib/Transforms/IPO/FunctionAttrs.cpp#L640-L642

However, we would still infer memory attributes for the whole function without taking this into account, so we could still end up inferring readnone for the function. This adds an argument clobber if there are any inalloca/preallocated arguments.

Disclaimer: I'm completely trusting the existing comment here, I'm not familiar with inalloc/preallocated arguments and why they're special in this regard.

Diff Detail

Event Timeline

nikic created this revision.Oct 12 2022, 8:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 12 2022, 8:27 AM
nikic requested review of this revision.Oct 12 2022, 8:27 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 12 2022, 8:28 AM
rnk accepted this revision.Oct 12 2022, 10:20 AM
rnk added a subscriber: akhuang.

Inalloca (& preallcoated) effectively allows the caller to take the address of the argument stack memory used for the call. The call effectively deallocates the argument memory, since it can immediately be reused by the next call, so it should be modeled like free.

+@akhuang because we were just discussing documentation of this feature

This revision is now accepted and ready to land.Oct 12 2022, 10:20 AM

Inalloca (& preallcoated) effectively allows the caller to take the address of the argument stack memory used for the call. The call effectively deallocates the argument memory, since it can immediately be reused by the next call, so it should be modeled like free.

I see, thanks! It looks like this is also mentioned in https://llvm.org/docs/InAlloca.html#callee-cleanup-calling-conventions:

Another wrinkle is the existence of callee-cleanup conventions. On Windows, all methods and many other functions adjust the stack to clear the memory used to pass their arguments. In some sense, this means that the allocas are automatically cleared by the call. However, LLVM instead models this as a write of undef to all of the inalloca values passed to the call instead of a stack adjustment. Frontends should still restore the stack pointer to avoid a stack leak.

rnk added a comment.Oct 12 2022, 1:58 PM

Another wrinkle is the existence of callee-cleanup conventions. On Windows, all methods and many other functions adjust the stack to clear the memory used to pass their arguments. In some sense, this means that the allocas are automatically cleared by the call. However, LLVM instead models this as a write of undef to all of the inalloca values passed to the call instead of a stack adjustment. Frontends should still restore the stack pointer to avoid a stack leak.

I don't recall why I thought modelling it as a "write of undef" was better than saying it deallocated the memory. It's effectively the same result as a stackrestore, which can be used to deallocate dynamic allocas.

It also kind of doesn't matter whether the call is callee cleanup, because it is valid for a pass to place a side-effect free call immediately after the call that uses inalloca.