This is an archive of the discontinued LLVM Phabricator instance.

[Coroutines] Introduce @llvm.coro.tls.wrapper to block optimizations
AbandonedPublic

Authored by ChuanqiXu on Jul 19 2022, 9:03 PM.

Details

Summary

This is the original idea to solve the TLS problem in coroutines described in https://discourse.llvm.org/t/address-thread-identification-problems-with-coroutine/62015.

The main discussion of the thread is about how should we handle readnone attribute and this is already done in D127383. The here is the other problem about TLS variables.

@jyknight points out that we could solve this problem and the TLS is not a constant problem in one shot and we get in consensus this is the good direction. So I sent D125291 and D129833.

But now clang15 branch is going to be created in the next week and D125291 has no hopes to land before that. It implies that the TLS bug would remain in clang15. I think it is really a pity that the bug has lived for 2 years.

@rjmccall sent concerns about the automatically merge of TLS addresses so that CoroEarly might not be early enough. But both of us failed to give an example. My thought is that the current one might not be perfect and D125291 should be the direction in the future. And the current one is simple enough and workable in most cases. I think we could land this first to fix the bug. I would revert this one if D125291 or any other similar patches get landed. How do you think about the strategy?

Diff Detail

Event Timeline

ChuanqiXu created this revision.Jul 19 2022, 9:03 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 19 2022, 9:03 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
ChuanqiXu requested review of this revision.Jul 19 2022, 9:03 PM

John mentioned this test case,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, co_await something_suspending());
}

Is replacing the TLS variable with llvm.coro.tls.wrapper in CoroEarly too late to fix the issue?

John mentioned this test case,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, co_await something_suspending());
}

Is replacing the TLS variable with llvm.coro.tls.wrapper in CoroEarly too late to fix the issue?

This example may be fine since C++ standard specifies that the order of evaluation of function arguments is unspecified: https://en.cppreference.com/w/cpp/language/eval_order.

ychen added a comment.Jul 20 2022, 7:30 PM

John mentioned this test case,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, co_await something_suspending());
}

Is replacing the TLS variable with llvm.coro.tls.wrapper in CoroEarly too late to fix the issue?

This example may be fine since C++ standard specifies that the order of evaluation of function arguments is unspecified: https://en.cppreference.com/w/cpp/language/eval_order.

That's my understanding as well. Sorry I should've changed it a little,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, (&x, co_await something_suspending()));
}

The comma operator should have the left-to-right evaluation order. Personally, I hope there is a workaround for Clang 15. I'm just trying to convince myself that this workaround solves both issues in principle (even with potential pessimization with the TLS variables). But this test case makes me hesitate.

John mentioned this test case,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, co_await something_suspending());
}

Is replacing the TLS variable with llvm.coro.tls.wrapper in CoroEarly too late to fix the issue?

This example may be fine since C++ standard specifies that the order of evaluation of function arguments is unspecified: https://en.cppreference.com/w/cpp/language/eval_order.

That's my understanding as well. Sorry I should've changed it a little,

thread_local int x = 0;
void helper(int *x, int y);
my_coro coroutine() {
  helper(&x, (&x, co_await something_suspending()));
}

The comma operator should have the left-to-right evaluation order. Personally, I hope there is a workaround for Clang 15. I'm just trying to convince myself that this workaround solves both issues in principle (even with potential pessimization with the TLS variables). But this test case makes me hesitate.

For the specific example, it is fine since &x would be deprecated due to it has no side effect as a comma operator. I guess this example fits your intention more:

thread_local int tls_variable = 0;
void helper(int *x);
int *helper1(int *x);
task coro() {
    helper((helper1(&tls_variable), co_await MyAwaiter()));
}

In this example, &tls_variable would be evaluated before the await expression: https://godbolt.org/z/xse1q57ze

Given the bug is important and the patch is relatively small and innocent, I want to land this one before 15.x branch is created if no objection comes in.

ychen added a comment.Jul 25 2022, 1:10 PM

Given the bug is important and the patch is relatively small and innocent, I want to land this one before 15.x branch is created if no objection comes in.

Sounds good to me. One last question is: why not just use llvm.threadlocal.address? The plan is to replace llvm.coro.tls.wrapper with llvm.threadlocal.address right? I'd prefer not to add an LLVM intrinsic just for one specific release.

Given the bug is important and the patch is relatively small and innocent, I want to land this one before 15.x branch is created if no objection comes in.

Sounds good to me. One last question is: why not just use llvm.threadlocal.address? The plan is to replace llvm.coro.tls.wrapper with llvm.threadlocal.address right? I'd prefer not to add an LLVM intrinsic just for one specific release.

Yeah, the plan is going to replace llvm.coro.tls.wrapper with llvm.threadlocal.address. The reason why I introduced a new intrinsics is the semantic differences. llvm.threadlocal.address is a fundamental one and llvm.coro.tls.wrapper is specific to coroutines. I think it might not be too bad. Since we've commented that llvm.coro.tls.wrapper is used internally. I feel like it might not be possible that someone else would use it accidently.

ychen accepted this revision.Jul 25 2022, 7:34 PM

LGTM. Please mention in the docs along the lines that we will "replace llvm.coro.tls.wrapper with llvm.threadlocal.address." in the future.

This revision is now accepted and ready to land.Jul 25 2022, 7:34 PM

LGTM. Please mention in the docs along the lines that we will "replace llvm.coro.tls.wrapper with llvm.threadlocal.address." in the future.

Thanks! Will do.

We failed to land the dependent patch in time. So we could keep patient now.

ChuanqiXu abandoned this revision.Jul 31 2022, 8:05 PM

Abandon this one since we landed D129833.