[PATCH] D93376: [LangRef] Clarify the semantics of lifetime intrinsics

Johannes Doerfert via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Dec 18 07:33:40 PST 2020


jdoerfert added a comment.



In D93376#2462499 <https://reviews.llvm.org/D93376#2462499>, @RalfJung wrote:

>> Two allocas with disjoint lifetimes should be able to be overlapped.
>
> Ah, that makes it very tricky... to also support ptrtoint mobility, alloca really needs to "see ahead" and determine which stack slots have disjoint lifetimes and which do not. Then it can immediately "reserve" some memory that does not overlap with stack slots with non-disjoint lifetime.

IMHO, this is not the job of an "alloca". A late transformation could make this explicit, that is first perform lifetime analysis on stack slots and then coalesce reassign the allocas accordingly. Basically register allocation for stack slots. I would have assumed we have something like this but I'm generally too afraid to venture into the MIR layer to check.

In D93376#2462365 <https://reviews.llvm.org/D93376#2462365>, @RalfJung wrote:

>> Why wouldn't/shouldn't it mean exactly what it means for stack allocations?
>> "The memory region specified in the lifetime start is dead until a lifetime start makes that memory accessible, ..."
>
> lifetime.start also has a magic effect "backward in time": when you just do alloca, it allocates some memory. When you do alloca and later do lifetime.start on the resulting pointer, (stack) memory allocation is delayed until the lifetime.start. IOW, lifetime.start is a very unusual intrinsic. Adding it *later* in the code can make a pointer *earlier* in the code dangling.

This mixes semantic and implementation of an alloca. Let's not do that. If you look at it a different way it makes more sense: Memory regions mentioned in lifetime intrinsics are initially dead. That does not mean they are not existent or that stack allocations would be delayed; they are known to be dead in a certain code region. Adding a lifetime adds information. Adding it
*later* adds more information. Arguably, we could mark the alloca in a way to indicate there are lifetimes attached but that is not the point. The thing is, we can decide to coalesce allocas with non-overlapping lifetimes into the same slot. (Under some conditions,) you can also reassign totally different allocas to code regions. Take

  alloca x,y,z;
  
  lifetime.start(x)
  use(x)
  if (...) {
    lifetime.start(y)
    use(y)                // x and y are life
    lifetime.end(y)
  }
  use(x)
  if (...) {
    lifetime.start(z)
    use(z)                // x and z are life
    lifetime.end(z)
  }
  lifetime.end(x)
   
  lifetime.start(z)
  use(z)                // x and z are life
  lifetime.end(z)



> How do you propose to be able to predict if an alloca actually allocates memory, if it is legal do to something like "%p = alloca (...)", followed by calling "f(p)", followed by "lifetime.start(p)" inside "f"? Now whether the original alloca actually allocates memory depends on the source code of another function...?
>
> Possibly a better fix is to avoid this "magic backward in time" effect, and instead use a flag on alloca to reflect whether memory is immediately allocated, or not. (The details of the semantics of this could still be tricky though.)




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D93376/new/

https://reviews.llvm.org/D93376



More information about the llvm-commits mailing list