Skip to content

Commit 99aec59

Browse files
Merge pull request #8130 from aschwaighofer/coro_noinline
[Coro] [async] Disable inlining in async coroutine splitting
2 parents 50bdb94 + 41c7cea commit 99aec59

File tree

8 files changed

+225
-77
lines changed

8 files changed

+225
-77
lines changed

llvm/lib/Transforms/Coroutines/CoroSplit.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -208,17 +208,12 @@ static bool replaceCoroEndAsync(AnyCoroEndInst *End) {
208208
// Insert the return instruction.
209209
Builder.SetInsertPoint(End);
210210
Builder.CreateRetVoid();
211-
InlineFunctionInfo FnInfo;
212211

213212
// Remove the rest of the block, by splitting it into an unreachable block.
214213
auto *BB = End->getParent();
215214
BB->splitBasicBlock(End);
216215
BB->getTerminator()->eraseFromParent();
217216

218-
auto InlineRes = InlineFunction(*MustTailCall, FnInfo);
219-
assert(InlineRes.isSuccess() && "Expected inlining to succeed");
220-
(void)InlineRes;
221-
222217
// We have cleaned up the coro.end block above.
223218
return false;
224219
}
@@ -1794,13 +1789,8 @@ static void splitAsyncCoroutine(Function &F, coro::Shape &Shape,
17941789
SmallVector<Value *, 8> Args(Suspend->args());
17951790
auto FnArgs = ArrayRef<Value *>(Args).drop_front(
17961791
CoroSuspendAsyncInst::MustTailCallFuncArg + 1);
1797-
auto *TailCall =
1798-
coro::createMustTailCall(Suspend->getDebugLoc(), Fn, FnArgs, Builder);
1792+
coro::createMustTailCall(Suspend->getDebugLoc(), Fn, FnArgs, Builder);
17991793
Builder.CreateRetVoid();
1800-
InlineFunctionInfo FnInfo;
1801-
auto InlineRes = InlineFunction(*TailCall, FnInfo);
1802-
assert(InlineRes.isSuccess() && "Expected inlining to succeed");
1803-
(void)InlineRes;
18041794

18051795
// Replace the lvm.coro.async.resume intrisic call.
18061796
replaceAsyncResumeFunction(Suspend, Continuation);

llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-infinite-loop-bug.ll

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt)
2222
i32 128 ; Initial async context size without space for frame
2323
}>
2424

25-
define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
26-
tail call swiftcc void %fnPtr(ptr %async.ctxt)
25+
define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
26+
tail call swifttailcc void %fnPtr(ptr %async.ctxt)
2727
ret void
2828
}
2929

@@ -37,12 +37,12 @@ entry:
3737

3838
; The address of alloca escapes but the analysis based on lifetimes fails to see
3939
; that it can't localize this alloca.
40-
; CHECK: define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
40+
; CHECK: define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
4141
; CHECK: entry:
4242
; CHECK-NOT: ret
4343
; CHECK-NOT: [[ESCAPED_ADDR:%.*]] = alloca i64, align 8
4444
; CHECK: ret
45-
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
45+
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
4646
entry:
4747
%escaped_addr = alloca i64
4848

llvm/test/Transforms/Coroutines/coro-async-addr-lifetime-start-bug.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ declare void @my_other_async_function(ptr %async.ctxt)
2222
i32 128 ; Initial async context size without space for frame
2323
}>
2424

25-
define swiftcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
26-
tail call swiftcc void %fnPtr(ptr %async.ctxt)
25+
define swifttailcc void @my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
26+
tail call swifttailcc void %fnPtr(ptr %async.ctxt)
2727
ret void
2828
}
2929

@@ -36,7 +36,7 @@ entry:
3636
ret ptr %resume_ctxt
3737
}
3838

