Ariel Ben-Yehuda via llvm-dev
2017-Mar-29 16:59 UTC
[llvm-dev] nocapture: affects aliasing or also numerical value?
Hi, I have a question about the meaning of the nocapture attribute: In Rust, safe code can use pointers as, say, HashMap keys (by reference equality) without regard to their lifetimes - of course, a dead pointer might be reference-equal to other pointers, but users should not face any other trouble with that (of course, dead pointers can't be dereferenced). Rust also has "anonymous &T" arguments, which are pointers that can't be dereferenced after the function returns. However, because pointers can be used as HashMap keys without regard to their lifetimes, their identity can be inserted into an HashMap. Now, we want to transfer this information to LLVM, which is quite similar to the `nocapture` attribute. However, according to the documentation for `nocapture`, "This indicates that the callee does not make any copies of the pointer that outlive the callee itself.". This might mean that the pointer becomes some sort of indeterminate value after the function returns - aka using it as a HashMap key would be trouble. Or it could just mean that the pointer can't be dereferenced after the function returns, which is the Rust semantics. Does `nocapture` have Rust-compatible semantics, and if not, is there some other way to emulate these semantics? Thanks, - Ariel
Daniel Berlin via llvm-dev
2017-Mar-29 17:12 UTC
[llvm-dev] nocapture: affects aliasing or also numerical value?
On Wed, Mar 29, 2017 at 9:59 AM, Ariel Ben-Yehuda via llvm-dev < llvm-dev at lists.llvm.org> wrote:> Hi, > > I have a question about the meaning of the nocapture attribute: > > In Rust, safe code can use pointers as, say, HashMap keys (by > reference equality) without regard to their lifetimes - of course, a > dead pointer might be reference-equal to other pointers, but users > should not face any other trouble with that (of course, dead pointers > can't be dereferenced). > > Rust also has "anonymous &T" arguments, which are pointers that can't > be dereferenced after the function returns.Do you mean "dereferenced in the called function"? or dereferenced in the callee?> However, because pointers > can be used as HashMap keys without regard to their lifetimes, their > identity can be inserted into an HashMap. > > Now, we want to transfer this information to LLVM, which is quite > similar to the `nocapture` attribute. > > However, according to the documentation for `nocapture`, "This > indicates that the callee does not make any copies of the pointer that > outlive the callee itself.". >> > This might mean that the pointer becomes some sort of indeterminate > value after the function returns - aka using it as a HashMap key would > be trouble.No, because that would not be a copy becoming indeterminate, since this is SSA. Remember this is SSA, so the original value passed to the function can only have been assigned once.> Or it could just mean that the pointer can't be > dereferenced after the function returns, which is the Rust semantics. >No, it doesn't mean that either. The semantics are precisely: "the *called* function does not store this pointer in a place that, after function return, it may be accessed by the called function or any other function that the called function used" To be concrete, if this is the entire function: declare func(nocapture i8*); define bar() { a_1 = pointer to foo call func(a_1) *a_1 = 5 } is legal. Additionally define bar() { a_1 = pointer to foo call func(a_1) call func2() } func2 cannot access a_1 Note: define bar() { a_1 = pointer to foo call func(a_1) a_1 = different thing } is impossible, because a_1 is an ssa value it would be: define bar() { a_1 = pointer to foo call func(a_1) a_2 = different thing } and a_2 is a different pointer than a_1. Note, if our first example was: declare func(nocapture i8*); define bar(i8* a_1 ) { call func(a_1) } bar would also be nocapture of a_1, and could be marked as such.> > Does `nocapture` have Rust-compatible semantics, and if not, is there > some other way to emulate these semantics? >If your semantic is that, after the call to func, a_1 is actually *dead*, the way to emulate that semantic would be to use llvm.lifetime.end on it.> Thanks, > - Ariel > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170329/47f027ed/attachment.html>