Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-lifetime-end.ll
blob330c61360e20a35a67707925b4c70edb04f3bd96
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2 ; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse' -S | FileCheck %s
4 declare ptr @malloc(i64)
6 %i8.array = type { [100 x i8] }
7 declare void @consume.i8.array(ptr)
9 @testbool = external local_unnamed_addr global i8, align 1
11 ; testval does not contain an explicit lifetime end. We must assume that it may
12 ; live across suspension.
13 define void @HasNoLifetimeEnd() presplitcoroutine {
14 ; CHECK-LABEL: define void @HasNoLifetimeEnd() {
15 ; CHECK-NEXT:  entry:
16 ; CHECK-NEXT:    [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @HasNoLifetimeEnd.resumers)
17 ; CHECK-NEXT:    [[ALLOC:%.*]] = call ptr @malloc(i64 16)
18 ; CHECK-NEXT:    [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
19 ; CHECK-NEXT:    store ptr @HasNoLifetimeEnd.resume, ptr [[VFRAME]], align 8
20 ; CHECK-NEXT:    [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
21 ; CHECK-NEXT:    store ptr @HasNoLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8
22 ; CHECK-NEXT:    [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
23 ; CHECK-NEXT:    call void @consume.i8.array(ptr [[INDEX_ADDR1]])
24 ; CHECK-NEXT:    [[INDEX_ADDR2:%.*]] = getelementptr inbounds [[HASNOLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
25 ; CHECK-NEXT:    store i1 false, ptr [[INDEX_ADDR2]], align 1
26 ; CHECK-NEXT:    ret void
28 entry:
29   %testval = alloca %i8.array
30   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
31   %alloc = call ptr @malloc(i64 16) #3
32   %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
34   call void @llvm.lifetime.start.p0(i64 100, ptr %testval)
35   call void @consume.i8.array(ptr %testval)
37   %save = call token @llvm.coro.save(ptr null)
38   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
39   switch i8 %suspend, label %exit [
40     i8 0, label %await.ready
41     i8 1, label %exit
42   ]
43 await.ready:
44   br label %exit
45 exit:
46   call i1 @llvm.coro.end(ptr null, i1 false, token none)
47   ret void
50 define void @LifetimeEndAfterCoroEnd() presplitcoroutine {
51 ; CHECK-LABEL: define void @LifetimeEndAfterCoroEnd() {
52 ; CHECK-NEXT:  entry:
53 ; CHECK-NEXT:    [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @LifetimeEndAfterCoroEnd.resumers)
54 ; CHECK-NEXT:    [[ALLOC:%.*]] = call ptr @malloc(i64 16)
55 ; CHECK-NEXT:    [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
56 ; CHECK-NEXT:    store ptr @LifetimeEndAfterCoroEnd.resume, ptr [[VFRAME]], align 8
57 ; CHECK-NEXT:    [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
58 ; CHECK-NEXT:    store ptr @LifetimeEndAfterCoroEnd.destroy, ptr [[DESTROY_ADDR]], align 8
59 ; CHECK-NEXT:    [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
60 ; CHECK-NEXT:    call void @consume.i8.array(ptr [[INDEX_ADDR1]])
61 ; CHECK-NEXT:    [[INDEX_ADDR2:%.*]] = getelementptr inbounds [[LIFETIMEENDAFTERCOROEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
62 ; CHECK-NEXT:    store i1 false, ptr [[INDEX_ADDR2]], align 1
63 ; CHECK-NEXT:    ret void
65 entry:
66   %testval = alloca %i8.array
67   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
68   %alloc = call ptr @malloc(i64 16) #3
69   %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
71   call void @llvm.lifetime.start.p0(i64 100, ptr %testval)
72   call void @consume.i8.array(ptr %testval)
74   %save = call token @llvm.coro.save(ptr null)
75   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
76   switch i8 %suspend, label %exit [
77     i8 0, label %await.ready
78     i8 1, label %exit
79   ]
80 await.ready:
81   br label %exit
82 exit:
83   call i1 @llvm.coro.end(ptr null, i1 false, token none)
84   call void @llvm.lifetime.end.p0(i64 100, ptr  %testval)
85   ret void
88 define void @BranchWithoutLifetimeEnd() presplitcoroutine {
89 ; CHECK-LABEL: define void @BranchWithoutLifetimeEnd() {
90 ; CHECK-NEXT:  entry:
91 ; CHECK-NEXT:    [[ID:%.*]] = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr @BranchWithoutLifetimeEnd.resumers)
92 ; CHECK-NEXT:    [[ALLOC:%.*]] = call ptr @malloc(i64 16)
93 ; CHECK-NEXT:    [[VFRAME:%.*]] = call noalias nonnull ptr @llvm.coro.begin(token [[ID]], ptr [[ALLOC]])
94 ; CHECK-NEXT:    store ptr @BranchWithoutLifetimeEnd.resume, ptr [[VFRAME]], align 8
95 ; CHECK-NEXT:    [[DESTROY_ADDR:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME:%.*]], ptr [[VFRAME]], i32 0, i32 1
96 ; CHECK-NEXT:    store ptr @BranchWithoutLifetimeEnd.destroy, ptr [[DESTROY_ADDR]], align 8
97 ; CHECK-NEXT:    [[TESTVAL:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 2
98 ; CHECK-NEXT:    call void @consume.i8.array(ptr [[TESTVAL]])
99 ; CHECK-NEXT:    [[TMP0:%.*]] = load i8, ptr @testbool, align 1
100 ; CHECK-NEXT:    [[INDEX_ADDR1:%.*]] = getelementptr inbounds [[BRANCHWITHOUTLIFETIMEEND_FRAME]], ptr [[VFRAME]], i32 0, i32 3
101 ; CHECK-NEXT:    store i1 false, ptr [[INDEX_ADDR1]], align 1
102 ; CHECK-NEXT:    ret void
104 entry:
105   %testval = alloca %i8.array
106   %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)
107   %alloc = call ptr @malloc(i64 16) #3
108   %vFrame = call noalias nonnull ptr @llvm.coro.begin(token %id, ptr %alloc)
110   call void @llvm.lifetime.start.p0(i64 100, ptr %testval)
111   call void @consume.i8.array(ptr %testval)
113   %0 = load i8, ptr @testbool, align 1
114   %tobool = trunc nuw i8 %0 to i1
115   br i1 %tobool, label %if.then, label %if.end
117 if.then:
118   call void @llvm.lifetime.end.p0(i64 100, ptr  %testval)
119   br label %if.end
121 if.end:
122   %save = call token @llvm.coro.save(ptr null)
123   %suspend = call i8 @llvm.coro.suspend(token %save, i1 false)
124   switch i8 %suspend, label %exit [
125     i8 0, label %await.ready
126     i8 1, label %exit
127   ]
128 await.ready:
129   br label %exit
130 exit:
131   call i1 @llvm.coro.end(ptr null, i1 false, token none)
132   ret void
136 declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
137 declare ptr @llvm.coro.begin(token, ptr writeonly) #3
138 declare ptr @llvm.coro.frame() #5
139 declare i8 @llvm.coro.suspend(token, i1) #3
140 declare i1 @llvm.coro.end(ptr, i1, token) #3
141 declare void @llvm.lifetime.start.p0(i64, ptr nocapture) #4
142 declare void @llvm.lifetime.end.p0(i64, ptr nocapture) #4