xref: /llvm-project/llvm/test/Transforms/LICM/sink-with-coroutine.ll (revision 51d5d7bbae92493a5bfa7cc6b519de8a5bb32fdb)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; Verifies that LICM is disabled for loops that contains coro.suspend.
3; RUN: opt -S < %s -passes=licm | FileCheck %s
4
5define i64 @licm(i64 %n) #0 {
6; CHECK-LABEL: define i64 @licm
7; CHECK-SAME: (i64 [[N:%.*]]) {
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    [[P:%.*]] = alloca i64, align 8
10; CHECK-NEXT:    br label [[BB0:%.*]]
11; CHECK:       bb0:
12; CHECK-NEXT:    br label [[LOOP:%.*]]
13; CHECK:       loop:
14; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, [[BB0]] ], [ [[T5:%.*]], [[AWAIT_READY:%.*]] ]
15; CHECK-NEXT:    [[T5]] = add i64 [[I]], 1
16; CHECK-NEXT:    [[SUSPEND:%.*]] = call i8 @llvm.coro.suspend(token none, i1 false)
17; CHECK-NEXT:    switch i8 [[SUSPEND]], label [[BB2:%.*]] [
18; CHECK-NEXT:    i8 0, label [[AWAIT_READY]]
19; CHECK-NEXT:    ]
20; CHECK:       await.ready:
21; CHECK-NEXT:    store i64 1, ptr [[P]], align 4
22; CHECK-NEXT:    [[T6:%.*]] = icmp ult i64 [[T5]], [[N]]
23; CHECK-NEXT:    br i1 [[T6]], label [[LOOP]], label [[BB2]]
24; CHECK:       bb2:
25; CHECK-NEXT:    [[RES:%.*]] = call i1 @llvm.coro.end(ptr null, i1 false, token none)
26; CHECK-NEXT:    ret i64 0
27;
28entry:
29  %p = alloca i64
30  br label %bb0
31
32bb0:
33  br label %loop
34
35loop:
36  %i = phi i64 [ 0, %bb0 ], [ %t5, %await.ready ]
37  %t5 = add i64 %i, 1
38  %suspend = call i8 @llvm.coro.suspend(token none, i1 false)
39  switch i8 %suspend, label %bb2 [
40  i8 0, label %await.ready
41  ]
42
43await.ready:
44  store i64 1, ptr %p
45  %t6 = icmp ult i64 %t5, %n
46  br i1 %t6, label %loop, label %bb2
47
48bb2:
49  %res = call i1 @llvm.coro.end(ptr null, i1 false, token none)
50  ret i64 0
51}
52
53@tls = thread_local global i32 0
54
55define i64 @hoist_threadlocal() presplitcoroutine {
56; CHECK-LABEL: define i64 @hoist_threadlocal
57; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
58; CHECK-NEXT:  entry:
59; CHECK-NEXT:    [[P:%.*]] = alloca i64, align 8
60; CHECK-NEXT:    br label [[LOOP_PREHEADER:%.*]]
61; CHECK:       loop.preheader:
62; CHECK-NEXT:    br label [[FOR_BODY:%.*]]
63; CHECK:       for.body:
64; CHECK-NEXT:    [[I:%.*]] = phi i64 [ 0, [[LOOP_PREHEADER]] ], [ [[I_NEXT:%.*]], [[LOOP_END:%.*]] ]
65; CHECK-NEXT:    [[I_NEXT]] = add i64 [[I]], 1
66; CHECK-NEXT:    [[THREAD_LOCAL_0:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls)
67; CHECK-NEXT:    [[READONLY_0:%.*]] = call ptr @readonly_funcs()
68; CHECK-NEXT:    [[SUSPEND:%.*]] = call i8 @llvm.coro.suspend(token none, i1 false)
69; CHECK-NEXT:    switch i8 [[SUSPEND]], label [[EXIT:%.*]] [
70; CHECK-NEXT:    i8 0, label [[AWAIT_READY:%.*]]
71; CHECK-NEXT:    ]
72; CHECK:       await.ready:
73; CHECK-NEXT:    [[THREAD_LOCAL_1:%.*]] = call ptr @llvm.threadlocal.address.p0(ptr @tls)
74; CHECK-NEXT:    [[READONLY_1:%.*]] = call ptr @readonly_funcs()
75; CHECK-NEXT:    [[CMP_0:%.*]] = icmp eq ptr [[THREAD_LOCAL_0]], [[THREAD_LOCAL_1]]
76; CHECK-NEXT:    [[CMP_1:%.*]] = icmp eq ptr [[READONLY_0]], [[READONLY_1]]
77; CHECK-NEXT:    [[CMP:%.*]] = and i1 [[CMP_0]], [[CMP_1]]
78; CHECK-NEXT:    br i1 [[CMP]], label [[NOT_REACHABLE:%.*]], label [[LOOP_END]]
79; CHECK:       not.reachable:
80; CHECK-NEXT:    call void @not.reachable()
81; CHECK-NEXT:    br label [[LOOP_END]]
82; CHECK:       loop.end:
83; CHECK-NEXT:    br i1 [[CMP]], label [[EXIT]], label [[FOR_BODY]]
84; CHECK:       exit:
85; CHECK-NEXT:    [[RES:%.*]] = call i1 @llvm.coro.end(ptr null, i1 false, token none)
86; CHECK-NEXT:    ret i64 0
87;
88entry:
89  %p = alloca i64
90  br label %loop.preheader
91
92loop.preheader:
93  br label %for.body
94
95for.body:
96  %i = phi i64 [ 0, %loop.preheader ], [ %i.next, %loop.end ]
97  %i.next = add i64 %i, 1
98  %thread_local.0 = call ptr @llvm.threadlocal.address(ptr @tls)
99  %readonly.0 = call ptr @readonly_funcs()
100  %suspend = call i8 @llvm.coro.suspend(token none, i1 false)
101  switch i8 %suspend, label %exit [
102  i8 0, label %await.ready
103  ]
104
105await.ready:
106  %thread_local.1 = call ptr @llvm.threadlocal.address(ptr @tls)
107  %readonly.1 = call ptr @readonly_funcs()
108  %cmp.0 = icmp eq ptr %thread_local.0, %thread_local.1
109  %cmp.1 = icmp eq ptr %readonly.0, %readonly.1
110  %cmp = and i1 %cmp.0, %cmp.1
111  br i1 %cmp, label %not.reachable, label %loop.end
112
113not.reachable:
114  call void @not.reachable()
115  br label %loop.end
116
117loop.end:
118  %loop.end.cond = icmp ugt i64 %i.next, 5
119  br i1 %cmp, label %exit, label %for.body
120
121exit:
122  %res = call i1 @llvm.coro.end(ptr null, i1 false, token none)
123  ret i64 0
124}
125
126declare i8  @llvm.coro.suspend(token, i1)
127declare i1  @llvm.coro.end(ptr, i1, token)
128declare nonnull ptr @readonly_funcs() readonly
129declare nonnull ptr @llvm.threadlocal.address(ptr nonnull) nounwind readnone willreturn
130declare void @not.reachable()
131