[coro async] Don't promote allocas to the frame or rewrite swifterror if there are...
authorArnold Schwaighofer <aschwaighofer@apple.com>
Fri, 12 Feb 2021 18:27:31 +0000 (10:27 -0800)
committerArnold Schwaighofer <aschwaighofer@apple.com>
Tue, 16 Feb 2021 17:05:38 +0000 (09:05 -0800)
Also don't call function to update the call graph if there are no
clones. The function will fail.

rdar://74277860

Differential Revision: https://reviews.llvm.org/D96620

llvm/lib/Transforms/Coroutines/CoroFrame.cpp
llvm/lib/Transforms/Coroutines/CoroSplit.cpp
llvm/test/Transforms/Coroutines/coro-async.ll

index 7ef69c4..b3279bb 100644 (file)
@@ -2219,7 +2219,9 @@ void coro::salvageDebugInfo(
 }
 
 void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
-  eliminateSwiftError(F, Shape);
+  // Don't eliminate swifterror in async functions that won't be split.
+  if (Shape.ABI != coro::ABI::Async || !Shape.CoroSuspends.empty())
+    eliminateSwiftError(F, Shape);
 
   if (Shape.ABI == coro::ABI::Switch &&
       Shape.SwitchLowering.PromiseAlloca) {
@@ -2290,7 +2292,8 @@ void coro::buildCoroutineFrame(Function &F, Shape &Shape) {
   }
 
   sinkLifetimeStartMarkers(F, Shape, Checker);
-  collectFrameAllocas(F, Shape, Checker, FrameData.Allocas);
+  if (Shape.ABI != coro::ABI::Async || !Shape.CoroSuspends.empty())
+    collectFrameAllocas(F, Shape, Checker, FrameData.Allocas);
   LLVM_DEBUG(dumpAllocas(FrameData.Allocas));
 
   // Collect the spills for arguments and other not-materializable values.
index 04f426d..52c06e8 100644 (file)
@@ -584,6 +584,8 @@ void CoroCloner::replaceCoroEnds() {
 
 static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape,
                                  ValueToValueMapTy *VMap) {
+  if (Shape.ABI == coro::ABI::Async && Shape.CoroSuspends.empty())
+    return;
   Value *CachedSlot = nullptr;
   auto getSwiftErrorSlot = [&](Type *ValueTy) -> Value * {
     if (CachedSlot) {
@@ -1811,7 +1813,8 @@ static void updateCallGraphAfterCoroutineSplit(
     case coro::ABI::RetconOnce:
       // Each clone in the Async/Retcon lowering references of the other clones.
       // Let the LazyCallGraph know about all of them at once.
-      CG.addSplitRefRecursiveFunctions(N.getFunction(), Clones);
+      if (!Clones.empty())
+        CG.addSplitRefRecursiveFunctions(N.getFunction(), Clones);
       break;
     }
 
index 6114d74..aa83405 100644 (file)
@@ -445,6 +445,60 @@ entry:
 ; CHECK: bitcast i8* %3 to %async.task*
 ; CHECK: }
 
+@no_coro_suspend_fp = constant <{ i32, i32 }>
+  <{ i32 trunc ( ; Relative pointer to async function
+       i64 sub (
+         i64 ptrtoint (void (i8*)* @no_coro_suspend to i64),
+         i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @no_coro_suspend_fp, i32 0, i32 1) to i64)
+       )
+     to i32),
+     i32 128    ; Initial async context size without space for frame
+}>
+
+define swiftcc void @no_coro_suspend(i8* %async.ctx) {
+entry:
+  %some_alloca = alloca i64
+  %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
+          i8* bitcast (<{i32, i32}>* @no_coro_suspend_fp to i8*))
+  %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
+  call void @some_may_write(i64* %some_alloca)
+  call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0)
+  unreachable
+}
+
+; CHECK-LABEL: define swiftcc void @no_coro_suspend
+; CHECK:   [[ALLOCA:%.*]] = alloca i64
+; CHECK:   call void @some_may_write(i64* {{.*}}[[ALLOCA]])
+
+@no_coro_suspend_swifterror_fp = constant <{ i32, i32 }>
+  <{ i32 trunc ( ; Relative pointer to async function
+       i64 sub (
+         i64 ptrtoint (void (i8*)* @no_coro_suspend_swifterror to i64),
+         i64 ptrtoint (i32* getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @no_coro_suspend_swifterror_fp, i32 0, i32 1) to i64)
+       )
+     to i32),
+     i32 128    ; Initial async context size without space for frame
+}>
+
+declare void @do_with_swifterror(i64** swifterror)
+
+define swiftcc void @no_coro_suspend_swifterror(i8* %async.ctx) {
+entry:
+  %some_alloca = alloca swifterror i64*
+  %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0,
+          i8* bitcast (<{i32, i32}>* @no_coro_suspend_swifterror_fp to i8*))
+  %hdl = call i8* @llvm.coro.begin(token %id, i8* null)
+  store i64* null, i64** %some_alloca, align 8
+  call void @do_with_swifterror(i64** swifterror %some_alloca)
+  call i1 (i8*, i1, ...) @llvm.coro.end.async(i8* %hdl, i1 0)
+  unreachable
+}
+
+ ; CHECK-LABEL: define swiftcc void @no_coro_suspend_swifterror
+ ; CHECK:  [[ALLOCA:%.*]] = alloca swifterror i64*
+ ; CHECK:   store i64* null, i64** [[ALLOCA]]
+ ; CHECK:   call void @do_with_swifterror(i64** {{.*}}swifterror{{.*}} [[ALLOCA]])
+
 declare { i8*, i8*, i8*, i8* } @llvm.coro.suspend.async.sl_p0i8p0i8p0i8p0i8s(i8*, i8*, ...)
 declare i8* @llvm.coro.prepare.async(i8*)
 declare token @llvm.coro.id.async(i32, i32, i32, i8*)