<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/72555>72555</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Subtle issue with [[clang::musttail]]
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          gerben-stavenga
      </td>
    </tr>
</table>

<pre>
    The C/C++ attribute [[clang::musttail]] is meant to be an attribute that guarantees tail call elimination, to prevent stack overflow in iterative algorithms that are written recursively. But as far as I understand it's meant to be a "semantic neutral" attribute. That is if the compiler accepts the attribute the semantics of the program remain the same. This is not true due to lifetime issues. The following example is a correct and legal program

https://godbolt.org/z/556s3a1Mv

where the output between with/without attribute clearly changes. The program with musttail is clearly buggy, ideally clang frontend should reject the attribute, but this requires escape analysis on locals, which can further depend on inlining etc. and I don't  think thats a feasible strategy. So perhaps the best thing is to specify explicitly in the documentation that the behavior is UB if locals are accessed after the tail call is executed.

Assuming the above "solution" to the lifetime issue there is a further issue. In which I think llvm takes the wrong approach. In case parameters are passed on the stack. A subtle issue arises around address escape analysis of those stack parameters.

https://godbolt.org/z/hdMxze9vc

Here the address of the variable that is stored on the stack escapes in function f. Now without musttail the compiler doesn't tail call (see lifetime discussion above). With musttail it escapes the pointer [rsp + 16] which is where the argument was placed on the stack by the caller. So here is an ambiguity. In some sense this address is managed by the caller, so it's lifetime encompasses the lifetime of the tailcall.  On the other hand, if one argues this way and you do a tailcall the called function cannot assume a non-escaped stackframe. Indeed we see that in case g_with_tailcall, it safes the value of the stack passed parameters over the function call, while in g_no_tailcall it doesn't. But this is strange the need to safe the variable depends on how it's called, not really about if it tailcalls itself or not.

Overall it seems llvm is operating in two different modes. If tailcall attribute is present, it considers the parameters that are passed on the stack as escaped by default and if no tailcall attribute is present the parameters are considered not-escaped.

I can see this happening due to the tail call reusing the stack frame and thus it considering the stack frame escaping, not realizing it's already dead. 

My expectation is, that the functions g_with_tailcall and g_no_tailcall should compile to the same instructions. And that in case variable addresses of stack passed parameters escape, those variables spill to normal stack (ie below sp) like stackless parameters so that addresses to the stack passed parameters never escape.

 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUV02P47wN_jXOhVgjcSbzcchhZhdB57B9D-9b9LigJdpWV5ZcUUo2--sLSnY-BrstekkAWyIfks9D0shseke0r3Zv1e7LClMcfNj3FFpynzjikVyPq9br8_6vgeBz1Rw-V81b1bwBxhhMmyJBvvymLLq-2r5W29cxcYxobLX7Uu2-gGEYCV2E6KElQHdzNw4YoU8Y0EUiBrkGCq0FsmY0DqPxrmo-y90p0JFcBI6ovoM_UuisP4FxYCIFjOZIgLb3wcRh5GIaA8EpmBjJQSCVApsj2XMNbykCMnQY5O8dktMUOKLTYGLVPH3ADFXTMI3oolHgKMWAtmqaayQ1_CX-DIPpIA4Eyo-TsRQAlaIpcn54GzjBYpDBlztT8H3AEQKNaFw5g2O2LYYZnI8QQyLQiQSaNR1FMxIY5kQsBwk6b60_GdcD_cBxsvIWEJQPgVQECdFSj3ZxV62_VOvX8jvEOLFUsTlUzaH3uvU21j70VXP4WTWH3e6Rt7j5ery9dBoolIh8ilOK0FI8ETk4mThUzUH-vOT7Er2yhMGeQQ3o-gX3Er0ch4VDgn053aa-PwsZjCa0cl04B13wLpLTwINPVkOgf0mcd_mWW22Sh4Yh0L-TCcRArHASRqI9s2HwDqxXaFmOnwajBlDooEshDhRA0yRuvAPjrHE5w1HVOaPvoIWoTxHEh_ue6Sdp7wjZtJaAY8BI_bmGPz1MFAacCila4gzM9RJs9MATKdOdgX5M1igT7RlmNmiv0kguZlkUhhcLAx6ND3L_H2_CwBJGpr_wj5k0YBcp5PNXlRkG-kEqRdL1bUlfmdMoiHIWW3-krABvUxFkIzjl3T0D5VGY-bZkLb-o4d3NGX2fE2TtcYSI36lk4RS86wGnKXhUQz6vkAkmDDhSpFCimTDH4md1SCuo4RU4tdEuIDAYJjnuk9OAWgfiXxRbNOd5NnLjp_5_BDHorz9-0stR3V7626KHxfes7yMGg8KFOPcKjj58iGbGyVLyLjmVK93V8Hd_gkVIF3HcNRrtiQsFr_Wtmmemmyppwyoxi81c1ap5qeGf94KLFwi5J3njhDfV7i3wBNL6N4_S1ks1DcNV_hj6TE84IcNkUX2MrT0XyGgthSyEC18c4NiaPpl4zsVnP0qHdExFtEsqZZqgw570vTWRLPuleV8CJif5EdLwPV_nkkjIYqAG-KMg9Zm1AzqdW00H3pXIsgWJF89Z8mefQHvAi40rGn0tnUInXRtFUDJInHefSn51SUoXcot_d5pIw0mCXggyS6D_JoX_trjJsCIwdnNMR7TpEtDC5iyTG_HIvMwHbpAVW6fBiHQc9N-cv3gRFxdGlXkZ5ykkncz1peROQEvPwo7uOV66ZW6qg4zpUpiSHnErWQmlj2MrrDad-Fz8M5jIZDvwQY7eifKPI4UZIhONXHqJaHrKi4B0Ugfx5EGbrqMglBy9lkHz3l3LdZ1HhmW7YHJxTq7yjo1sBEUD1zRetopfNCLZJJbStmfQ1GGyZeCaDpz_754_ehInCwzSkoOFN3e5eM8jqnDGMAw4TZRH07wi3Pf7QImXtl4wZ_pljHFIfBv7r85lBMb1twU0P3PCS33RBkItwaOu4Rbo1zzQSM3Dy-QhexlhCyv5I9sztHtmznN-bnxLkLIpgXEcQyqWanjNUd0o6ULOuZtQbs2_k0xJd4Hpb24z8GRE7h6cDyPa2ULVPBsZxrKV8lQ1L2DN9zl_VnrXjW32M5UuQJYwfgPGkQi4QLojAKz0fqtfti-4ov3mab3ePK6fm81q2D-v1aZpt-uHJ93R9nHXdpvnJ4XNjp60fmz1yuybdbPdbDaPm-fd9mFTb56fqdXbHTVPLT1sdtXDWlZRW4vAZOqt8oTdPzW73W5lsSXL-eOhacr-3zTyHRH2cv5Tm3quHtbWcOSrhWiipf2ftwM7b3z_4zNilYLdf5jGJg6prZUfq-Yg9ue_T1PwsgJWzaHsxVVzyIj_EwAA__8u65Lj">