[llvm-dev] [RFC] LLVM Coroutines
Gor Nishanov via llvm-dev
llvm-dev at lists.llvm.org
Sat Jun 11 17:43:45 PDT 2016
(Dropped llvm-dev by accident. Putting it back)
HI Eli:
>> coro.barrier() doesn't work: if the address of the alloca doesn't escape,
>> alias analysis will assume the barrier can't read or write the value of
>> the alloca, so the barrier doesn't actually block code movement.
Got it. I am new to this and learning a lot over the course
of this thread. Thank you for being patient with me.
Two questions and one clarification:
Q1: Do we have to have a load here?
===================================
>> block1:
>> %first_time = load... <--- What are we loading here?
>> br i1 %first_time, label return, label suspend1
>>
>> supend1:
>> %0 = coro.suspend()
>> switch %0 (resume1, destroy1)
Can we use three way coro.suspend instead?
Block1:
%0 = call i8 coro.suspend()
switch i8 %0, label suspend1 [i8 0 %return] ; or icmp + br i1
Suspend1:
switch i8 %0, label %resume1 [i8 1 %destroy1] ; or icmp + br i1
One problem I can see is that someone can write a pass that might merge
two branches / switches into one switch and we are back where we were.
I guess what you meant by load, is to call some coro.is.first.time() intrinsic.
So it looks like:
>> block1:
>> %first_time = call i1 coro.is.first.time()
>> br i1 %first_time, label return, label suspend1
>>
>> supend1:
>> %0 = coro.suspend()
>> switch %0 (resume1, destroy1)
This looks fine, there may be more uses for this intrinsic in the frontend.
Killing two birds with one stone. Good.
Question 2: Why the switch in the return block?
===============================================
I would think that **pre-split** return block would be simply:
return:
<run dtors for parameters, if required>
<conversion ops for ret value, if required>
<ret void> or <ret whatever>
Where and why I should put a switch that you mentioned in this return block?
BTW, I am speaking of the return block as if it is one block,
but, it could be a dominating block over all the blocks that together
run the destructors, do return value conversion, etc.
Clarification:
==============
>> Also, if some non-C++ language wants to generate coroutines,
>> it might not have to generate the return block at all.
C++ coroutines are flexible. The semantic of a coroutine is defined via
traits, so you may define a coroutine that returns void. It does not have
to return coroutine handle or some struct that wraps the coroutine handle.
For example, a developer may have a queue of suspended coroutines that is
processed by a scheduler, so a coroutine can queue its handle on suspension
either into a global queue or thread_local queue. If there are no destructors
to run for parameters, the return block would be simply:
return:
ret void
Cheers,
Gor
More information about the llvm-dev
mailing list