xref: /llvm-project/llvm/test/Transforms/Inline/convergence-inline.ll (revision f405c683ba929fcd0bcaa435ca2fbe4bb221d04b)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes='cgscc(inline)' -S %s | FileCheck %s
3
4define void @nonconvergent_callee() alwaysinline {
5; CHECK-LABEL: @nonconvergent_callee(
6; CHECK-NEXT:  entry:
7; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
8; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
9; CHECK-NEXT:    ret void
10;
11entry:
12  %token = call token @llvm.experimental.convergence.anchor()
13  call void @f(i32 0) [ "convergencectrl"(token %token) ]
14  ret void
15}
16
17define void @convergent_callee(i32 %v) convergent alwaysinline {
18; CHECK-LABEL: @convergent_callee(
19; CHECK-NEXT:  entry:
20; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
21; CHECK-NEXT:    call void @f(i32 [[V:%.*]]) [ "convergencectrl"(token [[TOKEN]]) ]
22; CHECK-NEXT:    ret void
23;
24entry:
25  %token = call token @llvm.experimental.convergence.entry()
26  call void @f(i32 %v) [ "convergencectrl"(token %token) ]
27  ret void
28}
29
30define void @test_nonconvergent() {
31; CHECK-LABEL: @test_nonconvergent(
32; CHECK-NEXT:  entry:
33; CHECK-NEXT:    [[TOKEN_I:%.*]] = call token @llvm.experimental.convergence.anchor()
34; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOKEN_I]]) ]
35; CHECK-NEXT:    ret void
36;
37entry:
38  call void @nonconvergent_callee()
39  ret void
40}
41
42define void @test_convergent_basic(i1 %cond) {
43; CHECK-LABEL: @test_convergent_basic(
44; CHECK-NEXT:  entry:
45; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
46; CHECK-NEXT:    br i1 [[COND:%.*]], label [[THEN:%.*]], label [[END:%.*]]
47; CHECK:       then:
48; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
49; CHECK-NEXT:    br label [[END]]
50; CHECK:       end:
51; CHECK-NEXT:    ret void
52;
53entry:
54  %token = call token @llvm.experimental.convergence.anchor()
55  br i1 %cond, label %then, label %end
56
57then:
58  call void @convergent_callee(i32 0) [ "convergencectrl"(token %token) ]
59  br label %end
60
61end:
62  ret void
63}
64
65define void @test_convergent_no_token(i1 %cond) convergent {
66; CHECK-LABEL: @test_convergent_no_token(
67; CHECK-NEXT:  entry:
68; CHECK-NEXT:    call void @convergent_callee(i32 0)
69; CHECK-NEXT:    ret void
70;
71entry:
72  call void @convergent_callee(i32 0)
73  ret void
74}
75
76define void @test_convergent_multiple() convergent {
77; CHECK-LABEL: @test_convergent_multiple(
78; CHECK-NEXT:  entry:
79; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
80; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
81; CHECK-NEXT:    call void @f(i32 1) [ "convergencectrl"(token [[TOKEN]]) ]
82; CHECK-NEXT:    call void @f(i32 2) [ "convergencectrl"(token [[TOKEN]]) ]
83; CHECK-NEXT:    ret void
84;
85entry:
86  %token = call token @llvm.experimental.convergence.entry()
87  call void @convergent_callee(i32 0) [ "convergencectrl"(token %token) ]
88  call void @convergent_callee(i32 1) [ "convergencectrl"(token %token) ]
89  call void @convergent_callee(i32 2) [ "convergencectrl"(token %token) ]
90  ret void
91}
92
93define void @test_convergent_loop(i1 %cond) {
94; CHECK-LABEL: @test_convergent_loop(
95; CHECK-NEXT:  entry:
96; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.anchor()
97; CHECK-NEXT:    br i1 [[COND:%.*]], label [[HDR:%.*]], label [[END:%.*]]
98; CHECK:       hdr:
99; CHECK-NEXT:    [[TOK_LOOP:%.*]] = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token [[TOKEN]]) ]
100; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOK_LOOP]]) ]
101; CHECK-NEXT:    br i1 [[COND]], label [[HDR]], label [[END]]
102; CHECK:       end:
103; CHECK-NEXT:    ret void
104;
105entry:
106  %token = call token @llvm.experimental.convergence.anchor()
107  br i1 %cond, label %hdr, label %end
108
109hdr:
110  %tok.loop = call token @llvm.experimental.convergence.loop() [ "convergencectrl"(token %token) ]
111  call void @convergent_callee(i32 0) [ "convergencectrl"(token %tok.loop) ]
112  br i1 %cond, label %hdr, label %end
113
114end:
115  ret void
116}
117
118define void @make_indirect_call(ptr %f, i32 %x) convergent alwaysinline {
119; CHECK-LABEL: @make_indirect_call(
120; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
121; CHECK-NEXT:    call void [[F:%.*]](i32 [[X:%.*]]) #[[ATTR2:[0-9]+]] [ "convergencectrl"(token [[TOKEN]]) ]
122; CHECK-NEXT:    ret void
123;
124  %token = call token @llvm.experimental.convergence.entry()
125  call void %f(i32 %x) convergent [ "convergencectrl"(token %token) ]
126  ret void
127}
128
129define void @test_indirect_call() convergent {
130; CHECK-LABEL: @test_indirect_call(
131; CHECK-NEXT:  entry:
132; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
133; CHECK-NEXT:    call void @f(i32 0) [ "convergencectrl"(token [[TOKEN]]) ]
134; CHECK-NEXT:    ret void
135;
136entry:
137  %token = call token @llvm.experimental.convergence.entry()
138  call void @make_indirect_call(ptr @convergent_callee, i32 0) [ "convergencectrl"(token %token) ]
139  ret void
140}
141
142define void @recurse() convergent alwaysinline {
143; CHECK-LABEL: @recurse(
144; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
145; CHECK-NEXT:    call void @recurse() [ "convergencectrl"(token [[TOKEN]]) ]
146; CHECK-NEXT:    ret void
147;
148  %token = call token @llvm.experimental.convergence.entry()
149  call void @recurse() [ "convergencectrl"(token %token) ]
150  ret void
151}
152
153define void @test_recursive_call() convergent {
154; CHECK-LABEL: @test_recursive_call(
155; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
156; CHECK-NEXT:    call void @recurse() [ "convergencectrl"(token [[TOKEN]]) ]
157; CHECK-NEXT:    ret void
158;
159  %token = call token @llvm.experimental.convergence.entry()
160  call void @recurse() [ "convergencectrl"(token %token) ]
161  ret void
162}
163
164define i32 @outer_g(i32 %x) convergent alwaysinline {
165; CHECK-LABEL: @outer_g(
166; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
167; CHECK-NEXT:    [[Y:%.*]] = call i32 @g(i32 [[X:%.*]]) [ "convergencectrl"(token [[TOKEN]]) ]
168; CHECK-NEXT:    ret i32 [[Y]]
169;
170  %token = call token @llvm.experimental.convergence.entry()
171  %y = call i32 @g(i32 %x) [ "convergencectrl"(token %token) ]
172  ret i32 %y
173}
174
175define void @test_two_calls() convergent {
176; CHECK-LABEL: @test_two_calls(
177; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
178; CHECK-NEXT:    [[Y_I:%.*]] = call i32 @g(i32 23) [ "convergencectrl"(token [[TOKEN]]) ]
179; CHECK-NEXT:    call void @f(i32 [[Y_I]]) [ "convergencectrl"(token [[TOKEN]]) ]
180; CHECK-NEXT:    ret void
181;
182  %token = call token @llvm.experimental.convergence.entry()
183  %x = call i32 @outer_g(i32 23) [ "convergencectrl"(token %token) ]
184  call void @convergent_callee(i32 %x) [ "convergencectrl"(token %token) ]
185  ret void
186}
187
188define i32 @token_not_first(i32 %x) convergent alwaysinline {
189; CHECK-LABEL: @token_not_first(
190; CHECK-NEXT:    {{%.*}} = alloca ptr, align 8
191; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
192; CHECK-NEXT:    [[Y:%.*]] = call i32 @g(i32 [[X:%.*]]) [ "convergencectrl"(token [[TOKEN]]) ]
193; CHECK-NEXT:    ret i32 [[Y]]
194;
195  %p = alloca ptr, align 8
196  %token = call token @llvm.experimental.convergence.entry()
197  %y = call i32 @g(i32 %x) [ "convergencectrl"(token %token) ]
198  ret i32 %y
199}
200
201define void @test_token_not_first() convergent {
202; CHECK-LABEL: @test_token_not_first(
203; CHECK-NEXT:    [[TOKEN:%.*]] = call token @llvm.experimental.convergence.entry()
204; CHECK-NEXT:    {{%.*}} = call i32 @g(i32 23) [ "convergencectrl"(token [[TOKEN]]) ]
205; CHECK-NEXT:    ret void
206;
207  %token = call token @llvm.experimental.convergence.entry()
208  %x = call i32 @token_not_first(i32 23) [ "convergencectrl"(token %token) ]
209  ret void
210}
211
212declare void @f(i32) convergent
213declare i32 @g(i32) convergent
214
215declare token @llvm.experimental.convergence.entry()
216declare token @llvm.experimental.convergence.anchor()
217declare token @llvm.experimental.convergence.loop()
218