<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jul 15, 2016 at 2:44 PM, Sanjoy Das <span dir="ltr"><<a href="mailto:sanjoy@playingwithpointers.com" target="_blank">sanjoy@playingwithpointers.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"><span class="">Hi Daniel,<br>
<br>
Daniel Berlin wrote:<br></span><span class="">
>     Don't we have the same problems for "exit(0)"<br>
><br>
><br>
> This is a noreturn call, so yes, iit has another hidden control<br>
> flow-side-effect of a slightly different kind. GCC models it as an extra<br>
> fake edge from the BB containing a noreturn call to the exit block of<br>
> the function, so that nothing sinks below it by accident.<br>
<br></span>
Just to be clear, it'd have to keep that sort of edge for all call<br>
sites, unless it can prove that the call target does not call exit?</blockquote><div><br></div><div>Yes.</div><div><br></div><div><div>/* Add fake edges to the function exit for any non constant and non</div><div>    noreturn calls (or noreturn calls with EH/abnormal edges),</div><div>    volatile inline assembly in the bitmap of blocks specified by BLOCKS</div><div>    or to the whole CFG if BLOCKS is zero. </div><div>...</div><div><br></div><div>    The goal is to expose cases in which entering a basic block does</div><div>    not imply that all subsequent instructions must be executed.  */</div></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
// ptr_a and ptr_b are NoAlias, ptr_a holds 0 to begin with.<br>
<br>
ThreadA:<br>
  while(true) { store volatile i32 42, i32* %ptr_b }<br>
  store atomic i32 42, i32* %ptr_a<br>
<br>
ThreadB:<br>
  %val = load atomic i32, i32* %ptr_a<br>
  assert(%val is not 42)  // The store is "guarded" by an inf loop<br>
<br>
<br>
We can't reorder the store to ptr_a to before the infinite loop.  The<br>
volatile store is there to make the infinite loop well defined.</blockquote><div><br></div><div>These do not have hidden control flow. It is actually well defined it just literallly involves other instructions :)</div><div><br></div><div>Note that gcc will optionally connect the infinite loop itself to the exit block with a fake edge if you want</div><div>(you can add/remove fake edges on a per-opt basis).</div><div><br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=""><br>
<br>
> Or did you mean something else?<br>
><br>
>        Both of these are optimization barriers<br>
>     while still being "nounwind" (i.e. could be legitimately contained in<br>
>     a nounwind function); though not in exactly the same way as a<br>
>     may-throw call (e.g. you can DSE across exit(0) and you can sink<br>
>     non-atomic loads past "while(true) {...}").<br>
><br>
><br>
> I do not claim there are not other instances. Noreturn is in fact, a<br>
> good exampl). But i would also bet they are just as buggy as may-throw<br>
> was for the same reason, and they would cause the same N^2ness.<br>
<br></span>
Yes.<span class=""><br>
<br>
> Essentially, anything that has produces hidden control flow (instead of<br>
> just depending on hidden control flow) will have this issue.<br>
> The also are things that any flag/analysis should be able to flag.<br>
<br></span>
Yup.<span class=""><font color="#888888"><br>
<br>
-- Sanjoy<br>
</font></span></blockquote></div><br></div></div>