<p dir="ltr"><br>
On Dec 26, 2015 8:15 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
><br>
> On Sat, Dec 26, 2015 at 9:55 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> ><br>
> ><br>
> > On Sat, Dec 26, 2015 at 5:15 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> > wrote:<br>
> >><br>
> >><br>
> >><br>
> >> On Sat, Dec 26, 2015 at 4:59 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
> >> wrote:<br>
> >>><br>
> >>> On Sat, Dec 26, 2015 at 7:08 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> >>> wrote:<br>
> >>> ><br>
> >>> > On Dec 26, 2015 3:04 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
> >>> >><br>
> >>> >> On Sat, Dec 26, 2015 at 5:57 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
> >>> >> wrote:<br>
> >>> >> ><br>
> >>> >> > On Dec 26, 2015 2:22 PM, "Connor Abbott" <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
> >>> >> > wrote:<br>
> >><br>
> >><br>
> >> [snip]<br>
> >><br>
> >>><br>
> >>> >> >> There are a few problems with this approach.<br>
> >>> >> >><br>
> >>> >> >> First off, imagine something like:<br>
> >>> >> >><br>
> >>> >> >> if (...) {<br>
> >>> >> >>   if (...) return;<br>
> >>> >> >> }<br>
> >>> >> >> ...<br>
> >>> >> >><br>
> >>> >> >> If I'm reading this correctly, we'd lower this to:<br>
> >>> >> >><br>
> >>> >> >> if (...) {<br>
> >>> >> >>    if (...) ;<br>
> >>> >> >> }<br>
> >>> >> >> ...<br>
> >>> >> ><br>
> >>> >> > Oops... You're right.  I meant to add returns.  This<br>
> >>> >> ><br>
> >>> >> > if (...) {<br>
> >>> >> >    if (...) return;<br>
> >>> >> >    // foo<br>
> >>> >> > }<br>
> >>> >> ><br>
> >>> >> > Should be lowered to<br>
> >>> >> ><br>
> >>> >> > if (...) {<br>
> >>> >> >    if (...) {<br>
> >>> >> >    } else {<br>
> >>> >> >       // foo<br>
> >>> >> >    }<br>
> >>> >> >    return;<br>
> >>> >> > }<br>
> >>> >> ><br>
> >>> >> > Which we can then lower further.<br>
> >>> >><br>
> >>> >> I don't think that's correct though. What if there's stuff after the<br>
> >>> >> outer if? It'll only get executed if the outer if condition is false,<br>
> >>> >> instead of if either one is false. I think we really need the flag in<br>
> >>> >> this case.<br>
> >>> ><br>
> >>> > If there's stuff in the outer if, it gets moved into the else<br>
> >>><br>
> >>> Stuff after the outer if, not in it.<br>
> >><br>
> >><br>
> >> Right.  I'm thinking what we probably want is a two-pass approach.<br>
> >><br>
> >> Pass 1: Loops.  We recurs into all loops and lower returns to set the<br>
> >> return flag and break.  This pass goes top-down and depth-first to ensure<br>
> >> that we hit the "if (return_flag) return" after the loop it belongs to.  I<br>
> >> also just realized that "if (return_flag return" needs to be inserted after<br>
> >> the phi nodes.  We'll need a new cursor helper for that.<br>
> >><br>
> >> Pass 2: If's not in loops.  At this point, we can ignore loops completely<br>
> >> since we've already lowered all of them and we need only consider blocks.<br>
> >> This pass is a post-order bottom-up DFS.  We look at if/else blocks and, if<br>
> >> one of them has a return, move the stuff after the node into whichever case<br>
> >> doesn't return and put a return after the node.<br>
> >><br>
> >> How does that sound?<br>
> ><br>
> ><br>
> > Bah!  I just realized why this won't work  If I have<br>
> ><br>
> > if (...) {<br>
> >    // foo<br>
> >    return;<br>
> > }<br>
> > // bar<br>
> ><br>
> > it'll get replace with<br>
> ><br>
> > if (...) {<br>
> >    // foo<br>
> > } else {<br>
> >    // bar<br>
> > }<br>
> ><br>
> > and we're still left with the problem of where to place the return.  I'm<br>
> > trying to get rid of it, so it seems natural to place it outside the<br>
> > function.  However, bar might not have returned at the end. so we may need<br>
> > to keep going.  For top-level, I thing this works ok because we can just<br>
> > pull the rest of the function into the else.  However, for nested if's, it<br>
> > doesn't work.  I guess I do need the return_flag for everything.  Let's hope<br>
> > dead_cf does a good job...<br>
> ><br>
><br>
> Yeah. The way I think about it is that if we have the following:<br>
><br>
> if (A) {<br>
>   if (B) return;<br>
>   foo();<br>
> }<br>
> bar();<br>
><br>
> then bar is predicated on !(A and B), but if we simply pull things<br>
> into the other branch, then we get:<br>
><br>
> if (A) {<br>
>   if (!B) {<br>
>     foo();<br>
>   }<br>
>   return;<br>
> }<br>
> bar();<br>
><br>
> and now bar is predicated on !A. In other words, when we moved the<br>
> return down we messed up the condition under which code after the if<br>
> is run, which is only ok if there isn't stuff after the if (i.e. if<br>
> we're on the top level). I think we need something similar to what you<br>
> have now, except that when we hit a return outside of a loop, we emit<br>
> code to set return_flag and return progress, propagating it upwards,<br>
> and then when we've made progress on either branch of an if we need to<br>
> wrap the stuff after the if (if there is any) in if (!return_flag) {}.<br>
> Then, pulling stuff into the other branch becomes an optimization, one<br>
> that we can either do here or with a few other passes as I mentioned<br>
> earlier (or perhaps both). I'm a fan of the "keep it simple and<br>
> correct, then optimize" approach, even if it means more code, so I'd<br>
> prefer to clean up the mess afterwards.</p>
<p dir="ltr">Yup.  That's my new plan.  I was trying to be too clever.</p>