diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1198,12 +1198,23 @@ function, returning a pointer to allocated storage disjoint from the storage for any other object accessible to the caller. +.. _nocapture: + ``nocapture`` - This indicates that the callee does not make any copies of the - pointer that outlive the callee itself in any form such as a pointer stored - in the memory or as a return value. This is not a valid - attribute for return values. Addresses used in volatile operations - are considered to be captured. + This indicates that the callee does not :ref:`capture ` the + pointer. This is not a valid attribute for return values. + This attribute applies only to the particular copy of the pointer passed in + this argument. A caller could pass two copies of the same pointer with one + being annotated nocapture and the other not, and the callee could validly + capture through the non annotated parameter. + +.. code-block:: llvm + + define void @f(i8* nocapture %a, i8* %b) { + ; (capture %b) + } + + call void @f(i8* @glb, i8* @glb) ; well-defined ``nofree`` This indicates that callee does not free the pointer argument. This is not @@ -2648,6 +2659,79 @@ which specialized optimization passes may use to implement type-based alias analysis. +.. _pointercapture: + +Pointer Capture +--------------- + +Given a function call and a pointer that is passed as an argument or stored in +the memory before the call, a pointer is *captured* by the call if it makes a +copy of any part of the pointer that outlives the call. +To be precise, a pointer is captured if one or more of the following conditions +hold: + +1. The call stores any bit of the pointer carrying information into a place, +and the stored bits can be read from the place by the caller after this call +exits. + +.. code-block:: llvm + + @glb = global i8* null + @glb2 = global i8* null + @glb3 = global i8* null + @glbi = global i32 0 + + define i8* @f(i8* %a, i8* %b, i8* %c, i8* %d, i8* %e) { + store i8* %a, i8** @glb ; %a is captured by this call + + store i8* %b, i8** @glb2 ; %b isn't captured because the stored value is overwritten by the store below + store i8* null, i8** @glb2 + + store i8* %c, i8** @glb3 + call void @g() ; If @g makes a copy of %c that outlives this call (@f), %c is captured + store i8* null, i8** @glb3 + + %i = ptrtoint i8* %d to i64 + %j = trunc i64 %i to i32 + store i32 %j, i32* @glbi ; %d is captured + + ret i8* %e ; %e is captured + } + +2. The call stores any bit of the pointer carrying information into a place, +and the stored bits can be safely read from the place by another thread via +synchronization. + +.. code-block:: llvm + + @lock = global i1 true + + define void @f(i8* %a) { + store i8* %a, i8** @glb + store atomic i1 false, i1* @lock release ; %a is captured because another +thread can safely read @glb + store i8* null, i8** @glb + ret void + } + +3. The call's behavior depends on any bit of the pointer carrying information. + +.. code-block:: llvm + + @glb = global i8 0 + define void @f(i8* %a) { + %c = icmp eq i8* %a, @glb + br i1 %c, BB_EXIT, BB_CONTINUE ; escapes %a + BB_EXIT: + call void exit() + unreachable + BB_CONTINUE: + ret void + } + +4. The pointer is used in a volatile access as its address. + + .. _volatile: Volatile Memory Accesses