<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jun 10, 2016 at 5:25 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">Hi Eli:<br>
<span class=""><br>
>> Naively, you would expect that it would be legal to hoist the store...<br>
>> but that breaks your coroutine semantics because the global could be mutated<br>
>> between the first return and the resume.<br>
<br>
</span>Hmmm... I don't see the problem. I think hoisting the store is perfectly legal<br>
transformation with all semantics preserved.<br>
<br>
Let's look at your example:<br>
<span class=""><br>
>> block1:<br>
>>   suspend<br>
>>   switch (resume, destroy, return)<br>
>><br>
>> resume:<br>
>>   store zero  to global @g<br>
</span>>>   doA()<br>
<span class="">>>   [...]<br>
>><br>
>> destroy:<br>
>>   store zero  to global @g<br>
</span>>>   doB()<br>
<span class="">>>   [...]<br>
>><br>
>> return:<br>
>>   store zero to global @g<br>
</span>>>   doC<br>
>>   [...]<br>
<br>
As written the behavior is:<br>
<br>
  1) when we encounter a suspend during the first pass through the function,<br>
     store 0 to @g and doC()<br>
<br>
  2) when we encounter a suspend after coroutine was resumed<br>
     ret void<br>
<br>
  3) When coroutine is resumed:<br>
     store 0 to @g and doA()<br>
<br>
  4) When coroutine is destroyed:<br>
     store 0 to @g and doB()<br>
<br>
If this is a coroutine that can be resumed asynchronously from a different<br>
thread there is a data race. For example, if resume happens before 'f' returns,<br>
doA() can write something useful to @g, and 'f' will clobber it with zero.<br>
But, this race is already present in the code and is not introduced by LLVM.<br>
<br>
Let's hoist the store and see what happens:<br>
<br>
>> block1:<br>
>>   suspend<br>
<span class="">>>   store zero  to global @g<br>
>>   switch (resume, destroy, return)<br>
>><br>
>> resume:<br>
</span>>>   doA()<br>
>>   [...]<br>
>><br>
>> destroy:<br>
>>   doB()<br>
>>   [...]<br>
>><br>
>> return:<br>
>>   doC()<br>
>>   [...]<br>
<br>
Now, let's split it up:<br>
  1. RAUW coro.suspend with -1,0,1 in f, f.resume and f.destroy<br>
  2. remove coro.suspend in f, replace with ret void in f.resume<br>
<br>
void f() {<br>
  [...]<br>
<span class="">  store zero  to global @g<br>
</span>  doC();<br>
  [...]<br>
}<br>
<br>
void @f.resume() {<br>
entry:<br>
<span class="">  store zero  to global @g<br>
</span>  doA();<br>
  [....]<br>
}<br>
<br>
void @f.destroy() {<br>
entry:<br>
<span class="">  store zero  to global @g<br>
</span>  doB();<br>
  [....]<br>
}<br>
<br>
Behavior looks exactly as before. What am I missing?<br>
<br></blockquote><div><br></div><div>Err... I guess nothing; sorry, I got myself confused.  Essentially executing a return statement, then jumping back, seems wrong, but I'm having trouble coming up with a good example of how it would actually break something.  I guess there aren't really any issues on a pure control-flow basis: you can't execute a global side-effect a different number of times than it would otherwise happen.<br><br>You might run into problems with allocas: LLVM's optimizer will assume the lifetime of any alloca in the current function ends when you hit a "ret" instruction, so jumping back from the ret to the middle of the function could lead to wrong results.  Silly example:<br><br></div><div>x = alloca...<br><br>block1:<br>
  suspend<br>  ; increment could get moved here.<br></div><div><span class="">  switch (resume, destroy, return)<br>
<br>resume:<br>
</span>  x += 1<br>
   [...]<br> 
<br>destroy:<br>
  x += 1<br>
   [...]<br>
<br>return:<br></div><div>  (don't touch x)<br></div><div>  [...]<br></div><div><br></div><div>The increment is only supposed to execute once, but instead executes twice.<br></div><div><br></div><div>This isn't a great example... and I'm not sure issues are limited to allocas... but that's the idea, anyway.<br></div><div><br></div><div>-Eli<br></div></div><br></div></div>