39-
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) {
39+
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) {
4040
entry:
4141
%escaped_addr = alloca i64
4242

llvm/test/Transforms/Coroutines/coro-async-dyn-align.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,20 @@ declare swiftcc void @asyncReturn(ptr)
3333
declare swiftcc void @asyncSuspend(ptr)
3434
declare {ptr} @llvm.coro.suspend.async(i32, ptr, ptr, ...)
3535

36-
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) {
37-
tail call swiftcc void %fnPtr(ptr %async.ctxt)
36+
define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt) alwaysinline {
37+
musttail call swifttailcc void %fnPtr(ptr %async.ctxt)
3838
ret void
3939
}
4040

41-
define ptr @__swift_async_resume_project_context(ptr %ctxt) {
41+
define ptr @__swift_async_resume_project_context(ptr %ctxt) alwaysinline {
4242
entry:
4343
%resume_ctxt = load ptr, ptr %ctxt, align 8
4444
ret ptr %resume_ctxt
4545
}
4646

4747

4848
; CHECK: %my_async_function.Frame = type { i64, [48 x i8], i64, i64, [16 x i8], ptr, i64, ptr }
49-
; CHECK: define swiftcc void @my_async_function
49+
; CHECK: define swifttailcc void @my_async_function
5050
; CHECK: [[T0:%.*]] = getelementptr inbounds %my_async_function.Frame, ptr %async.ctx.frameptr, i32 0, i32 3
5151
; CHECK: [[T1:%.*]] = ptrtoint ptr [[T0]] to i64
5252
; CHECK: [[T2:%.*]] = add i64 [[T1]], 31
@@ -60,7 +60,7 @@ entry:
6060
; CHECK: store i64 2, ptr [[T4]]
6161
; CHECK: store i64 3, ptr [[T9]]
6262

63-
define swiftcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine {
63+
define swifttailcc void @my_async_function(ptr swiftasync %async.ctxt) presplitcoroutine {
6464
entry:
6565
%tmp = alloca i64, align 8
6666
%tmp2 = alloca i64, align 16
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
; RUN: opt < %s -passes='default<O2>' -S | FileCheck --check-prefixes=CHECK %s
2+
; RUN: opt < %s -O0 -S | FileCheck --check-prefixes=CHECK-O0 %s
3+
4+
5+
; CHECK-NOT: llvm.coro.suspend.async
6+
; CHECK-O0-NOT: llvm.coro.suspend.async
7+
8+
; This test used to crash during updating the call graph in coro splitting.
9+
10+
target datalayout = "p:64:64:64"
11+
12+
%swift.async_func_pointer = type <{ i32, i32 }>
13+
14+
@"$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 }>
15+
@"$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 }>
16+
17+
define swifttailcc void @"$s1d3fooyySbYaF"(ptr swiftasync %0, i1 %1) {
18+
entry:
19+
%2 = alloca ptr, align 8
20+
%c.debug = alloca i1, align 8
21+
%3 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @"$s1d3fooyySbYaFTu")
22+
%4 = call ptr @llvm.coro.begin(token %3, ptr null)
23+
store ptr %0, ptr %2, align 8
24+
call void @llvm.memset.p0.i64(ptr align 8 %c.debug, i8 0, i64 1, i1 false)
25+
store i1 %1, ptr %c.debug, align 8
26+
call void asm sideeffect "", "r"(ptr %c.debug)
27+
%5 = load i32, ptr getelementptr inbounds (%swift.async_func_pointer, ptr @"$s1d3baryySbYaFTu", i32 0, i32 1), align 8
28+
%6 = zext i32 %5 to i64
29+
%7 = call swiftcc ptr @swift_task_alloc(i64 %6) #4
30+
call void @llvm.lifetime.start.p0(i64 -1, ptr %7)
31+
%8 = load ptr, ptr %2, align 8
32+
%9 = getelementptr inbounds <{ ptr, ptr }>, ptr %7, i32 0, i32 0
33+
store ptr %8, ptr %9, align 8
34+
%10 = call ptr @llvm.coro.async.resume()
35+
%11 = getelementptr inbounds <{ ptr, ptr }>, ptr %7, i32 0, i32 1
36+
store ptr %10, ptr %11, align 8
37+
%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)
38+
%13 = extractvalue { ptr } %12, 0
39+
%14 = call ptr @__swift_async_resume_project_context(ptr %13)
40+
store ptr %14, ptr %2, align 8
41+
call swiftcc void @swift_task_dealloc(ptr %7) #4
42+
call void @llvm.lifetime.end.p0(i64 -1, ptr %7)
43+
%15 = load ptr, ptr %2, align 8
44+
%16 = getelementptr inbounds <{ ptr, ptr }>, ptr %15, i32 0, i32 1
45+
%17 = load ptr, ptr %16, align 8
46+
%18 = load ptr, ptr %2, align 8
47+
%19 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %4, i1 false, ptr @"$s1d3fooyySbYaF.0.1", ptr %17, ptr %18)
48+
unreachable
49+
}
50+
51+
declare token @llvm.coro.id.async(i32, i32, i32, ptr) #1
52+
53+
declare void @llvm.trap() #2
54+
55+
declare ptr @llvm.coro.begin(token, ptr) #1
56+
57+
declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1 immarg) #3
58+
59+
define hidden swifttailcc void @"$s1d3baryySbYaF"(ptr swiftasync %0, i1 %1) {
60+
entry:
61+
%2 = alloca ptr, align 8
62+
%c.debug = alloca i1, align 8
63+
%3 = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @"$s1d3baryySbYaFTu")
64+
%4 = call ptr @llvm.coro.begin(token %3, ptr null)
65+
store ptr %0, ptr %2, align 8
66+
call void @llvm.memset.p0.i64(ptr align 8 %c.debug, i8 0, i64 1, i1 false)
67+
store i1 %1, ptr %c.debug, align 8
68+
call void asm sideeffect "", "r"(ptr %c.debug)
69+
br i1 %1, label %5, label %17
70+
71+
5: ; preds = %entry
72+
%6 = xor i1 %1, true
73+
%7 = load i32, ptr getelementptr inbounds (%swift.async_func_pointer, ptr @"$s1d3fooyySbYaFTu", i32 0, i32 1), align 8
74+
%8 = zext i32 %7 to i64
75+
%9 = call swiftcc ptr @swift_task_alloc(i64 %8) #4
76+
call void @llvm.lifetime.start.p0(i64 -1, ptr %9)
77+
%10 = load ptr, ptr %2, align 8
78+
%11 = getelementptr inbounds <{ ptr, ptr }>, ptr %9, i32 0, i32 0
79+
store ptr %10, ptr %11, align 8
80+
%12 = call ptr @llvm.coro.async.resume()
81+
%13 = getelementptr inbounds <{ ptr, ptr }>, ptr %9, i32 0, i32 1
82+
store ptr %12, ptr %13, align 8
83+
%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)
84+
%15 = extractvalue { ptr } %14, 0
85+
%16 = call ptr @__swift_async_resume_project_context(ptr %15)
86+
store ptr %16, ptr %2, align 8
87+
call swiftcc void @swift_task_dealloc(ptr %9) #4
88+
call void @llvm.lifetime.end.p0(i64 -1, ptr %9)
89+
br label %18
90+
91+
17: ; preds = %entry
92+
br label %18
93+
94+
18: ; preds = %5, %17
95+
%19 = load ptr, ptr %2, align 8
96+
%20 = getelementptr inbounds <{ ptr, ptr }>, ptr %19, i32 0, i32 1
97+
%21 = load ptr, ptr %20, align 8
98+
%22 = load ptr, ptr %2, align 8
99+
%23 = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %4, i1 false, ptr @"$s1d3baryySbYaF.0", ptr %21, ptr %22)
100+
unreachable
101+
}
102+
103+
declare swiftcc ptr @swift_task_alloc(i64) #4
104+
105+
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #5
106+
107+
declare ptr @llvm.coro.async.resume() #6
108+
109+
define linkonce_odr hidden ptr @__swift_async_resume_project_context(ptr %0) #7 {
110+
entry:
111+
%1 = load ptr, ptr %0, align 8
112+
%2 = call ptr @llvm.swift.async.context.addr()
113+
store ptr %1, ptr %2, align 8
114+
ret ptr %1
115+
}
116+
117+
declare ptr @llvm.swift.async.context.addr() #1
118+
119+
define internal swifttailcc void @"$s1d3fooyySbYaF.0"(ptr %0, ptr %1, i1 %2) #8 {
120+
entry:
121+
musttail call swifttailcc void %0(ptr swiftasync %1, i1 %2)
122+
ret void
123+
}
124+
125+
declare { ptr } @llvm.coro.suspend.async.sl_p0s(i32, ptr, ptr, ...) #6
126+
127+
declare swiftcc void @swift_task_dealloc(ptr) #4
128+
129+
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #5
130+
131+
define internal swifttailcc void @"$s1d3fooyySbYaF.0.1"(ptr %0, ptr %1) #8 {
132+
entry:
133+
musttail call swifttailcc void %0(ptr swiftasync %1)
134+
ret void
135+
}
136+
137+
declare i1 @llvm.coro.end.async(ptr, i1, ...) #1
138+
139+
define internal swifttailcc void @"$s1d3baryySbYaF.0"(ptr %0, ptr %1) #8 {
140+
entry:
141+
musttail call swifttailcc void %0(ptr swiftasync %1)
142+
ret void
143+
}
144+
145+
define internal swifttailcc void @"$s1d3baryySbYaF.0.2"(ptr %0, ptr %1, i1 %2) #8 {
146+
entry:
147+
musttail call swifttailcc void %0(ptr swiftasync %1, i1 %2)
148+
ret void
149+
}
150+
151+
attributes #1 = { nounwind }
152+
attributes #2 = { cold noreturn nounwind }
153+
attributes #3 = { nocallback nofree nounwind willreturn}
154+
attributes #4 = { nounwind }
155+
attributes #5 = { nocallback nofree nosync nounwind willreturn }
156+
attributes #6 = { nomerge nounwind }
157+
attributes #7 = { alwaysinline nounwind }
158+
attributes #8 = { alwaysinline nounwind }

