xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-split-musttail1.ll (revision 3bb39690d729d85cd93c9dd6e750d82d6f367541)
1; Tests that coro-split will convert coro.await.suspend.handle to a musttail call.
2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s
3; RUN: opt < %s -passes='pgo-instr-gen,cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck --check-prefixes=CHECK %s
4
5define void @f() #0 {
6entry:
7  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
8  %alloc = call ptr @malloc(i64 16) #3
9  %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
10
11  %save = call token @llvm.coro.save(ptr null)
12  %addr1 = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
13  call fastcc void %addr1(ptr null)
14
15  %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
16  switch i8 %suspend, label %exit [
17    i8 0, label %await.suspend
18    i8 1, label %exit
19  ]
20await.suspend:
21  %save2 = call token @llvm.coro.save(ptr null)
22  %br0 = call i8 @switch_result()
23  switch i8 %br0, label %unreach [
24    i8 0, label %await.resume3
25    i8 1, label %await.resume1
26    i8 2, label %await.resume2
27  ]
28await.resume1:
29  %hdl = call ptr @g()
30  call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl, ptr @await_suspend_function)
31  br label %final.suspend
32await.resume2:
33  %hdl2 = call ptr @h()
34  call void @llvm.coro.await.suspend.handle(ptr null, ptr %hdl2, ptr @await_suspend_function)
35  br label %final.suspend
36await.resume3:
37  call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_suspend_function)
38  br label %final.suspend
39final.suspend:
40  %suspend2 = call i8 @llvm.coro.suspend(token %save2, i1 false)
41  switch i8 %suspend2, label %exit [
42    i8 0, label %pre.exit
43    i8 1, label %exit
44  ]
45pre.exit:
46  br label %exit
47exit:
48  call i1 @llvm.coro.end(ptr null, i1 false, token none)
49  ret void
50unreach:
51  unreachable
52}
53
54; Verify that in the initial function resume is not marked with musttail.
55; CHECK-LABEL: @f(
56; CHECK: %[[addr1:.+]] = call ptr @llvm.coro.subfn.addr(ptr null, i8 0)
57; CHECK-NOT: musttail call fastcc void %[[addr1]](ptr null)
58
59; Verify that in the resume part resume call is marked with musttail.
60; CHECK-LABEL: @f.resume(
61; CHECK: %[[hdl:.+]] = call ptr @g()
62; CHECK-NEXT: call ptr @await_suspend_function
63; CHECK-NEXT: %[[addr2:.+]] = call ptr @llvm.coro.subfn.addr
64; CHECK-NEXT: musttail call fastcc void %[[addr2]]
65; CHECK-NEXT: ret void
66; CHECK: %[[hdl2:.+]] = call ptr @h()
67; CHECK-NEXT: call ptr @await_suspend_function
68; CHECK-NEXT: %[[addr3:.+]] = call ptr @llvm.coro.subfn.addr
69; CHECK-NEXT: musttail call fastcc void %[[addr3]]
70; CHECK-NEXT: ret void
71; CHECK: call ptr @await_suspend_function
72; CHECK: %[[addr4:.+]] = call ptr @llvm.coro.subfn.addr
73; CHECK-NEXT: musttail call fastcc void %[[addr4]]
74; CHECK-NEXT: ret void
75
76
77
78declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #1
79declare i1 @llvm.coro.alloc(token) #2
80declare i64 @llvm.coro.size.i64() #3
81declare ptr @llvm.coro.begin(token, ptr writeonly) #2
82declare token @llvm.coro.save(ptr) #2
83declare ptr @llvm.coro.frame() #3
84declare i8 @llvm.coro.suspend(token, i1) #2
85declare ptr @llvm.coro.free(token, ptr nocapture readonly) #1
86declare i1 @llvm.coro.end(ptr, i1, token) #2
87declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8) #1
88declare ptr @malloc(i64)
89declare i8 @switch_result()
90declare ptr @g()
91declare ptr @h()
92declare ptr @await_suspend_function(ptr %awaiter, ptr %hdl)
93
94attributes #0 = { presplitcoroutine }
95attributes #1 = { argmemonly nounwind readonly }
96attributes #2 = { nounwind }
97attributes #3 = { nounwind readnone }
98