[PATCH] D151774: [LICM] Don't hoist threadlocals within presplit coroutines

Chuanqi Xu via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 30 20:51:28 PDT 2023


ChuanqiXu created this revision.
ChuanqiXu added reviewers: nikic, jdoerfert, jyknight, nlopes, nhaehnle.
Herald added subscribers: StephenFan, asbirlea, hiraditya.
Herald added a project: All.
ChuanqiXu requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Close https://github.com/llvm/llvm-project/issues/63022

This is the following of https://reviews.llvm.org/D135550, which is discussed in https://discourse.llvm.org/t/rfc-unify-memory-effect-attributes/65579. In my imagination, we could fix the issue fundamentally after we introduces new memory kind `thread id`. But I am not very sure if we can fix the issue fundamentally in time.

Besides that, I think the correctness is the most important. So it should not be bad to land this given it is innocent.


https://reviews.llvm.org/D151774

Files:
  llvm/lib/Transforms/Scalar/LICM.cpp
  llvm/test/Transforms/LICM/sink-with-coroutine.ll


Index: llvm/test/Transforms/LICM/sink-with-coroutine.ll
===================================================================
--- llvm/test/Transforms/LICM/sink-with-coroutine.ll
+++ llvm/test/Transforms/LICM/sink-with-coroutine.ll
@@ -48,5 +48,56 @@
   ret i64 0
 }
 
+ at tls = thread_local global i32 0
+
+define i64 @hoist_threadlocal() presplitcoroutine {
+; CHECK-LABEL: @hoist_threadlocal
+; CHECK: loop.preheader:
+; CHECK-NEXT: br label %for.body
+; CHECK: for.body:
+; CHECK-NEXT: %i = phi i64
+; CHECK-NEXT: %i.next = add i64 %i
+; CHECK-NEXT: %0 = call ptr @llvm.threadlocal.address
+; CHECK-NEXT: %suspend = call i8 @llvm.coro.suspend
+; CHECK-NEXT: switch i8 %suspend, label %exit 
+; CHECK-NEXT: i8 0, label %await.ready 
+; CHECK: await.ready:
+; CHECK-NEXT: %1 = call ptr @llvm.threadlocal.address
+entry:
+  %p = alloca i64
+  br label %loop.preheader
+
+loop.preheader:
+  br label %for.body
+
+for.body:
+  %i = phi i64 [ 0, %loop.preheader ], [ %i.next, %loop.end ]
+  %i.next = add i64 %i, 1
+  %0 = call ptr @llvm.threadlocal.address(ptr @tls)
+  %suspend = call i8 @llvm.coro.suspend(token none, i1 false)
+    switch i8 %suspend, label %exit [
+    i8 0, label %await.ready
+  ]
+
+await.ready:
+  %1 = call ptr @llvm.threadlocal.address(ptr @tls)
+  %cmp = icmp eq ptr %0, %1
+  br i1 %cmp, label %not.reachable, label %loop.end
+
+not.reachable:
+  call void @not.reachable()
+  br label %loop.end
+
+loop.end:
+  %loop.end.cond = icmp ugt i64 %i.next, 5
+  br i1 %cmp, label %exit, label %for.body
+
+exit:
+  %res = call i1 @llvm.coro.end(ptr null, i1 false)
+  ret i64 0
+}
+
 declare i8  @llvm.coro.suspend(token, i1)
 declare i1  @llvm.coro.end(ptr, i1)
+declare nonnull ptr @llvm.threadlocal.address(ptr nonnull) nounwind readnone willreturn
+declare void @not.reachable()
Index: llvm/lib/Transforms/Scalar/LICM.cpp
===================================================================
--- llvm/lib/Transforms/Scalar/LICM.cpp
+++ llvm/lib/Transforms/Scalar/LICM.cpp
@@ -1219,6 +1219,14 @@
     if (CI->isConvergent())
       return false;
 
+    // FIXME: We don't handle the semantics of thread local well. So that the
+    // address thread locals are fake constants in coroutines. We forbid this
+    // explcitly now.
+    // Remove this check after we handle the semantics of thread locals well.
+    if (CI->getIntrinsicID() == Intrinsic::threadlocal_address &&
+        CI->getFunction()->isPresplitCoroutine())
+      return false;
+
     using namespace PatternMatch;
     if (match(CI, m_Intrinsic<Intrinsic::assume>()))
       // Assumes don't actually alias anything or throw


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151774.526884.patch
Type: text/x-patch
Size: 2614 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230531/6ca1c43b/attachment.bin>


More information about the llvm-commits mailing list