llvm/test/Transforms/Coroutines/coro-async-unreachable.ll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ target datalayout = "p:64:64:64"
1313
declare void @my_other_async_function(ptr %async.ctxt)
1414

1515
; Function that implements the dispatch to the callee function.
16-
define swiftcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) {
17-
tail call swiftcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
16+
define swifttailcc void @my_async_function.my_other_async_function_fp.apply(ptr %fnPtr, ptr %async.ctxt, ptr %task, ptr %actor) alwaysinline {
17+
musttail call swifttailcc void %fnPtr(ptr %async.ctxt, ptr %task, ptr %actor)
1818
ret void
1919
}
2020

@@ -38,7 +38,7 @@ entry:
3838
i32 128 ; Initial async context size without space for frame
3939
}>
4040

41-
define swiftcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor) {
41+
define swifttailcc void @unreachable(ptr %async.ctxt, ptr %task, ptr %actor) {
4242
entry:
4343
%tmp = alloca { i64, i64 }, align 8
4444
%proj.1 = getelementptr inbounds { i64, i64 }, ptr %tmp, i64 0, i32 0
@@ -77,11 +77,11 @@ entry:
7777
unreachable
7878
}
7979

80-
; CHECK: define swiftcc void @unreachable
80+
; CHECK: define swifttailcc void @unreachable
8181
; CHECK-NOT: @llvm.coro.suspend.async
8282
; CHECK: return
8383

84-
; CHECK: define internal swiftcc void @unreachable.resume.0
84+
; CHECK: define internal swifttailcc void @unreachable.resume.0
8585
; CHECK: unreachable
8686

8787
declare ptr @llvm.coro.prepare.async(ptr)

0 commit comments

Comments
 (0)