<div dir="ltr">I reverted this in <span style="color:rgb(0,0,0)">r221226. It shouldn't be hard to fix, but I didn't want to leave it broken overnight.</span><div><span style="color:rgb(0,0,0)"><br></span></div><div><span style="color:rgb(0,0,0)">Basically, if you have the situation a musttail calls b which musttail calls c and they all use byval, then you can inline b into a but you must preserve the musttail call to c.</span></div><div><span style="color:rgb(0,0,0)"><br></span></div><div><span style="color:rgb(0,0,0)">musttail is a *guarantee* that tail call elimination will occur, not an optimization hint that we can remove. The musttail annotation guarantees two things:<br>1. No stack frame will be created for the musttail call, so unbounded stack growth cannot occur.</span></div><div><span style="color:rgb(0,0,0)">2. Any inalloca or variadic arguments are forwarded in place without modification.</span></div><div><span style="color:rgb(0,0,0)"><br></span></div><div><span style="color:rgb(0,0,0)">In the byval case, it's property 1 we need to think about. Suppose c was actually a and this was mutual tail recursion. Now without musttail, the program may blow the stack.</span></div><div><span style="color:rgb(0,0,0)"><br></span></div><div><font color="#000000">You can still do your optimization safely and preserve musttail. You just have to realize that passing a pointer to a byval argument doesn't actually escape it. The pointer parameter that the callee receives is actually a new pointer that points to a fresh copy of the data. If a byval parameter passed to b escapes to c in any way, that was already a violation of musttail semantics, so the original program was incorrect. The only safe way to pass a local alloca or byval parameter to a musttail callee is if you pass it as a byval argument, because that creates a copy.</font></div><div><font color="#000000"><br></font></div><div><font color="#000000">It took a while to talk this out with Nick this afternoon.</font></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Nov 3, 2014 at 11:50 AM, Reid Kleckner <span dir="ltr"><<a href="mailto:rnk@google.com" target="_blank">rnk@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I think the changes for musttail were wrong here, but I need to think harder. Mechanically, inlining one level of musttail -> musttail should work, but it violates the langref guarantees. Maybe we need to finesse the reference.<div><br></div><div>This is the kind of optimizer change that should really get pre-commit code review.</div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Oct 31, 2014 at 11:02 PM, Rafael Espíndola <span dir="ltr"><<a href="mailto:rafael.espindola@gmail.com" target="_blank">rafael.espindola@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div>><br>
> -; Don't insert lifetime end markers here, the lifetime is trivially over due<br>
> -; the return.<br>
> -; CHECK: define void @test_byval_a(<br>
> -; CHECK: musttail call void @test_byval_c(<br>
> -; CHECK-NEXT: ret void<br>
> -<br>
> -declare void @test_byval_c(i32* byval %p)<br>
> -define internal void @test_byval_b(i32* byval %p) {<br>
> -  musttail call void @test_byval_c(i32* byval %p)<br>
> -  ret void<br>
> -}<br>
> -define void @test_byval_a(i32* byval %p) {<br>
> -  musttail call void @test_byval_b(i32* byval %p)<br>
> -  ret void<br>
> -}<br>
> -<br>
> -; Don't insert a stack restore, we're about to return.<br>
> -; CHECK: define void @test_dynalloca_a(<br>
> -; CHECK: call i8* @llvm.stacksave(<br>
> -; CHECK: alloca i8, i32 %n<br>
> -; CHECK: musttail call void @test_dynalloca_c(<br>
> -; CHECK-NEXT: ret void<br>
> -<br>
> -declare void @escape(i8* %buf)<br>
> -declare void @test_dynalloca_c(i32* byval %p, i32 %n)<br>
> -define internal void @test_dynalloca_b(i32* byval %p, i32 %n) alwaysinline {<br>
> -  %buf = alloca i8, i32 %n              ; dynamic alloca<br>
> -  call void @escape(i8* %buf)           ; escape it<br>
> -  musttail call void @test_dynalloca_c(i32* byval %p, i32 %n)<br>
> -  ret void<br>
> -}<br>
> -define void @test_dynalloca_a(i32* byval %p, i32 %n) {<br>
> -  musttail call void @test_dynalloca_b(i32* byval %p, i32 %n)<br>
> -  ret void<br>
> -}<br>
<br>
</div></div>Why remove these tests? The musttail case in particular is interesting.<br>
<br>
Cheers,<br>
Rafael<br>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>