<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jun 10, 2016 at 10:32 PM, Gor Nishanov <span dir="ltr"><<a href="mailto:gornishanov@gmail.com" target="_blank">gornishanov@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Okay. New intrinsics:<br>
<br>
declare void coro.barrier(i64); // will get a unique number for every insertion<br>
<span class=""><br>
>>   x = alloca...<br>
>><br>
>> block1:<br>
>>   suspend<br>
</span>>>   ; nothing can sneak in here???, Right?<br>
<span class="">>>   switch (resume, destroy, return)<br>
>><br>
>> resume:<br>
</span>>>   coro.barrier(0)<br>
>>   x += 1 ; load + inc + store<br>
>>   [...]<br>
>><br>
>> destroy:<br>
>>   coro.barrier(1)<br>
>>   x += 1 ; load + inc + store<br>
>>   [...]<br>
>><br>
>> return:<br>
>>   coro.barrier(2)<br>
<span class="">>>   (don't touch x)<br>
>>   [...]<br>
<br>
</span>Now we are good, right?<br>
I am still not giving up hope for an intrinsic approach.<br></blockquote><div><br></div><div>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.<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
There is always a backup plan to go to your "two function" idea with a slight<br>
twist.<br>
<br>
<br>
Almost two functions (coro.fork(), coro.suspendO() same as in original proposal)<br>
================================================================================<br>
<br>
CoroEarly pass which runs at EP_EarlyAsPossible will extract f.start using<br>
coro.fork as a guide (since false branch bypasses the coroutine body).<br>
<br>
Coroutine will now travel as two functions until CoroSplit gets to f.start<br>
(Probably will use 'coroutine' attribute on a function to indicate that it<br>
requires CoroSplit to munge on it.)<br>
<br>
I am still hoping we can find a solution without requiring to separate f.start<br>
out. Seems like a huge hammer to avoid undesirable code motion / hoisting.<br>
<br>
(I really hope that @coro.barrier(i64) approach can work)<br>
</blockquote><div><br> </div></div>If you really don't want two functions, you could probably do something like this:<br><br><span class="">block1:<br></span></div><div class="gmail_extra"><span class="">%first_time = load...<br></span></div><div class="gmail_extra"><span class="">br i1 %first_time, label return, label suspend1<br><br>suspend1:<br>suspend </span><br>
<span class="">switch (resume1, destroy1)<br></span><br><span class="">block2:<br></span><div class="gmail_extra"><span class="">%first_time = load...<br></span></div><span class="">br i1 %first_time, label return, label suspend2<br><br>suspend2:<br>suspend </span><br>
<span class="">switch (resume2, destroy2)<br><br></span><span class=""></span></div><div class="gmail_extra"><span class="">label return:<br></span></div><div class="gmail_extra"><span class="">%cont = phi i32 [(block1, 1), (block2, 2)]<br></span></div><div class="gmail_extra"><span class="">; do stuff<br></span></div><div class="gmail_extra"><span class="">switch %cont... (1, label suspend1), (2, label suspend2)<br><br></span></div><div class="gmail_extra"><span class="">It's a little awkward to generate the return block, but otherwise it's reasonably clean. Also, if some non-C++ language wants to generate coroutines, it might not have to generate the return block at all.<br><br></span></div><div class="gmail_extra"><span class="">-Eli<br></span></div></div>