<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jul 14, 2016 at 9:28 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 David:<br>
<span class=""><br>
>> How do you deal with basic blocks which appear to be used by multiple parts<br>
>> of the coroutine? We handled this in WinEHPrepare by cloning any BBs which<br>
>> were shared.<br>
<br>
</span>I experimented with several approaches, but, cloning ended up being the simplest<br>
and most reliable. Suspend points express three different control flows that<br>
can happen at the suspend point: a suspension (default), resumption (0) and<br>
destruction (1).<br>
<br>
  %0 = call i8 @llvm.coro.suspend([..])<br>
  switch i8 %0, label %suspend [i8 0, label %resume,<br>
                                i8 1, label %destroy]<br>
<br>
I slap a switch that jumps to all suspend points in the function. Then I clone<br>
the function twice (one will become resume clone, and another destroy clone).<br>
This switch becomes the entry block in the clones. Then, I RAUW coro.suspends<br>
with -1, 0, or 1 (in original, resume and destroy clones respectively) and let<br>
SimplifyCFG do the rest. (This is slightly simplified explanation, but it should<br>
 give the idea).<br></blockquote><div><br></div><div>I like it, sounds nice and simple :)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><br>
>> I would remove the attribute.  There are all sorts of tricks you can do to<br>
>> avoid scanning the function for calls to the intrinsic.  For example, you<br>
>> can see if a declaration of your intrinsic exists and, if so, if it has an<br>
>> users in the function in question (under the assumption that there are few).<br>
<br>
</span>Aye-aye. Will remove the attribute.<br>
<br>
With respect to lessening the impact of coroutine passes, one approach I tried<br>
was to look during doInitialize whether there are any uses of coroutine<br>
intrinsics and set a flag if there are any, or maybe build a set of functions<br>
with coroutines intrinsics in doInitialize, so that in runOnFunction, I can just<br>
check whether the function is in the set and skip if it is not.<br>
<br>
Then, I scared myself silly that some optimization passes can materialize<br>
new functions or new function bodies and I will miss them. So I stopped doing<br>
that.<br>
<br>
I think your approach takes care of my "materialization" concern. (BTW, I don't<br>
even know if that is a real concern).</blockquote><div><br></div><div>Functions can be created from nothing in LLVM.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> But may not be profitable if there are a<br>
lot of small functions that are faster to scan for coroutine intrinsics then to<br>
scan potentially longer list of coroutine intrinsics users.<br></blockquote><div><br></div><div>I find that unlikely but we can always benchmark it if we get concerned.  I'd use a naive approach to start out with.</div><div>If it shows up on profiles, we can optimize it.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
BTW, Do you have a preference on how to restart CGSCC pipeline? One of the four<br>
options I listed (repeated in P.S), or even some better way I did not think<br>
about?<br></blockquote><div><br></div><div>I'm not an expert in that area.  I think you will want someone like Chandler or Hal to give advice here.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
Thank you,<br>
Gor<br>
<br>
P.S.<br>
<br>
Option 1: <a href="https://reviews.llvm.org/D21569" rel="noreferrer" target="_blank">https://reviews.llvm.org/D21569</a> (no longer relevant, since we are<br>
                                           removing AttrKind::Coroutine)<br>
Option 2: <a href="https://reviews.llvm.org/D21570" rel="noreferrer" target="_blank">https://reviews.llvm.org/D21570</a> (bool& Devirt in runSCC)<br>
Option 3: <a href="https://reviews.llvm.org/D21572" rel="noreferrer" target="_blank">https://reviews.llvm.org/D21572</a> (virtual bool restatedRequested())<br>
Option 4: Fake devirtualized call in a function pass, so that RefreshSCC will<br>
          detect devirtualization and restart the pipeline by itself.<br>
</blockquote></div><br></div></div>