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

Chuanqi Xu via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 5 22:17:49 PDT 2023


ChuanqiXu updated this revision to Diff 528683.
ChuanqiXu marked an inline comment as done.
ChuanqiXu added a comment.

Address comments.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D151774/new/

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,63 @@
   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: %thread_local.0 = call ptr @llvm.threadlocal.address
+; CHECK-NEXT: %readonly.0 = call ptr @readonly_funcs()
+; 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: %thread_local.1 = call ptr @llvm.threadlocal.address
+; CHECK-NEXT: %readonly.1 = call ptr @readonly_funcs()
+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
+  %thread_local.0 = call ptr @llvm.threadlocal.address(ptr @tls)
+  %readonly.0 = call ptr @readonly_funcs()
+  %suspend = call i8 @llvm.coro.suspend(token none, i1 false)
+    switch i8 %suspend, label %exit [
+    i8 0, label %await.ready
+  ]
+
+await.ready:
+  %thread_local.1 = call ptr @llvm.threadlocal.address(ptr @tls)
+  %readonly.1 = call ptr @readonly_funcs()
+  %cmp.0 = icmp eq ptr %thread_local.0, %thread_local.1
+  %cmp.1 = icmp eq ptr %readonly.0, %readonly.1
+  %cmp = and i1 %cmp.0, %cmp.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 @readonly_funcs() readonly
+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
@@ -1226,6 +1226,15 @@
 
     // Handle simple cases by querying alias analysis.
     MemoryEffects Behavior = AA->getMemoryEffects(CI);
+
+    // FIXME: We don't handle the semantics of thread local well. So that the
+    // address of thread locals are fake constants in coroutines. So We forbid
+    // to treat onlyReadsMemory call in coroutines as constants now. Note that
+    // it is possible to hide a thread local access in a onlyReadsMemory call.
+    // Remove this check after we handle the semantics of thread locals well.
+    if (Behavior.onlyReadsMemory() && CI->getFunction()->isPresplitCoroutine())
+      return false;
+
     if (Behavior.doesNotAccessMemory())
       return true;
     if (Behavior.onlyReadsMemory()) {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D151774.528683.patch
Type: text/x-patch
Size: 3142 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230606/d2f3f9e8/attachment.bin>


More information about the llvm-commits mailing list