[llvm-dev] nocapture: affects aliasing or also numerical value?

Daniel Berlin via llvm-dev llvm-dev at lists.llvm.org
Wed Mar 29 10:12:25 PDT 2017


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>


More information about the llvm-dev mailing list