diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -17635,7 +17635,7 @@ Overview: """"""""" -The '``llvm.lifetime.start``' intrinsic specifies the start of a memory +The '``llvm.lifetime.start``' intrinsic specifies the start of a stack-allocated object's lifetime. Arguments: @@ -17643,15 +17643,37 @@ The first argument is a constant integer representing the size of the object, or -1 if it is variable sized. The second argument is a pointer -to the object. +to the object. It should be either :ref:`alloca ` or a bitcast +to :ref:`alloca `. Semantics: """""""""" -This intrinsic indicates that before this point in the code, the value -of the memory pointed to by ``ptr`` is dead. This means that it is known -to never be used and has an undefined value. A load from the pointer -that precedes this intrinsic can be replaced with ``'undef'``. +This intrinsic indicates the start of the lifetime of an alloca that +``ptr`` points to. + +If an alloca is used by any '``llvm.lifetime.start``', the alloca is initially +dead. +Dereferencing a pointer to a dead alloca is undefined behavior, but operations +that do not dereference the pointer such as +:ref:`getelementptr ` or +:ref:`ptrtoint ` return a valid value. +When '``llvm.lifetime.start``' to the alloca is executed, the alloca is marked +as alive, its value is filled with '``undef``', and all operations on it work as +expected. The alloca is dead again when either +:ref:`llvm.lifetime.end ` to the alloca is executed or the +function returns. + +'``llvm.lifetime.start``' to the same alloca cannot be executed twice. +It is an ill-formed program if there is a path between two +'``llvm.lifetime.start``' calls to the same alloca without visiting any +'``llvm.lifetime.end``' call to the alloca, and LLVM transformations may raise +assertion failure when such program is given. + +'``llvm.lifetime.start``' cannot relocate the alloca. In other words, +observation of the address of an alloca during different lifetimes should +yield the same value. + .. _int_lifeend: @@ -17668,7 +17690,7 @@ Overview: """"""""" -The '``llvm.lifetime.end``' intrinsic specifies the end of a memory +The '``llvm.lifetime.end``' intrinsic specifies the end of a stack-allocated object's lifetime. Arguments: @@ -17676,15 +17698,15 @@ The first argument is a constant integer representing the size of the object, or -1 if it is variable sized. The second argument is a pointer -to the object. +to the object. It should be either :ref:`alloca ` or a bitcast +to :ref:`alloca `. Semantics: """""""""" -This intrinsic indicates that after this point in the code, the value of -the memory pointed to by ``ptr`` is dead. This means that it is known to -never be used and has an undefined value. Any stores into the memory -object following this intrinsic may be removed as dead. +This intrinsic indicates that the alloca that ``ptr`` points to is dead. See +:ref:`lifetime.start to see the definition of a dead alloca. +Calling ``llvm.lifetime.end`` on a dead alloca is no-op. '``llvm.invariant.start``' Intrinsic ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5164,6 +5164,26 @@ &Call); break; } + case Intrinsic::lifetime_start: { + auto *Ptr = Call.getArgOperand(1); + if (auto *BC = dyn_cast(Ptr)) + Ptr = BC->getOperand(0); + Assert(isa(Ptr), + "lifetime.start's pointer operand should be either alloca or " + "bitcast to alloca.", + &Call); + break; + } + case Intrinsic::lifetime_end: { + auto *Ptr = Call.getArgOperand(1); + if (auto *BC = dyn_cast(Ptr)) + Ptr = BC->getOperand(0); + Assert(isa(Ptr), + "lifetime.end's pointer operand should be either alloca or " + "bitcast to alloca.", + &Call); + break; + } }; }