<div dir="ltr">There was a discussion on a very similar topic with regards to C++20 coroutines back in November/December 2020 entitled "[RFC] Coroutine and pthread_self". It discusses exactly the same issues you will run into -- although for coroutines, the issue only occurs in early optimization passes, because eventually the coroutine with yield-points gets transformed into a "normal" function.<div><br></div><div><div>Note that TLS access is not the only problem you have -- the removal of redundant function-calls across a thread-switch will also be a problem, e.g. as enabled by LLVM IR's "readnone" attribute (which is generated from C __attribute__((const)) which is present e.g. on pthread_self).</div><div><br></div><div>See the thread starting here:<br></div><div><div><div><a href="https://lists.llvm.org/pipermail/llvm-dev/2020-November/146766.html">https://lists.llvm.org/pipermail/llvm-dev/2020-November/146766.html</a><br></div><div>and then into the next month here:</div><div><a href="https://lists.llvm.org/pipermail/llvm-dev/2020-December/147012.html">https://lists.llvm.org/pipermail/llvm-dev/2020-December/147012.html</a><br></div></div></div></div><div><br></div><div>The work in this area has not yet been completed.<div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Aug 31, 2021 at 1:44 PM Valentin Churavy via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>Hi LLVM-dev,</div><div><br></div><div>I am working on a runtime system that has task migration, e.g. a task can be migrated between different threads. So a function can start executing on one thread, call a function (that might call into the function),</div><div>and then execute onto a different thread. This poses a problem with thread local variables. As an example, take the program below. After the call to `callee` we might have switched threads and thus we need to</div><div>recalculate the location of the thread local variable. <br></div><div><br></div><div>```</div><div>@var = available_externally thread_local global i32 0, align 4<br><br>declare void @callee()<br><br>define signext i32 @main() nounwind {<br>    entry:<br>    %0 = load i32, i32* @var, align 4<br>    call void @callee()<br>    %1 = load i32, i32* @var, align 4<br>    %2 = icmp eq i32 %0, %1<br>    %3 = zext i1 %2 to i32<br>    ret i32 %3<br>}</div><div>```</div><div><br></div><div>As far as I can tell there is no current mechanism to inform LLVM that thread migration might occur, and it depends on the backend what behaviour you might get.</div><div><br></div><div>As an example compiling with `x86-64-unknown-linux-gnu`, we get:</div><div><br></div><div>```</div><div>     movq    var@GOTTPOFF(%rip), %rbx<br>      movl    %fs:(%rbx), %ebp<br>      callq   callee@PLT<br>    xorl    %eax, %eax<br>    cmpl    %fs:(%rbx), %ebp</div><div>```</div><div><br></div><div>Which happens to be correct. On Darwin on the other hand:</div><div><br></div><div>```</div><div>   movq    _var@TLVP(%rip), %rdi<br> callq   *(%rdi)<br>       movq    %rax, %rbx<br>    movl    (%rax), %ebp<br>  callq   _callee<br>       xorl    %eax, %eax<br>    cmpl    (%rbx), %ebp</div><div>```</div><div><br></div><div>the address for the TLS get's CSE'd, and thus the load could be incorrect.</div><div><br></div><div>Has there been any prior work on supporting thread migration + thread local storage?</div><div><br></div><div>Kind regards,</div><div>Valentin<br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div><div><br></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>