<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Thu, Jun 9, 2016 at 1:17 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:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Eli:<span class=""></span><span class=""><br>
> That said, thinking about it a bit more, I'm not really sure why you need to<br>
> tie the suspend call to the branch in the first place.<br>
<br>
</span>I am not sure I understand the question. Suspend intrinsic is replaced with<br>
a branch to a return block in the 'f' and with 'ret void' in resume.<br></blockquote><div><br></div><div>Right... but that doesn't mean the call to the suspend intrinsic has to be the last non-terminator instruction in the basic block before you run CoroSplit. You can split the basic block in CoroSplit so any instructions after the suspend call are part of a different basic block. Then resume and destroy both branch to the continuation of the basic block (and run different codepaths based on the boolean).<br></div><div><span class=""></span><br><span class=""></span></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> What exactly is your algorithm doing that requires it? I mean, a naive<br>
> implementation of CoroSplit based on your llvm.experimental.coro.suspend<br>
> intrinsic clones the whole function, replaces the result of suspend calls<br>
> with "true" in one version and "false" in the other, and runs SimplifyCFG<br>
> to kill the dead code.<br>
<br>
</span>Very close. We do clone function body twice, once for resume and once for<br>
destroy. We make a new entry block with a switch instruction that will branch to<br>
all resume branches in `f.resume` and to all cleanup branches in `f.destroy` and<br>
then let SimplifyCFG to remove the rest.<br></blockquote><div><br></div><div>Okay, that helps me visualize it.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Changing the subject a little bit. I was thinking we can get rid of the<br>
coro.fork altogether it we add a third label to the corosuspend.<br>
<br>
Namely:<br>
<br>
corosuspend [final] [save %token] to label %return.block<br>
<span class=""> resume label %resume<br>
cleanup label %cleanup<br>
<br>
</span>corosuspend is lowered as follows:<br>
in 'f': corosuspend is replaced with `br %return.block`<br>
<br>
in 'f.resume':<br>
add a new entry block with a switch jumping to all resume blocks<br>
corosuspend is replaced with `ret void`<br>
<br>
in 'f.destroy':<br>
add a new entry block with a switch jumping to all cleanup blocks<br>
corosuspend is replaced with `ret void`<br>
<br>
I think this makes understanding of the model clearer. The only negative side<br>
to a corosuspend with three branching targets is that it is very likely that<br>
to label block will be the same in all corosuspend's thus wasting valuable<br>
bits. :-)<br></blockquote><div><br></div>Yes, this makes sense.<br></div><div class="gmail_quote"><div><br></div><div>-Eli<br></div></div></div></div>