xref: /llvm-project/llvm/test/Transforms/Coroutines/coro-split-musttail-chain-pgo-counter-promo.ll (revision 3bb39690d729d85cd93c9dd6e750d82d6f367541)
1; REQUIRES: x86-registered-target
2; RUN: opt -passes='pgo-instr-gen,instrprof,coro-split' -do-counter-promotion=true -S < %s | FileCheck %s
3
4; CHECK-LABEL: define internal fastcc void @f.resume
5; CHECK: musttail call fastcc void
6; CHECK-NEXT: ret void
7; CHECK: musttail call fastcc void
8; CHECK-NEXT: ret void
9; CHECK-LABEL: define internal fastcc void @f.destroy
10target triple = "x86_64-grtev4-linux-gnu"
11
12%CoroutinePromise = type { ptr, i64, [8 x i8], ptr}
13%Awaitable.1 = type { ptr }
14%Awaitable.2 = type { ptr, ptr }
15
16declare void @await_suspend(ptr noundef nonnull align 1 dereferenceable(1), ptr) local_unnamed_addr
17declare ptr @await_transform_await_suspend(ptr noundef nonnull align 8 dereferenceable(16), ptr) local_unnamed_addr
18declare void @destroy_frame_slowpath(ptr noundef nonnull align 16 dereferenceable(32)) local_unnamed_addr
19declare ptr @other_coro();
20declare void @heap_delete(ptr noundef, i64 noundef, i64 noundef) local_unnamed_addr
21declare noundef nonnull ptr @heap_allocate(i64 noundef, i64 noundef) local_unnamed_addr
22
23declare void @llvm.assume(i1 noundef)
24declare i64 @llvm.coro.align.i64()
25declare i1 @llvm.coro.alloc(token)
26declare ptr @llvm.coro.begin(token, ptr writeonly)
27declare i1 @llvm.coro.end(ptr, i1, token)
28declare ptr @llvm.coro.free(token, ptr nocapture readonly)
29declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr)
30declare token @llvm.coro.save(ptr)
31declare i64 @llvm.coro.size.i64()
32declare ptr @llvm.coro.subfn.addr(ptr nocapture readonly, i8)
33declare i8 @llvm.coro.suspend(token, i1)
34declare void @llvm.instrprof.increment(ptr, i64, i32, i32)
35declare void @llvm.instrprof.value.profile(ptr, i64, i64, i32, i32)
36declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture)
37declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture)
38
39; Function Attrs: noinline nounwind presplitcoroutine uwtable
40define ptr @f(i32 %0) presplitcoroutine align 32 {
41  %2 = alloca i32, align 8
42  %3 = alloca %CoroutinePromise, align 16
43  %4 = alloca %Awaitable.1, align 8
44  %5 = alloca %Awaitable.2, align 8
45  %6 = call token @llvm.coro.id(i32 8, ptr nonnull %3, ptr nonnull @f, ptr null)
46  %7 = call i1 @llvm.coro.alloc(token %6)
47  br i1 %7, label %8, label %12
48
498:                                                ; preds = %1
50  %9 = call i64 @llvm.coro.size.i64()
51  %10 = call i64 @llvm.coro.align.i64()
52  %11 = call noalias noundef nonnull ptr @heap_allocate(i64 noundef %9, i64 noundef %10) #27
53  call void @llvm.assume(i1 true) [ "align"(ptr %11, i64 %10) ]
54  br label %12
55
5612:                                               ; preds = %8, %1
57  %13 = phi ptr [ null, %1 ], [ %11, %8 ]
58  %14 = call ptr @llvm.coro.begin(token %6, ptr %13) #28
59  call void @llvm.lifetime.start.p0(i64 32, ptr nonnull %3) #9
60  store ptr null, ptr %3, align 16
61  %15 = getelementptr inbounds {ptr, i64}, ptr %3, i64 0, i32 1
62  store i64 0, ptr %15, align 8
63  call void @llvm.lifetime.start.p0(i64 8, ptr nonnull %4) #9
64  store ptr %3, ptr %4, align 8
65  %16 = call token @llvm.coro.save(ptr null)
66  call void @await_suspend(ptr noundef nonnull align 1 dereferenceable(1) %4, ptr %14) #9
67  %17 = call i8 @llvm.coro.suspend(token %16, i1 false)
68  switch i8 %17, label %61 [
69    i8 0, label %18
70    i8 1, label %21
71  ]
72
7318:                                               ; preds = %12
74  call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %4) #9
75  %19 = icmp slt i32 0, %0
76  br i1 %19, label %20, label %36
77
7820:                                               ; preds = %18
79  br label %22
80
8121:                                               ; preds = %12
82  call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %4) #9
83  br label %54
84
8522:                                               ; preds = %20, %31
86  %23 = phi i32 [ 0, %20 ], [ %32, %31 ]
87  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %5) #9
88  %24 = call ptr @other_coro()
89  store ptr %3, ptr %5, align 8
90  %25 = getelementptr inbounds { ptr, ptr }, ptr %5, i64 0, i32 1
91  store ptr %24, ptr %25, align 8
92  %26 = call token @llvm.coro.save(ptr null)
93  call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_transform_await_suspend)
94  %30 = call i8 @llvm.coro.suspend(token %26, i1 false)
95  switch i8 %30, label %60 [
96    i8 0, label %31
97    i8 1, label %34
98  ]
99
10031:                                               ; preds = %22
101  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %5) #9
102  %32 = add nuw nsw i32 %23, 1
103  %33 = icmp slt i32 %32, %0
104  br i1 %33, label %22, label %35, !llvm.loop !0
105
10634:                                               ; preds = %22
107  call void @llvm.lifetime.end.p0(i64 16, ptr nonnull %5) #9
108  br label %54
109
11035:                                               ; preds = %31
111  br label %36
112
11336:                                               ; preds = %35, %18
114  %37 = call token @llvm.coro.save(ptr null)
115  %38 = getelementptr inbounds i8, ptr %14, i64 16
116  %39 = getelementptr inbounds i8, ptr %14, i64 32
117  %40 = load i64, ptr %39, align 8
118  %41 = load ptr, ptr %38, align 16
119  %42 = icmp eq ptr %41, null
120  br i1 %42, label %43, label %46
121
12243:                                               ; preds = %36
123  call void @llvm.coro.await.suspend.handle(ptr null, ptr null, ptr @await_transform_await_suspend)
124  br label %47
125
12646:                                               ; preds = %36
127  call void @destroy_frame_slowpath(ptr noundef nonnull align 16 dereferenceable(32) %38) #9
128  br label %47
129
13047:                                               ; preds = %43, %46
131  %48 = inttoptr i64 %40 to ptr
132  %49 = call ptr @llvm.coro.subfn.addr(ptr %48, i8 0)
133  %50 = ptrtoint ptr %49 to i64
134  call fastcc void %49(ptr %48) #9
135  %51 = call i8 @llvm.coro.suspend(token %37, i1 true) #28
136  switch i8 %51, label %61 [
137    i8 0, label %53
138    i8 1, label %52
139  ]
140
14152:                                               ; preds = %47
142  br label %54
143
14453:                                               ; preds = %47
145  call void @llvm.lifetime.start.p0(i64 16, ptr nonnull %2) #9
146  unreachable
147
14854:                                               ; preds = %52, %34, %21
149  call void @llvm.lifetime.end.p0(i64 32, ptr nonnull %3) #9
150  %55 = call ptr @llvm.coro.free(token %6, ptr %14)
151  %56 = icmp eq ptr %55, null
152  br i1 %56, label %61, label %57
153
15457:                                               ; preds = %54
155  %58 = call i64 @llvm.coro.size.i64()
156  %59 = call i64 @llvm.coro.align.i64()
157  call void @heap_delete(ptr noundef nonnull %55, i64 noundef %58, i64 noundef %59) #9
158  br label %61
159
16060:                                               ; preds = %22
161  br label %61
162
16361:                                               ; preds = %60, %57, %54, %47, %12
164  %62 = getelementptr inbounds i8, ptr %3, i64 -16
165  %63 = call i1 @llvm.coro.end(ptr null, i1 false, token none) #28
166  ret ptr %62
167}
168
169!0 = distinct !{!0, !1}
170!1 = !{!"llvm.loop.mustprogress"}
171