xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-async-nomerge.ll (revision a0d2fc126efd85a4712681e7ec04a04171557475)
1; RUN: opt < %s -O2 -S
2; RUN: opt -S -hoist-common-insts -hoist-common-insts -passes=simplifycfg < %s | FileCheck %s --check-prefixes=CHECK
3target datalayout = "p:64:64:64"
4%swift.async_func_pointer = type <{ i32, i32 }>
5%swift.context = type { ptr, ptr }
6
7declare void @f()
8declare void @g()
9declare ptr @llvm.coro.async.resume()
10declare { ptr } @llvm.coro.suspend.async.sl_p0i8s(i32, ptr, ptr, ...)
11declare ptr @llvm.coro.begin(token, ptr writeonly)
12declare token @llvm.coro.id.async(i32, i32, i32, ptr)
13
14declare i1 @llvm.coro.end.async(ptr, i1, ...)
15
16define linkonce_odr hidden ptr @__swift_async_resume_get_context(ptr %0) {
17entry:
18  ret ptr %0
19}
20
21@repoTU = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @repo to i64), i64 ptrtoint (ptr @repoTU to i64)) to i32), i32 16 }>, align 8
22
23; This test used to crash in optimized mode because simplify cfg would sink the
24; suspend.async() instruction into a common successor block.
25
26; CHECK: swifttailcc void @repo
27; CHECK:llvm.coro.suspend.async.sl_p0s
28; CHECK: br
29; CHECK:llvm.coro.suspend.async.sl_p0s
30; CHECK: br
31; CHECK: ret
32
33define hidden swifttailcc void @repo(ptr swiftasync %0, i1 %cond) {
34entry:
35  %tok = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @repoTU)
36  %id = call ptr @llvm.coro.begin(token %tok, ptr null)
37  br i1 %cond, label %bb1, label %bb2
38
39bb1:
40  call void @f()
41  %ptr0 = call ptr @llvm.coro.async.resume()
42  call void @f()
43  ; Simplifycfg must not sink the suspend instruction.
44  %t3 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr0, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr0, ptr %0)
45  br label %tailblock
46
47bb2:
48  call void @g()
49  %ptr1 = call ptr @llvm.coro.async.resume()
50  call void @g()
51  ; Simplifycfg must not sink the suspend instruction.
52  %t4 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr1, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr1, ptr %0)
53  br label %tailblock
54
55tailblock:
56  %t = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %id, i1 false, ptr @repo.0, ptr @return, ptr %0)
57  unreachable
58}
59
60define internal swifttailcc void @repo.0(ptr %0, ptr %1) {
61entry:
62  musttail call swifttailcc void %0(ptr swiftasync %1)
63  ret void
64}
65
66declare swifttailcc void @swift_task_switch(ptr, ptr)
67
68define internal swifttailcc void @repo.1(ptr %0, ptr %1) {
69entry:
70  musttail call swifttailcc void @swift_task_switch(ptr swiftasync %1, ptr %0)
71  ret void
72}
73
74declare swifttailcc void @return(ptr swiftasync)
75
76@repoTU2 = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @repo2 to i64), i64 ptrtoint (ptr @repoTU2 to i64)) to i32), i32 16 }>, align 8
77
78; This test used to crash in optimized mode because simplify cfg would hoist the
79; async.resume() instruction into a common block.
80
81; CHECK: swifttailcc void @repo2
82; CHECK: entry:
83; CHECK: br i1
84
85; CHECK: @llvm.coro.async.resume()
86; CHECK: llvm.coro.suspend.async.sl_p0s
87; CHECK: br
88
89; CHECK:@llvm.coro.async.resume()
90; CHECK:llvm.coro.suspend.async.sl_p0s
91; CHECK: br
92
93; CHECK: ret
94
95define hidden swifttailcc void @repo2(ptr swiftasync %0, i1 %cond) {
96entry:
97  %tok = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @repoTU2)
98  %id = call ptr @llvm.coro.begin(token %tok, ptr null)
99  br i1 %cond, label %bb1, label %bb2
100
101bb1:
102  ; Simplifycfg must not hoist the resume instruction.
103  %ptr0 = call ptr @llvm.coro.async.resume()
104  call void @f()
105  %t3 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr0, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr0, ptr %0)
106  call void @f()
107  br label %tailblock
108
109bb2:
110  ; Simplifycfg must not hoist the resume instruction.
111  %ptr1 = call ptr @llvm.coro.async.resume()
112  call void @g()
113  %t4 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr1, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr1, ptr %0)
114  call void @g()
115  br label %tailblock
116
117tailblock:
118  %t = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %id, i1 false, ptr @repo.0, ptr @return, ptr %0)
119  unreachable
120}
121