[llvm-dev] [RFC] LLVM Coroutines

Gor Nishanov via llvm-dev llvm-dev at lists.llvm.org
Thu Jun 9 17:31:38 PDT 2016


Hi Eli:

>> semantics of the fork intrinsic... thinking about it a bit more, I think
>> you're going to run into problems with trying to keep around a return block
>> through optimizations:

How about this? Make all control flow explicit (duh).

    declare i8 coro.suspend([...])

    returns:
      0 - resume
      1 - cleanup
      anything else - suspend

Now we can get rid of the coro.fork altogether.

    [...]
    %0 = call i8 @llvm.coro.suspend([...])
    switch i8 %0, label %suspend [ i32 0, label %resume,
                                   i32 1, label %cleanup]
  suspend:
    call void @llvm.coro.end()
    br %return.block

We no longer have to do any special handling of return block as coro.end takes
care of it.

  Lowering of coro.suspend X

  1. Split block at coro.suspend, new block becomes the resume label X
  2. RAUW coro.suspend with 0 in f.resume and 1 in f.destroy
  3. Replace coro.suspend with 'br %suspend'

  coro.end expands as before:

  in f => no-op
  in f.resume/f.destroy => ret void (+ fancy things in landing pads)

Gor

On Thu, Jun 9, 2016 at 4:50 PM, Eli Friedman <eli.friedman at gmail.com> wrote:
> On Thu, Jun 9, 2016 at 2:33 PM, Gor Nishanov <gornishanov at gmail.com> wrote:
>>
>> Lowering of coro.suspend number X:
>>
>> 1) split block at coro.suspend, new block becomes jump point for
>> resumption X
>> 2) RAUW coro.suspend with i1 true in resume clone i1 false in destroy
>> clone
>> 3) replace coro.suspend with br %return.block in 'f', 'ret void' in clones
>>
>> Scratch the proposed corosuspend instruction. I think the intrinsic will
>> work
>> just fine!
>
>
> That sounds right.
>
>
> If you're going down that route, that still leaves the question of the
> semantics of the fork intrinsic... thinking about it a bit more, I think
> you're going to run into problems with trying to keep around a return block
> through optimizations:
>
> [...]
> %first.return = call i1 @llvm.experimental.coro.fork()
> %cmp = icmp eq i32 %x, 0
> br i1 %cmp, label %block1, label %block2
>
> block1:
> [...]
> br i1 %first.return, label %coro.return, label %coro.start
>
> block2:
> [...]
> br i1 %first.return, label %coro.return, label %coro.start
>
> coro.return:
> %xxx = phi i32 [ %a, %block1 ], [ %b, %block2 ]
> call void @f(i32 %xxx)
> ret i8* %frame
>
> (Now you can't trivially insert branches to the return block because of the
> PHI node.)
>
> -Eli


More information about the llvm-dev mailing list