diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index a552b3ac20085c..aed4cd027d0338 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -208,17 +208,12 @@ static bool replaceCoroEndAsync(AnyCoroEndInst *End) { // Insert the return instruction. Builder.SetInsertPoint(End); Builder.CreateRetVoid(); - InlineFunctionInfo FnInfo; // Remove the rest of the block, by splitting it into an unreachable block. auto *BB = End->getParent(); BB->splitBasicBlock(End); BB->getTerminator()->eraseFromParent(); - auto InlineRes = InlineFunction(*MustTailCall, FnInfo); - assert(InlineRes.isSuccess() && "Expected inlining to succeed"); - (void)InlineRes; - // We have cleaned up the coro.end block above. return false; } @@ -1842,13 +1837,8 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape, SmallVector Args(Suspend->args()); auto FnArgs = ArrayRef(Args).drop_front( CoroSuspendAsyncInst::MustTailCallFuncArg + 1); - auto *TailCall = - coro::createMustTailCall(Suspend->getDebugLoc(), Fn, FnArgs, Builder); + coro::createMustTailCall(Suspend->getDebugLoc(), Fn, FnArgs, Builder); Builder.CreateRetVoid(); - InlineFunctionInfo FnInfo; - auto InlineRes = InlineFunction(*TailCall, FnInfo); - assert(InlineRes.isSuccess() && "Expected inlining to succeed"); - (void)InlineRes; // Replace the lvm.coro.async.resume intrisic call. replaceAsyncResumeFunction(Suspend, Continuation); diff --git a/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll b/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll index 07b3bd8fa94ac0..4960709932948c 100644 --- a/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll +++ b/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll @@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt) i32 128 ; Initial async context size without space for frame }> -define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) { - tail call swiftcc void %fnPtr(ptr %async.ctxt) +define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline { + tail call swifttailcc void %fnPtr(ptr %async.ctxt) ret void } @@ -37,12 +37,12 @@ entry: ; The address of alloca escapes but the analysis based on lifetimes fails to see ; that it can't localize this alloca. -; CHECK: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) { +; CHECK: define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) { ; CHECK: entry: ; CHECK-NOT: ret ; CHECK-NOT: [[ESCAPED_ADDR:%.*]] = alloca i64, align 8 ; CHECK: ret -define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) { +define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) { entry: %escaped_addr = alloca i64 diff --git a/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll b/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll index 2306b72a0055fe..42377285f77ca9 100644 --- a/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll +++ b/llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll @@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt) i32 128 ; Initial async context size without space for frame }> -define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) { - tail call swiftcc void %fnPtr(ptr %async.ctxt) +define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline { + tail call swifttailcc void %fnPtr(ptr %async.ctxt) ret void } @@ -36,7 +36,7 @@ entry: ret ptr %resume_ctxt } -define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) { +define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) { entry: %escaped_addr = alloca i64 diff --git a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll index 040c9881c1ab30..567977ea1476d7 100644 --- a/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll +++ b/llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll @@ -33,12 +33,12 @@ declare swiftcc void @asyncReturn(ptr) declare swiftcc void @asyncSuspend(ptr) declare {ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...) -define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) { - tail call swiftcc void %fnPtr(ptr %async.ctxt) +define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline { + musttail call swifttailcc void %fnPtr(ptr %async.ctxt) ret void } -define ptr @__swift_async_resume_project_context(ptr %ctxt) { +define ptr @__swift_async_resume_project_context(ptr %ctxt) alwaysinline { entry: %resume_ctxt = load ptr, ptr %ctxt, align 8 ret ptr %resume_ctxt @@ -46,7 +46,7 @@ entry: ; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr } -; CHECK: define swiftcc void @my_async_function +; CHECK: define swifttailcc void @my_async_function ; CHECK: [[T0:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr %async.ctx.frameptr, i32 0, i32 3 ; CHECK: [[T1:%.*]] = ptrtoint ptr [[T0]] to i64 ; CHECK: [[T2:%.*]] = add i64 [[T1]], 31 @@ -60,7 +60,7 @@ entry: ; CHECK: store i64 2, ptr [[T4]] ; CHECK: store i64 3, ptr [[T9]] -define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine { +define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine { entry: %tmp = alloca i64, align 8 %tmp2 = alloca i64, align 16 diff --git a/llvm/test/Transforms/Coroutines/coro-async-mutal-recursive.ll b/llvm/test/Transforms/Coroutines/coro-async-mutal-recursive.ll new file mode 100644 index 00000000000000..4931fe998daa60 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-async-mutal-recursive.ll @@ -0,0 +1,158 @@ +; RUN: opt < %s -passes='default' -S | FileCheck --check-prefixes=CHECK %s +; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s + + +; CHECK-NOT: llvm.coro.suspend.async +; CHECK-O0-NOT: llvm.coro.suspend.async + +; This test used to crash during updating the call graph in coro splitting. + +target datalayout = "p:64:64:64" + +%swift.async_func_pointer = type <{ i32, i32 }> + +@"$s1d3fooyySbYaFTu" = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"$s1d3fooyySbYaF" to i64), i64 ptrtoint (ptr @"$s1d3fooyySbYaFTu" to i64)) to i32), i32 16 }> +@"$s1d3baryySbYaFTu" = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"$s1d3baryySbYaF" to i64), i64 ptrtoint (ptr @"$s1d3baryySbYaFTu" to i64)) to i32), i32 16 }> + +define swifttailcc void @"$s1d3fooyySbYaF"(ptr swiftasync %0, i1 %1) { +entry: + %2 = alloca ptr, align 8 + %c.debug = alloca i1, align 8 + %3 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @"$s1d3fooyySbYaFTu") + %4 = call ptr @llvm.coro.begin(token %3, ptr null) + store ptr %0, ptr %2, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %c.debug, i8 0, i64 1, i1 false) + store i1 %1, ptr %c.debug, align 8 + call void asm sideeffect "", "r"(ptr %c.debug) + %5 = load i32, ptr getelementptr inbounds (%swift.async_func_pointer, ptr @"$s1d3baryySbYaFTu", i32 0, i32 1), align 8 + %6 = zext i32 %5 to i64 + %7 = call swiftcc ptr @swift_task_alloc(i64 %6) #4 + call void @llvm.lifetime.start.p0(i64 -1, ptr %7) + %8 = load ptr, ptr %2, align 8 + %9 = getelementptr inbounds <{ ptr, ptr }>, ptr %7, i32 0, i32 0 + store ptr %8, ptr %9, align 8 + %10 = call ptr @llvm.coro.async.resume() + %11 = getelementptr inbounds <{ ptr, ptr }>, ptr %7, i32 0, i32 1 + store ptr %10, ptr %11, align 8 + %12 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %10, ptr @__swift_async_resume_project_context, ptr @"$s1d3fooyySbYaF.0", ptr @"$s1d3baryySbYaF", ptr %7, i1 %1) + %13 = extractvalue { ptr } %12, 0 + %14 = call ptr @__swift_async_resume_project_context(ptr %13) + store ptr %14, ptr %2, align 8 + call swiftcc void @swift_task_dealloc(ptr %7) #4 + call void @llvm.lifetime.end.p0(i64 -1, ptr %7) + %15 = load ptr, ptr %2, align 8 + %16 = getelementptr inbounds <{ ptr, ptr }>, ptr %15, i32 0, i32 1 + %17 = load ptr, ptr %16, align 8 + %18 = load ptr, ptr %2, align 8 + %19 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %4, i1 false, ptr @"$s1d3fooyySbYaF.0.1", ptr %17, ptr %18) + unreachable +} + +declare token @llvm.coro.id.async(i32, i32, i32, ptr) #1 + +declare void @llvm.trap() #2 + +declare ptr @llvm.coro.begin(token, ptr) #1 + +declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1 immarg) #3 + +define hidden swifttailcc void @"$s1d3baryySbYaF"(ptr swiftasync %0, i1 %1) { +entry: + %2 = alloca ptr, align 8 + %c.debug = alloca i1, align 8 + %3 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @"$s1d3baryySbYaFTu") + %4 = call ptr @llvm.coro.begin(token %3, ptr null) + store ptr %0, ptr %2, align 8 + call void @llvm.memset.p0.i64(ptr align 8 %c.debug, i8 0, i64 1, i1 false) + store i1 %1, ptr %c.debug, align 8 + call void asm sideeffect "", "r"(ptr %c.debug) + br i1 %1, label %5, label %17 + +5: ; preds = %entry + %6 = xor i1 %1, true + %7 = load i32, ptr getelementptr inbounds (%swift.async_func_pointer, ptr @"$s1d3fooyySbYaFTu", i32 0, i32 1), align 8 + %8 = zext i32 %7 to i64 + %9 = call swiftcc ptr @swift_task_alloc(i64 %8) #4 + call void @llvm.lifetime.start.p0(i64 -1, ptr %9) + %10 = load ptr, ptr %2, align 8 + %11 = getelementptr inbounds <{ ptr, ptr }>, ptr %9, i32 0, i32 0 + store ptr %10, ptr %11, align 8 + %12 = call ptr @llvm.coro.async.resume() + %13 = getelementptr inbounds <{ ptr, ptr }>, ptr %9, i32 0, i32 1 + store ptr %12, ptr %13, align 8 + %14 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0s(i32 0, ptr %12, ptr @__swift_async_resume_project_context, ptr @"$s1d3baryySbYaF.0.2", ptr @"$s1d3fooyySbYaF", ptr %9, i1 %6) + %15 = extractvalue { ptr } %14, 0 + %16 = call ptr @__swift_async_resume_project_context(ptr %15) + store ptr %16, ptr %2, align 8 + call swiftcc void @swift_task_dealloc(ptr %9) #4 + call void @llvm.lifetime.end.p0(i64 -1, ptr %9) + br label %18 + +17: ; preds = %entry + br label %18 + +18: ; preds = %5, %17 + %19 = load ptr, ptr %2, align 8 + %20 = getelementptr inbounds <{ ptr, ptr }>, ptr %19, i32 0, i32 1 + %21 = load ptr, ptr %20, align 8 + %22 = load ptr, ptr %2, align 8 + %23 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %4, i1 false, ptr @"$s1d3baryySbYaF.0", ptr %21, ptr %22) + unreachable +} + +declare swiftcc ptr @swift_task_alloc(i64) #4 + +declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #5 + +declare ptr @llvm.coro.async.resume() #6 + +define linkonce_odr hidden ptr @__swift_async_resume_project_context(ptr %0) #7 { +entry: + %1 = load ptr, ptr %0, align 8 + %2 = call ptr @llvm.swift.async.context.addr() + store ptr %1, ptr %2, align 8 + ret ptr %1 +} + +declare ptr @llvm.swift.async.context.addr() #1 + +define internal swifttailcc void @"$s1d3fooyySbYaF.0"(ptr %0, ptr %1, i1 %2) #8 { +entry: + musttail call swifttailcc void %0(ptr swiftasync %1, i1 %2) + ret void +} + +declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #6 + +declare swiftcc void @swift_task_dealloc(ptr) #4 + +declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #5 + +define internal swifttailcc void @"$s1d3fooyySbYaF.0.1"(ptr %0, ptr %1) #8 { +entry: + musttail call swifttailcc void %0(ptr swiftasync %1) + ret void +} + +declare i1 @llvm.coro.end.async(ptr, i1, ...) #1 + +define internal swifttailcc void @"$s1d3baryySbYaF.0"(ptr %0, ptr %1) #8 { +entry: + musttail call swifttailcc void %0(ptr swiftasync %1) + ret void +} + +define internal swifttailcc void @"$s1d3baryySbYaF.0.2"(ptr %0, ptr %1, i1 %2) #8 { +entry: + musttail call swifttailcc void %0(ptr swiftasync %1, i1 %2) + ret void +} + +attributes #1 = { nounwind } +attributes #2 = { cold noreturn nounwind } +attributes #3 = { nocallback nofree nounwind willreturn} +attributes #4 = { nounwind } +attributes #5 = { nocallback nofree nosync nounwind willreturn } +attributes #6 = { nomerge nounwind } +attributes #7 = { alwaysinline nounwind } +attributes #8 = { alwaysinline nounwind } diff --git a/llvm/test/Transforms/Coroutines/coro-async-unreachable.ll b/llvm/test/Transforms/Coroutines/coro-async-unreachable.ll index 79ef8939b0eccf..ed4f526b8ed986 100644 --- a/llvm/test/Transforms/Coroutines/coro-async-unreachable.ll +++ b/llvm/test/Transforms/Coroutines/coro-async-unreachable.ll @@ -13,8 +13,8 @@ target datalayout = "p:64:64:64" declare void @my_other_async_function(ptr %async.ctxt) ; Function that implements the dispatch to the callee function. -define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) { - tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) +define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) alwaysinline { + musttail call swifttailcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) ret void } @@ -38,7 +38,7 @@ entry: i32 128 ; Initial async context size without space for frame }> -define swiftcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor) { +define swifttailcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor) { entry: %tmp = alloca { i64, i64 }, align 8 %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 @@ -77,11 +77,11 @@ entry: unreachable } -; CHECK: define swiftcc void @unreachable +; CHECK: define swifttailcc void @unreachable ; CHECK-NOT: @llvm.coro.suspend.async ; CHECK: return -; CHECK: define internal swiftcc void @unreachable.resume.0 +; CHECK: define internal swifttailcc void @unreachable.resume.0 ; CHECK: unreachable declare ptr @llvm.coro.prepare.async(ptr) diff --git a/llvm/test/Transforms/Coroutines/coro-async.ll b/llvm/test/Transforms/Coroutines/coro-async.ll index 3740c3d1d83871..8ead304fe29887 100644 --- a/llvm/test/Transforms/Coroutines/coro-async.ll +++ b/llvm/test/Transforms/Coroutines/coro-async.ll @@ -37,28 +37,28 @@ declare void @my_other_async_function(ptr %async.ctxt) }> ; Function that implements the dispatch to the callee function. -define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) { - tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) +define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) alwaysinline { + musttail call swifttailcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) ret void } declare void @some_user(i64) declare void @some_may_write(ptr) -define ptr @__swift_async_resume_project_context(ptr %ctxt) { +define ptr @__swift_async_resume_project_context(ptr %ctxt) alwaysinline { entry: %resume_ctxt = load ptr, ptr %ctxt, align 8 ret ptr %resume_ctxt } -define ptr @resume_context_projection(ptr %ctxt) { +define ptr @resume_context_projection(ptr %ctxt) alwaysinline { entry: %resume_ctxt = load ptr, ptr %ctxt, align 8 ret ptr %resume_ctxt } -define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 { +define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine !dbg !1 { entry: %tmp = alloca { i64, i64 }, align 8 %vector = alloca <4 x double>, align 16 @@ -100,7 +100,7 @@ entry: %val.2 = load i64, ptr %proj.2 call void @some_user(i64 %val.2) store <4 x double> %vector_spill, ptr %vector, align 16 - tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + tail call swifttailcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } @@ -116,8 +116,8 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) { ; CHECK: @my_async_function_pa_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 } ; CHECK: @my_async_function2_fp = constant <{ i32, i32 }> <{ {{.*}}, i32 176 } -; CHECK-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) -; CHECK-O0-LABEL: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) +; CHECK-LABEL: define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) +; CHECK-O0-LABEL: define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) ; CHECK-SAME: !dbg ![[SP1:[0-9]+]] { ; CHECK: coro.return: ; CHECK: [[FRAMEPTR:%.*]] = getelementptr inbounds i8, ptr %async.ctxt, i64 128 @@ -139,12 +139,12 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) { ; CHECK-O0: [[VECTOR_SPILL:%.*]] = load <4 x double>, ptr {{.*}} ; CHECK-O0: [[VECTOR_SPILL_ADDR:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr {{.*}}, i32 0, i32 1 ; CHECK-O0: store <4 x double> [[VECTOR_SPILL]], ptr [[VECTOR_SPILL_ADDR]], align 16 -; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) +; CHECK: tail call swifttailcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) ; CHECK: ret void ; CHECK: } -; CHECK-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr nocapture readonly swiftasync %0, ptr %1, ptr nocapture readnone %2) -; CHECK-O0-LABEL: define internal swiftcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2) +; CHECK-LABEL: define internal swifttailcc void @my_async_functionTQ0_(ptr nocapture readonly swiftasync %0, ptr %1, ptr nocapture readnone %2) +; CHECK-O0-LABEL: define internal swifttailcc void @my_async_functionTQ0_(ptr swiftasync %0, ptr %1, ptr %2) ; CHECK-SAME: !dbg ![[SP2:[0-9]+]] { ; CHECK: entryresume.0: ; CHECK: [[CALLER_CONTEXT:%.*]] = load ptr, ptr %0 @@ -163,7 +163,7 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) { ; CHECK: tail call void @some_user(i64 [[VAL1]]) ; CHECK: [[VAL2:%.*]] = load i64, ptr [[ALLOCA_PRJ2]] ; CHECK: tail call void @some_user(i64 [[VAL2]]) -; CHECK: tail call swiftcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]]) +; CHECK: tail call swifttailcc void @asyncReturn(ptr [[ASYNC_CTXT_RELOAD]], ptr %1, ptr [[ACTOR_RELOAD]]) ; CHECK: ret void ; CHECK: } @@ -177,7 +177,7 @@ define void @my_async_function_pa(ptr %ctxt, ptr %task, ptr %actor) { i32 128 ; Initial async context size without space for frame }> -define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 { +define swifttailcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) presplitcoroutine "frame-pointer"="all" !dbg !6 { entry: %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 2, ptr @my_async_function2_fp) @@ -210,12 +210,12 @@ entry: call void @llvm.coro.async.context.dealloc(ptr %callee_context) %continuation_actor_arg = extractvalue {ptr, ptr, ptr} %res.2, 1 - tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %continuation_actor_arg) + tail call swifttailcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %continuation_actor_arg) call i1 @llvm.coro.end(ptr %hdl, i1 0, token none) unreachable } -; CHECK-LABEL: define swiftcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) +; CHECK-LABEL: define swifttailcc void @my_async_function2(ptr %task, ptr %actor, ptr %async.ctxt) ; CHECK-SAME: #[[FRAMEPOINTER:[0-9]+]] ; CHECK-SAME: !dbg ![[SP3:[0-9]+]] ; CHECK: store ptr %async.ctxt, @@ -225,22 +225,22 @@ entry: ; CHECK: store ptr [[CALLEE_CTXT]], ; CHECK: store ptr @my_async_function2.resume.0, ; CHECK: store ptr %async.ctxt, -; CHECK: tail call swiftcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) +; CHECK: tail call swifttailcc void @asyncSuspend(ptr nonnull [[CALLEE_CTXT]], ptr %task, ptr %actor) ; CHECK: ret void -; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.0(ptr %0, ptr nocapture readnone %1, ptr nocapture readonly %2) +; CHECK-LABEL: define internal swifttailcc void @my_async_function2.resume.0(ptr %0, ptr nocapture readnone %1, ptr nocapture readonly %2) ; CHECK-SAME: #[[FRAMEPOINTER]] ; CHECK-SAME: !dbg ![[SP4:[0-9]+]] ; CHECK: [[CALLEE_CTXT:%.*]] = load ptr, ptr %2 ; CHECK: [[CALLEE_CTXT_SPILL_ADDR:%.*]] = getelementptr inbounds i8, ptr [[CALLEE_CTXT]], i64 152 ; CHECK: store ptr @my_async_function2.resume.1, ; CHECK: [[CALLLE_CTXT_RELOAD:%.*]] = load ptr, ptr [[CALLEE_CTXT_SPILL_ADDR]] -; CHECK: tail call swiftcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]] +; CHECK: tail call swifttailcc void @asyncSuspend(ptr [[CALLEE_CTXT_RELOAD]] ; CHECK: ret void -; CHECK-LABEL: define internal swiftcc void @my_async_function2.resume.1(ptr nocapture readonly %0, ptr %1, ptr nocapture readnone %2) +; CHECK-LABEL: define internal swifttailcc void @my_async_function2.resume.1(ptr nocapture readonly %0, ptr %1, ptr nocapture readnone %2) ; CHECK-SAME: #[[FRAMEPOINTER]] -; CHECK: tail call swiftcc void @asyncReturn({{.*}}%1) +; CHECK: tail call swifttailcc void @asyncReturn({{.*}}%1) ; CHECK: ret void define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) { @@ -252,7 +252,7 @@ define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) { ; CHECK-LABEL: define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) ; CHECK: store ptr @my_async_functionTQ0_ ; CHECK: store ptr %ctxt -; CHECK: tail call swiftcc void @asyncSuspend +; CHECK: tail call swifttailcc void @asyncSuspend ; CHECK: ret void @dont_crash_on_cf_fp = constant <{ i32, i32 }> @@ -266,7 +266,7 @@ define swiftcc void @top_level_caller(ptr %ctxt, ptr %task, ptr %actor) { }> -define swiftcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) { +define swifttailcc void @dont_crash_on_cf_dispatch(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) alwaysinline { %isNull = icmp eq ptr %task, null br i1 %isNull, label %is_null, label %is_not_null @@ -274,11 +274,11 @@ is_null: ret void is_not_null: - tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) + musttail call swifttailcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor) ret void } -define swiftcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { +define swifttailcc void @dont_crash_on_cf(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, ptr @dont_crash_on_cf_fp) @@ -296,7 +296,7 @@ entry: call void @llvm.coro.async.context.dealloc(ptr %callee_context) %continuation_task_arg = extractvalue {ptr, ptr, ptr} %res, 1 - tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + tail call swifttailcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } @@ -311,12 +311,12 @@ entry: i32 128 ; Initial async context size without space for frame }> -define swiftcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) { - musttail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor) +define swifttailcc void @must_tail_call_return(ptr %async.ctxt, ptr %task, ptr %actor) alwaysinline { + musttail call swifttailcc void @asyncReturn(ptr %async.ctxt, ptr %task, ptr %actor) ret void } -define swiftcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { +define swifttailcc void @multiple_coro_end_async(ptr %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %id = call token @llvm.coro.id.async(i32 128, i32 16, i32 0, ptr @dont_crash_on_cf_fp) @@ -350,8 +350,8 @@ is_not_equal: unreachable } -; CHECK-LABEL: define internal swiftcc void @multiple_coro_end_async.resume.0( -; CHECK: musttail call swiftcc void @asyncReturn( +; CHECK-LABEL: define internal swifttailcc void @multiple_coro_end_async.resume.0( +; CHECK: musttail call swifttailcc void @asyncReturn( ; CHECK: ret void @polymorphic_suspend_return_fp = constant <{ i32, i32 }> @@ -364,7 +364,7 @@ is_not_equal: i32 64 ; Initial async context size without space for frame }> -define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { +define swifttailcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) presplitcoroutine { entry: %tmp = alloca { i64, i64 }, align 8 %proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0 @@ -405,13 +405,13 @@ entry: %val.2 = load i64, ptr %proj.2 call void @some_user(i64 %val.2) - tail call swiftcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) + tail call swifttailcc void @asyncReturn(ptr %async.ctxt, ptr %continuation_task_arg, ptr %actor) call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 0) unreachable } -; CHECK-LABEL: define swiftcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) -; CHECK-LABEL: define internal swiftcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3) +; CHECK-LABEL: define swifttailcc void @polymorphic_suspend_return(ptr swiftasync %async.ctxt, ptr %task, ptr %actor) +; CHECK-LABEL: define internal swifttailcc void @polymorphic_suspend_return.resume.0(ptr {{.*}}swiftasync{{.*}} %0, ptr {{.*}}swiftself{{.*}} %1, ptr {{.*}}%2, ptr {{.*}}%3) ; CHECK: } @no_coro_suspend_fp = constant <{ i32, i32 }> @@ -481,7 +481,7 @@ entry: declare void @crash() declare void @use(ptr) -define swiftcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine { +define swifttailcc void @undefined_coro_async_resume(ptr %async.ctx) presplitcoroutine { entry: %id = call token @llvm.coro.id.async(i32 24, i32 16, i32 0, ptr @undefined_coro_async_resume_fp) %hdl = call ptr @llvm.coro.begin(token %id, ptr null) @@ -491,7 +491,7 @@ entry: %unused = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %hdl, i1 false) unreachable } -; CHECK-LABEL: define swiftcc void @undefined_coro_async_resume +; CHECK-LABEL: define swifttailcc void @undefined_coro_async_resume ; CHECK-NOT: @llvm.coro.async.resume ; CHECK: call void @use(ptr null) ; CHECK: ret @@ -505,8 +505,8 @@ declare i1 @llvm.coro.end(ptr, i1, token) declare {ptr, ptr, ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...) declare ptr @llvm.coro.async.context.alloc(ptr, ptr) declare void @llvm.coro.async.context.dealloc(ptr) -declare swiftcc void @asyncReturn(ptr, ptr, ptr) -declare swiftcc void @asyncSuspend(ptr, ptr, ptr) +declare swifttailcc void @asyncReturn(ptr, ptr, ptr) +declare swifttailcc void @asyncSuspend(ptr, ptr, ptr) declare ptr @llvm.coro.async.resume() declare void @llvm.coro.async.size.replace(ptr, ptr) declare ptr @hide(ptr) diff --git a/llvm/test/Transforms/Coroutines/swift-async-dbg.ll b/llvm/test/Transforms/Coroutines/swift-async-dbg.ll index 74edf7a3f3a540..a78bcdf0ddee23 100644 --- a/llvm/test/Transforms/Coroutines/swift-async-dbg.ll +++ b/llvm/test/Transforms/Coroutines/swift-async-dbg.ll @@ -1,13 +1,13 @@ -; RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s -; RUN: opt -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s -; RUN: opt -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY -; RUN: opt -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY +; RUN: opt -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s +; RUN: opt -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s +; RUN: opt -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s --check-prefix=NOENTRY +; RUN: opt -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s --check-prefix=NOENTRY ;; Replicate those tests with non-instruction debug markers. -; RUN: opt --try-experimental-debuginfo-iterators -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s -; RUN: opt --try-experimental-debuginfo-iterators -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s -; RUN: opt --try-experimental-debuginfo-iterators -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY -; RUN: opt --try-experimental-debuginfo-iterators -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg)' -o - | FileCheck %s --check-prefix=NOENTRY +; RUN: opt --try-experimental-debuginfo-iterators -mtriple='arm64-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s +; RUN: opt --try-experimental-debuginfo-iterators -mtriple='x86_64' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s +; RUN: opt --try-experimental-debuginfo-iterators -mtriple='i386-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s --check-prefix=NOENTRY +; RUN: opt --try-experimental-debuginfo-iterators -mtriple='armv7-' %s -S -passes='module(coro-early),cgscc(coro-split,simplifycfg),always-inline' -o - | FileCheck %s --check-prefix=NOENTRY ; NOENTRY-NOT: OP_llvm_entry_value @@ -93,29 +93,29 @@ define swifttailcc void @coroutineA(ptr swiftasync %arg) !dbg !48 { @coroutineBTu = global <{i32, i32}> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"coroutineB" to i64), i64 ptrtoint (ptr @"coroutineBTu" to i64)) to i32), i32 16 }>, align 8 @coroutineATu = global <{i32, i32}> <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @"coroutineA" to i64), i64 ptrtoint (ptr @"coroutineATu" to i64)) to i32), i32 16 }>, align 8 -define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) !dbg !64 { +define weak_odr hidden ptr @__swift_async_resume_get_context(ptr %arg) alwaysinline !dbg !64 { ret ptr %arg, !dbg !65 } -define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) !dbg !66 { +define hidden swifttailcc void @coroutineA.1(ptr %arg, i64 %arg1, i64 %arg2, ptr %arg3) alwaysinline !dbg !66 { musttail call swifttailcc void @swift_task_switch(ptr swiftasync %arg3, ptr %arg, i64 %arg1, i64 %arg2), !dbg !67 ret void, !dbg !67 } -define weak_odr hidden ptr @__swift_async_resume_project_context(ptr %arg) !dbg !68 { +define weak_odr hidden ptr @__swift_async_resume_project_context(ptr %arg) alwaysinline !dbg !68 { %i1 = load ptr, ptr %arg, align 8, !dbg !69 %i2 = call ptr @llvm.swift.async.context.addr(), !dbg !69 store ptr %i1, ptr %i2, align 8, !dbg !69 ret ptr %i1, !dbg !69 } -define hidden swifttailcc void @coroutineA.0(ptr %arg, ptr %arg1) !dbg !70 { +define hidden swifttailcc void @coroutineA.0(ptr %arg, ptr %arg1) alwaysinline !dbg !70 { musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !71 ret void, !dbg !71 } -define hidden swifttailcc void @coroutineA.0.1(ptr %arg, ptr %arg1) !dbg !72 { +define hidden swifttailcc void @coroutineA.0.1(ptr %arg, ptr %arg1) alwaysinline !dbg !72 { musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !73 ret void, !dbg !73 } -define swifttailcc void @coroutineB(ptr swiftasync %arg) !dbg !37 { +define swifttailcc void @coroutineB(ptr swiftasync %arg) alwaysinline !dbg !37 { %i2 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr nonnull @coroutineBTu) %i3 = call ptr @llvm.coro.begin(token %i2, ptr null) %i6 = getelementptr inbounds <{ ptr, ptr }>, ptr %arg, i64 0, i32 1, !dbg !42 @@ -123,7 +123,7 @@ define swifttailcc void @coroutineB(ptr swiftasync %arg) !dbg !37 { %i10 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %i3, i1 false, ptr nonnull @coroutineB.0, ptr %i712, ptr %arg), !dbg !42 unreachable, !dbg !42 } -define hidden swifttailcc void @coroutineB.0(ptr %arg, ptr %arg1) !dbg !44 { +define hidden swifttailcc void @coroutineB.0(ptr %arg, ptr %arg1) alwaysinline !dbg !44 { musttail call swifttailcc void %arg(ptr swiftasync %arg1), !dbg !47 ret void, !dbg !47 }