Page MenuHomePhabricator

[coroutines] Always place escaped allocas into the coroutine frame
Needs ReviewPublic

Authored by GorNishanov on Aug 24 2017, 8:56 AM.

Details

Summary

An alloca that escaped, might be accessed after resume via code external to the coroutine.
Therefore even if we do not see a use of an alloca after resume in the coroutine body,
we still need to place it into the coroutine frame.

In the follwoing example, %sneaky needs to go into the coroutine frame.

  %sneaky = alloca i32
...
  %hideit = ptrtoint i32* %sneaky to i64
  call void @escape(i64 %hideit)
...
  %tok = call i8 @llvm.coro.suspend(token none, i1 false)

  ... not used after suspend ...

Diff Detail

Event Timeline

GorNishanov created this revision.Aug 24 2017, 8:56 AM
lewissbaker added inline comments.Nov 1 2017, 4:32 AM
lib/Transforms/Coroutines/CoroFrame.cpp
889

Does this mean that passing the address of any allocad memory to a function call will cause it to be spilled even if its lifetime does not extend past a suspension point?

I'm thinking of cases where we have:

{
  co_await something;
  {
    int x = 123;
    escapes(&x);
  }
  co_await somethingElse;
}

Am I correct in understanding that with the proposed logic that x would be spilled to the frame even thought its lifetime does not cross a suspension-point? Can we avoid that?

Should we be checking for llvm.lifetime.start / llvm.lifetime.end intrinsics and if found only considering the result of allocaEscapes(&I) if the lifetime start/end span contains a suspension point?

lewissbaker added inline comments.Nov 1 2017, 4:38 AM
lib/Transforms/Coroutines/CoroFrame.cpp
889

You're calling allocaEscapes(&I) for each User in I.users() here but the call doesn't seem to depend on the user.

Can the call to allocaEscapes(&I) be moved out of the loop and just called once?