We can sometimes propagate nocapture attributes from caller
arguments to callsite arguments.
This can occur in in the following cases:
- The callsite is in a basic block that ends with a return statement.
- Between the callsite the end of its basic block there are no may-write instructions.
- The return value of the callsite is not used (directly or indirectly) as the address of a may-read instruction.
- There are allocas or leaked (not freed or returned) mallocs reachable from the callsite.
- The callsite/caller are nothrow OR there is no landing padd in the caller.
These requirements are intentionally over conservative. We are only trying
to catch relatively trivial cases.
Requirements 1 & 2 are there to ensure that after the callsite has
returned, the state of any captured in memory pointers cannot change. This
implies that if the caller has any nocapture in memory gurantees, that
state has been reached by the end of the callsite.
Requirements 3 & 4 are to cover cases where pointers could escape the
callsite (but not the caller) through non-dead code. Any return value thats
loaded from (or used to create a pointer that is loaded from) could have
derived from an argument. Finally, allocas/leaked mallocs in general are
difficult (so we avoid them entirely). Callsites can arbitrarily store
pointers in allocas for use later without violating a nocapture gurantee by
the caller, as the allocas are torn down at caller return. Likewise a
leaked malloc would not be accessible outside of the caller, but could
still be accessible after the callsite. There are a variety of complex
cases involving allocas/leaked mallocs. For simplicity, if we see either we
simply fail.
Requirement 5 is to cover the last way to escape to occur. If the
callsite/caller is nothrow its a non-issue. If the callsite may throw, then
a method of capture is through an exception. If the caller has no landing
padd to catch this exception, then the exception state will be visible
outside of the caller so any gurantees about nocapture made by the caller
will apply to the callsites throw. If the caller has a landing padd, its
possible for the callsite to capture a pointer in a throw that is later
cleared by the caller.