Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / Attributor / callgraph.ll
bloba85c6a02a99e57fb53c90fb86210adb5a913dd9c
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals
2 ; RUN: opt -passes=attributor -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,UNLIM,OUNLM
3 ; RUN: opt -passes=attributor -attributor-print-call-graph -S -disable-output < %s | FileCheck %s --check-prefixes=DOT
4 ; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=2 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,UPTO2,LIMI2
5 ; RUN: opt -passes=attributor --attributor-max-specializations-per-call-base=0 -S < %s | FileCheck %s --check-prefixes=CHECK,OWRDL,LIMI0
6 ; RUN: opt -passes=attributor --attributor-assume-closed-world -S < %s | FileCheck %s --check-prefixes=CHECK,UPTO2,UNLIM,CWRLD
8 ;.
9 ; CHECK: @[[G:[a-zA-Z0-9_$"\\.-]+]] = global ptr @usedByGlobal
11 define dso_local void @func1() {
12 ; CHECK-LABEL: @func1(
13 ; CHECK-NEXT:    br label [[TMP2:%.*]]
14 ; CHECK:       1:
15 ; CHECK-NEXT:    unreachable
16 ; CHECK:       2:
17 ; CHECK-NEXT:    call void @func3()
18 ; CHECK-NEXT:    ret void
20   %1 = icmp ne i32 0, 0
21   br i1 %1, label %2, label %3
23 2:                                                ; preds = %0
24   call void @func2(i1 false)
25   br label %3
27 3:                                                ; preds = %2, %0
28   call void () @func3()
29   ret void
32 declare void @func3()
33 define internal void @func4() {
34 ; CHECK-LABEL: @func4(
35 ; CHECK-NEXT:    call void @func3()
36 ; CHECK-NEXT:    ret void
38   call void @func3()
39   ret void
41 define internal void @internal_good() {
42 ; CHECK-LABEL: @internal_good(
43 ; CHECK-NEXT:    call void @void(ptr @func4)
44 ; CHECK-NEXT:    ret void
46   call void @void(ptr @func4)
47   ret void
50 define dso_local void @func2(i1 %c) {
51 ; UPTO2-LABEL: @func2(
52 ; UPTO2-NEXT:    [[F:%.*]] = select i1 [[C:%.*]], ptr @internal_good, ptr @func4
53 ; UPTO2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[F]], @func4
54 ; UPTO2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
55 ; UPTO2:       2:
56 ; UPTO2-NEXT:    call void @func4()
57 ; UPTO2-NEXT:    br label [[TMP6:%.*]]
58 ; UPTO2:       3:
59 ; UPTO2-NEXT:    br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
60 ; UPTO2:       4:
61 ; UPTO2-NEXT:    call void @internal_good()
62 ; UPTO2-NEXT:    br label [[TMP6]]
63 ; UPTO2:       5:
64 ; UPTO2-NEXT:    unreachable
65 ; UPTO2:       6:
66 ; UPTO2-NEXT:    ret void
68 ; LIMI0-LABEL: @func2(
69 ; LIMI0-NEXT:    [[F:%.*]] = select i1 [[C:%.*]], ptr @internal_good, ptr @func4
70 ; LIMI0-NEXT:    call void [[F]](), !callees !0
71 ; LIMI0-NEXT:    ret void
73   %f = select i1 %c, ptr @internal_good, ptr @func4
74   call void %f()
75   ret void
79 define void @func5(i32 %0) {
80 ; UPTO2-LABEL: @func5(
81 ; UPTO2-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
82 ; UPTO2-NEXT:    [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3
83 ; UPTO2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[TMP3]], @func3
84 ; UPTO2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
85 ; UPTO2:       5:
86 ; UPTO2-NEXT:    call void @func3()
87 ; UPTO2-NEXT:    br label [[TMP9:%.*]]
88 ; UPTO2:       6:
89 ; UPTO2-NEXT:    br i1 true, label [[TMP7:%.*]], label [[TMP8:%.*]]
90 ; UPTO2:       7:
91 ; UPTO2-NEXT:    call void @func4()
92 ; UPTO2-NEXT:    br label [[TMP9]]
93 ; UPTO2:       8:
94 ; UPTO2-NEXT:    unreachable
95 ; UPTO2:       9:
96 ; UPTO2-NEXT:    ret void
98 ; LIMI0-LABEL: @func5(
99 ; LIMI0-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
100 ; LIMI0-NEXT:    [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3
101 ; LIMI0-NEXT:    call void [[TMP3]](), !callees !1
102 ; LIMI0-NEXT:    ret void
104   %2 = icmp ne i32 %0, 0
105   %3 = select i1 %2, ptr @func4, ptr @func3
106   call void () %3()
107   ret void
110 define i32 @musttailCall(i32 %0) {
111 ; CHECK-LABEL: @musttailCall(
112 ; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[TMP0:%.*]], 0
113 ; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[TMP2]], ptr @func4, ptr @func3
114 ; CHECK-NEXT:    [[C:%.*]] = musttail call i32 [[TMP3]](i32 0)
115 ; CHECK-NEXT:    ret i32 [[C]]
117   %2 = icmp ne i32 %0, 0
118   %3 = select i1 %2, ptr @func4, ptr @func3
119   %c = musttail call i32 (i32) %3(i32 0)
120   ret i32 %c
123 declare i32 @retI32()
124 declare void @takeI32(i32)
125 declare float @retFloatTakeFloat(float)
126 ; This callee is always filtered out because of the noundef argument
127 declare float @retFloatTakeFloatFloatNoundef(float, float noundef)
128 declare void @void()
130 define i32 @non_matching_fp1(i1 %c1, i1 %c2, i1 %c) {
131 ; UNLIM-LABEL: @non_matching_fp1(
132 ; UNLIM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
133 ; UNLIM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
134 ; UNLIM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
135 ; UNLIM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
136 ; UNLIM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
137 ; UNLIM:       2:
138 ; UNLIM-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
139 ; UNLIM-NEXT:    br label [[TMP15:%.*]]
140 ; UNLIM:       3:
141 ; UNLIM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
142 ; UNLIM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
143 ; UNLIM:       5:
144 ; UNLIM-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
145 ; UNLIM-NEXT:    br label [[TMP15]]
146 ; UNLIM:       6:
147 ; UNLIM-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @void
148 ; UNLIM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
149 ; UNLIM:       8:
150 ; UNLIM-NEXT:    [[CALL3:%.*]] = call i32 @void(i32 42)
151 ; UNLIM-NEXT:    br label [[TMP15]]
152 ; UNLIM:       9:
153 ; UNLIM-NEXT:    br i1 true, label [[TMP10:%.*]], label [[TMP14:%.*]]
154 ; UNLIM:       10:
155 ; UNLIM-NEXT:    [[TMP11:%.*]] = bitcast i32 42 to float
156 ; UNLIM-NEXT:    [[TMP12:%.*]] = call float @retFloatTakeFloat(float [[TMP11]])
157 ; UNLIM-NEXT:    [[TMP13:%.*]] = bitcast float [[TMP12]] to i32
158 ; UNLIM-NEXT:    br label [[TMP15]]
159 ; UNLIM:       14:
160 ; UNLIM-NEXT:    unreachable
161 ; UNLIM:       15:
162 ; UNLIM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[TMP13]], [[TMP10]] ]
163 ; UNLIM-NEXT:    ret i32 [[CALL_PHI]]
165 ; LIMI2-LABEL: @non_matching_fp1(
166 ; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
167 ; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
168 ; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
169 ; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
170 ; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
171 ; LIMI2:       2:
172 ; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
173 ; LIMI2-NEXT:    br label [[TMP7:%.*]]
174 ; LIMI2:       3:
175 ; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
176 ; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
177 ; LIMI2:       5:
178 ; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
179 ; LIMI2-NEXT:    br label [[TMP7]]
180 ; LIMI2:       6:
181 ; LIMI2-NEXT:    [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees !0
182 ; LIMI2-NEXT:    br label [[TMP7]]
183 ; LIMI2:       7:
184 ; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ]
185 ; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
187 ; LIMI0-LABEL: @non_matching_fp1(
188 ; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
189 ; LIMI0-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr @void
190 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
191 ; LIMI0-NEXT:    [[CALL:%.*]] = call i32 [[FP]](i32 42), !callees !2
192 ; LIMI0-NEXT:    ret i32 [[CALL]]
194   %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32
195   %fp2 = select i1 %c2, ptr @retFloatTakeFloat, ptr @void
196   %fp = select i1 %c, ptr %fp1, ptr %fp2
197   %call = call i32 %fp(i32 42)
198   ret i32 %call
201 define i32 @non_matching_fp1_noundef(i1 %c1, i1 %c2, i1 %c) {
202 ; UNLIM-LABEL: @non_matching_fp1_noundef(
203 ; UNLIM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
204 ; UNLIM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
205 ; UNLIM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
206 ; UNLIM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
207 ; UNLIM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
208 ; UNLIM:       2:
209 ; UNLIM-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
210 ; UNLIM-NEXT:    br label [[TMP9:%.*]]
211 ; UNLIM:       3:
212 ; UNLIM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
213 ; UNLIM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
214 ; UNLIM:       5:
215 ; UNLIM-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
216 ; UNLIM-NEXT:    br label [[TMP9]]
217 ; UNLIM:       6:
218 ; UNLIM-NEXT:    br i1 true, label [[TMP7:%.*]], label [[TMP8:%.*]]
219 ; UNLIM:       7:
220 ; UNLIM-NEXT:    [[CALL3:%.*]] = call i32 @void(i32 42)
221 ; UNLIM-NEXT:    br label [[TMP9]]
222 ; UNLIM:       8:
223 ; UNLIM-NEXT:    unreachable
224 ; UNLIM:       9:
225 ; UNLIM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP7]] ]
226 ; UNLIM-NEXT:    ret i32 [[CALL_PHI]]
228 ; LIMI2-LABEL: @non_matching_fp1_noundef(
229 ; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
230 ; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
231 ; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
232 ; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
233 ; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
234 ; LIMI2:       2:
235 ; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @takeI32(i32 42)
236 ; LIMI2-NEXT:    br label [[TMP7:%.*]]
237 ; LIMI2:       3:
238 ; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
239 ; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
240 ; LIMI2:       5:
241 ; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 @retI32(i32 42)
242 ; LIMI2-NEXT:    br label [[TMP7]]
243 ; LIMI2:       6:
244 ; LIMI2-NEXT:    [[CALL3:%.*]] = call i32 [[FP]](i32 42), !callees !1
245 ; LIMI2-NEXT:    br label [[TMP7]]
246 ; LIMI2:       7:
247 ; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP6]] ]
248 ; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
250 ; LIMI0-LABEL: @non_matching_fp1_noundef(
251 ; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
252 ; LIMI0-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloatFloatNoundef, ptr @void
253 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
254 ; LIMI0-NEXT:    [[CALL:%.*]] = call i32 [[FP]](i32 42), !callees !3
255 ; LIMI0-NEXT:    ret i32 [[CALL]]
257   %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32
258   %fp2 = select i1 %c2, ptr @retFloatTakeFloatFloatNoundef, ptr @void
259   %fp = select i1 %c, ptr %fp1, ptr %fp2
260   %call = call i32 %fp(i32 42)
261   ret i32 %call
264 define void @non_matching_fp2(i1 %c1, i1 %c2, i1 %c, ptr %unknown) {
265 ; OUNLM-LABEL: @non_matching_fp2(
266 ; OUNLM-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
267 ; OUNLM-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
268 ; OUNLM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
269 ; OUNLM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
270 ; OUNLM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
271 ; OUNLM:       2:
272 ; OUNLM-NEXT:    call void @takeI32()
273 ; OUNLM-NEXT:    br label [[TMP10:%.*]]
274 ; OUNLM:       3:
275 ; OUNLM-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
276 ; OUNLM-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
277 ; OUNLM:       5:
278 ; OUNLM-NEXT:    call void @retI32()
279 ; OUNLM-NEXT:    br label [[TMP10]]
280 ; OUNLM:       6:
281 ; OUNLM-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
282 ; OUNLM-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
283 ; OUNLM:       8:
284 ; OUNLM-NEXT:    call void @retFloatTakeFloat()
285 ; OUNLM-NEXT:    br label [[TMP10]]
286 ; OUNLM:       9:
287 ; OUNLM-NEXT:    call void [[FP]]()
288 ; OUNLM-NEXT:    br label [[TMP10]]
289 ; OUNLM:       10:
290 ; OUNLM-NEXT:    ret void
292 ; LIMI2-LABEL: @non_matching_fp2(
293 ; LIMI2-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
294 ; LIMI2-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
295 ; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
296 ; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
297 ; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
298 ; LIMI2:       2:
299 ; LIMI2-NEXT:    call void @takeI32()
300 ; LIMI2-NEXT:    br label [[TMP7:%.*]]
301 ; LIMI2:       3:
302 ; LIMI2-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
303 ; LIMI2-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
304 ; LIMI2:       5:
305 ; LIMI2-NEXT:    call void @retI32()
306 ; LIMI2-NEXT:    br label [[TMP7]]
307 ; LIMI2:       6:
308 ; LIMI2-NEXT:    call void [[FP]]()
309 ; LIMI2-NEXT:    br label [[TMP7]]
310 ; LIMI2:       7:
311 ; LIMI2-NEXT:    ret void
313 ; LIMI0-LABEL: @non_matching_fp2(
314 ; LIMI0-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
315 ; LIMI0-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
316 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
317 ; LIMI0-NEXT:    call void [[FP]]()
318 ; LIMI0-NEXT:    ret void
320 ; CWRLD-LABEL: @non_matching_fp2(
321 ; CWRLD-NEXT:    [[FP1:%.*]] = select i1 [[C1:%.*]], ptr @retI32, ptr @takeI32
322 ; CWRLD-NEXT:    [[FP2:%.*]] = select i1 [[C2:%.*]], ptr @retFloatTakeFloat, ptr [[UNKNOWN:%.*]]
323 ; CWRLD-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr [[FP1]], ptr [[FP2]]
324 ; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @takeI32
325 ; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
326 ; CWRLD:       2:
327 ; CWRLD-NEXT:    call void @takeI32()
328 ; CWRLD-NEXT:    br label [[TMP21:%.*]]
329 ; CWRLD:       3:
330 ; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @retI32
331 ; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
332 ; CWRLD:       5:
333 ; CWRLD-NEXT:    call void @retI32()
334 ; CWRLD-NEXT:    br label [[TMP21]]
335 ; CWRLD:       6:
336 ; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @func3
337 ; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
338 ; CWRLD:       8:
339 ; CWRLD-NEXT:    call void @func3()
340 ; CWRLD-NEXT:    br label [[TMP21]]
341 ; CWRLD:       9:
342 ; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[FP]], @func4
343 ; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
344 ; CWRLD:       11:
345 ; CWRLD-NEXT:    call void @func4()
346 ; CWRLD-NEXT:    br label [[TMP21]]
347 ; CWRLD:       12:
348 ; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
349 ; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]]
350 ; CWRLD:       14:
351 ; CWRLD-NEXT:    call void @retFloatTakeFloat()
352 ; CWRLD-NEXT:    br label [[TMP21]]
353 ; CWRLD:       15:
354 ; CWRLD-NEXT:    [[TMP16:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef
355 ; CWRLD-NEXT:    br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]]
356 ; CWRLD:       17:
357 ; CWRLD-NEXT:    call void @retFloatTakeFloatFloatNoundef()
358 ; CWRLD-NEXT:    br label [[TMP21]]
359 ; CWRLD:       18:
360 ; CWRLD-NEXT:    br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]]
361 ; CWRLD:       19:
362 ; CWRLD-NEXT:    call void @void()
363 ; CWRLD-NEXT:    br label [[TMP21]]
364 ; CWRLD:       20:
365 ; CWRLD-NEXT:    unreachable
366 ; CWRLD:       21:
367 ; CWRLD-NEXT:    ret void
369   %fp1 = select i1 %c1, ptr @retI32, ptr @takeI32
370   %fp2 = select i1 %c2, ptr @retFloatTakeFloat, ptr %unknown
371   %fp = select i1 %c, ptr %fp1, ptr %fp2
372   call void %fp()
373   ret void
376 define i32 @non_matching_unknown(i1 %c, ptr %fn) {
377 ; OUNLM-LABEL: @non_matching_unknown(
378 ; OUNLM-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
379 ; OUNLM-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32
380 ; OUNLM-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
381 ; OUNLM:       2:
382 ; OUNLM-NEXT:    [[CALL1:%.*]] = call i32 @retI32(i32 42)
383 ; OUNLM-NEXT:    br label [[TMP4:%.*]]
384 ; OUNLM:       3:
385 ; OUNLM-NEXT:    [[CALL2:%.*]] = call i32 [[FP]](i32 42)
386 ; OUNLM-NEXT:    br label [[TMP4]]
387 ; OUNLM:       4:
388 ; OUNLM-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ]
389 ; OUNLM-NEXT:    ret i32 [[CALL_PHI]]
391 ; LIMI2-LABEL: @non_matching_unknown(
392 ; LIMI2-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
393 ; LIMI2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @retI32
394 ; LIMI2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
395 ; LIMI2:       2:
396 ; LIMI2-NEXT:    [[CALL1:%.*]] = call i32 @retI32(i32 42)
397 ; LIMI2-NEXT:    br label [[TMP4:%.*]]
398 ; LIMI2:       3:
399 ; LIMI2-NEXT:    [[CALL2:%.*]] = call i32 [[FP]](i32 42)
400 ; LIMI2-NEXT:    br label [[TMP4]]
401 ; LIMI2:       4:
402 ; LIMI2-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP3]] ]
403 ; LIMI2-NEXT:    ret i32 [[CALL_PHI]]
405 ; LIMI0-LABEL: @non_matching_unknown(
406 ; LIMI0-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
407 ; LIMI0-NEXT:    [[CALL:%.*]] = call i32 [[FP]](i32 42)
408 ; LIMI0-NEXT:    ret i32 [[CALL]]
410 ; CWRLD-LABEL: @non_matching_unknown(
411 ; CWRLD-NEXT:    [[FP:%.*]] = select i1 [[C:%.*]], ptr @retI32, ptr [[FN:%.*]]
412 ; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP]], @func3
413 ; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
414 ; CWRLD:       2:
415 ; CWRLD-NEXT:    [[CALL1:%.*]] = call i32 @func3(i32 42)
416 ; CWRLD-NEXT:    br label [[TMP24:%.*]]
417 ; CWRLD:       3:
418 ; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP]], @func4
419 ; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
420 ; CWRLD:       5:
421 ; CWRLD-NEXT:    [[CALL2:%.*]] = call i32 @func4(i32 42)
422 ; CWRLD-NEXT:    br label [[TMP24]]
423 ; CWRLD:       6:
424 ; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP]], @retI32
425 ; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
426 ; CWRLD:       8:
427 ; CWRLD-NEXT:    [[CALL3:%.*]] = call i32 @retI32(i32 42)
428 ; CWRLD-NEXT:    br label [[TMP24]]
429 ; CWRLD:       9:
430 ; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[FP]], @takeI32
431 ; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
432 ; CWRLD:       11:
433 ; CWRLD-NEXT:    [[CALL4:%.*]] = call i32 @takeI32(i32 42)
434 ; CWRLD-NEXT:    br label [[TMP24]]
435 ; CWRLD:       12:
436 ; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloat
437 ; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP18:%.*]]
438 ; CWRLD:       14:
439 ; CWRLD-NEXT:    [[TMP15:%.*]] = bitcast i32 42 to float
440 ; CWRLD-NEXT:    [[TMP16:%.*]] = call float @retFloatTakeFloat(float [[TMP15]])
441 ; CWRLD-NEXT:    [[TMP17:%.*]] = bitcast float [[TMP16]] to i32
442 ; CWRLD-NEXT:    br label [[TMP24]]
443 ; CWRLD:       18:
444 ; CWRLD-NEXT:    [[TMP19:%.*]] = icmp eq ptr [[FP]], @retFloatTakeFloatFloatNoundef
445 ; CWRLD-NEXT:    br i1 [[TMP19]], label [[TMP20:%.*]], label [[TMP21:%.*]]
446 ; CWRLD:       20:
447 ; CWRLD-NEXT:    [[CALL5:%.*]] = call i32 @retFloatTakeFloatFloatNoundef(i32 42)
448 ; CWRLD-NEXT:    br label [[TMP24]]
449 ; CWRLD:       21:
450 ; CWRLD-NEXT:    br i1 true, label [[TMP22:%.*]], label [[TMP23:%.*]]
451 ; CWRLD:       22:
452 ; CWRLD-NEXT:    [[CALL6:%.*]] = call i32 @void(i32 42)
453 ; CWRLD-NEXT:    br label [[TMP24]]
454 ; CWRLD:       23:
455 ; CWRLD-NEXT:    unreachable
456 ; CWRLD:       24:
457 ; CWRLD-NEXT:    [[CALL_PHI:%.*]] = phi i32 [ [[CALL1]], [[TMP2]] ], [ [[CALL2]], [[TMP5]] ], [ [[CALL3]], [[TMP8]] ], [ [[CALL4]], [[TMP11]] ], [ [[TMP17]], [[TMP14]] ], [ [[CALL5]], [[TMP20]] ], [ [[CALL6]], [[TMP22]] ]
458 ; CWRLD-NEXT:    ret i32 [[CALL_PHI]]
460   %fp = select i1 %c, ptr @retI32, ptr %fn
461   %call = call i32 %fp(i32 42)
462   ret i32 %call
465 ; This function is used in a "direct" call but with a different signature.
466 ; We check that it does not show up above in any of the if-cascades because
467 ; the address is not actually taken.
468 declare void @usedOnlyInCastedDirectCall(i32)
469 define void @usedOnlyInCastedDirectCallCaller() {
470 ; CHECK-LABEL: @usedOnlyInCastedDirectCallCaller(
471 ; CHECK-NEXT:    call void @usedOnlyInCastedDirectCall()
472 ; CHECK-NEXT:    ret void
474   call void @usedOnlyInCastedDirectCall()
475   ret void
478 define internal void @usedByGlobal() {
479 ; CHECK-LABEL: @usedByGlobal(
480 ; CHECK-NEXT:    ret void
482   ret void
484 @G = global ptr @usedByGlobal
486 define void @broker(ptr %unknown) !callback !0 {
487 ; OWRDL-LABEL: @broker(
488 ; OWRDL-NEXT:    call void [[UNKNOWN:%.*]]()
489 ; OWRDL-NEXT:    ret void
491 ; CWRLD-LABEL: @broker(
492 ; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[UNKNOWN:%.*]], @func3
493 ; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
494 ; CWRLD:       2:
495 ; CWRLD-NEXT:    call void @func3()
496 ; CWRLD-NEXT:    br label [[TMP21:%.*]]
497 ; CWRLD:       3:
498 ; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[UNKNOWN]], @func4
499 ; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
500 ; CWRLD:       5:
501 ; CWRLD-NEXT:    call void @func4()
502 ; CWRLD-NEXT:    br label [[TMP21]]
503 ; CWRLD:       6:
504 ; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[UNKNOWN]], @retI32
505 ; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
506 ; CWRLD:       8:
507 ; CWRLD-NEXT:    call void @retI32()
508 ; CWRLD-NEXT:    br label [[TMP21]]
509 ; CWRLD:       9:
510 ; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[UNKNOWN]], @takeI32
511 ; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
512 ; CWRLD:       11:
513 ; CWRLD-NEXT:    call void @takeI32()
514 ; CWRLD-NEXT:    br label [[TMP21]]
515 ; CWRLD:       12:
516 ; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloat
517 ; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]]
518 ; CWRLD:       14:
519 ; CWRLD-NEXT:    call void @retFloatTakeFloat()
520 ; CWRLD-NEXT:    br label [[TMP21]]
521 ; CWRLD:       15:
522 ; CWRLD-NEXT:    [[TMP16:%.*]] = icmp eq ptr [[UNKNOWN]], @retFloatTakeFloatFloatNoundef
523 ; CWRLD-NEXT:    br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]]
524 ; CWRLD:       17:
525 ; CWRLD-NEXT:    call void @retFloatTakeFloatFloatNoundef()
526 ; CWRLD-NEXT:    br label [[TMP21]]
527 ; CWRLD:       18:
528 ; CWRLD-NEXT:    br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]]
529 ; CWRLD:       19:
530 ; CWRLD-NEXT:    call void @void()
531 ; CWRLD-NEXT:    br label [[TMP21]]
532 ; CWRLD:       20:
533 ; CWRLD-NEXT:    unreachable
534 ; CWRLD:       21:
535 ; CWRLD-NEXT:    ret void
537   call void %unknown()
538   ret void
541 define void @func6() {
542 ; CHECK-LABEL: @func6(
543 ; CHECK-NEXT:    call void @broker(ptr nocapture nofree noundef nonnull @func3)
544 ; CHECK-NEXT:    ret void
546   call void @broker(ptr @func3)
547   ret void
550 ; Cannot be internal_good as it is internal and we see all uses.
551 ; Can be func4 since it escapes.
552 define void @func7(ptr %unknown) {
553 ; UPTO2-LABEL: @func7(
554 ; UPTO2-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[UNKNOWN:%.*]], @func3
555 ; UPTO2-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
556 ; UPTO2:       2:
557 ; UPTO2-NEXT:    call void @func3()
558 ; UPTO2-NEXT:    br label [[TMP6:%.*]]
559 ; UPTO2:       3:
560 ; UPTO2-NEXT:    br i1 true, label [[TMP4:%.*]], label [[TMP5:%.*]]
561 ; UPTO2:       4:
562 ; UPTO2-NEXT:    call void @func4()
563 ; UPTO2-NEXT:    br label [[TMP6]]
564 ; UPTO2:       5:
565 ; UPTO2-NEXT:    unreachable
566 ; UPTO2:       6:
567 ; UPTO2-NEXT:    ret void
569 ; LIMI0-LABEL: @func7(
570 ; LIMI0-NEXT:    call void [[UNKNOWN:%.*]](), !callees !1
571 ; LIMI0-NEXT:    ret void
573   call void %unknown(), !callees !2
574   ret void
577 ; Check there's no crash if something that isn't a function appears in !callees
578 define void @undef_in_callees() {
579 ; UNLIM-LABEL: @undef_in_callees(
580 ; UNLIM-NEXT:  cond.end.i:
581 ; UNLIM-NEXT:    call void undef(ptr undef, i32 undef, ptr undef), !callees !2
582 ; UNLIM-NEXT:    ret void
584 ; LIMI2-LABEL: @undef_in_callees(
585 ; LIMI2-NEXT:  cond.end.i:
586 ; LIMI2-NEXT:    call void undef(ptr undef, i32 undef, ptr undef), !callees !4
587 ; LIMI2-NEXT:    ret void
589 ; LIMI0-LABEL: @undef_in_callees(
590 ; LIMI0-NEXT:  cond.end.i:
591 ; LIMI0-NEXT:    call void undef(ptr undef, i32 undef, ptr undef), !callees !6
592 ; LIMI0-NEXT:    ret void
594 cond.end.i:
595   call void undef(ptr undef, i32 undef, ptr undef), !callees !3
596   ret void
599 define void @as_cast(ptr %arg) {
600 ; OWRDL-LABEL: @as_cast(
601 ; OWRDL-NEXT:    [[FP:%.*]] = load ptr addrspace(1), ptr [[ARG:%.*]], align 8
602 ; OWRDL-NEXT:    tail call addrspace(1) void [[FP]]()
603 ; OWRDL-NEXT:    ret void
605 ; CWRLD-LABEL: @as_cast(
606 ; CWRLD-NEXT:    [[FP:%.*]] = load ptr addrspace(1), ptr [[ARG:%.*]], align 8
607 ; CWRLD-NEXT:    [[FP_AS0:%.*]] = addrspacecast ptr addrspace(1) [[FP]] to ptr
608 ; CWRLD-NEXT:    [[TMP1:%.*]] = icmp eq ptr [[FP_AS0]], @func3
609 ; CWRLD-NEXT:    br i1 [[TMP1]], label [[TMP2:%.*]], label [[TMP3:%.*]]
610 ; CWRLD:       2:
611 ; CWRLD-NEXT:    tail call void @func3()
612 ; CWRLD-NEXT:    br label [[TMP21:%.*]]
613 ; CWRLD:       3:
614 ; CWRLD-NEXT:    [[TMP4:%.*]] = icmp eq ptr [[FP_AS0]], @func4
615 ; CWRLD-NEXT:    br i1 [[TMP4]], label [[TMP5:%.*]], label [[TMP6:%.*]]
616 ; CWRLD:       5:
617 ; CWRLD-NEXT:    tail call void @func4()
618 ; CWRLD-NEXT:    br label [[TMP21]]
619 ; CWRLD:       6:
620 ; CWRLD-NEXT:    [[TMP7:%.*]] = icmp eq ptr [[FP_AS0]], @retI32
621 ; CWRLD-NEXT:    br i1 [[TMP7]], label [[TMP8:%.*]], label [[TMP9:%.*]]
622 ; CWRLD:       8:
623 ; CWRLD-NEXT:    call void @retI32()
624 ; CWRLD-NEXT:    br label [[TMP21]]
625 ; CWRLD:       9:
626 ; CWRLD-NEXT:    [[TMP10:%.*]] = icmp eq ptr [[FP_AS0]], @takeI32
627 ; CWRLD-NEXT:    br i1 [[TMP10]], label [[TMP11:%.*]], label [[TMP12:%.*]]
628 ; CWRLD:       11:
629 ; CWRLD-NEXT:    call void @takeI32()
630 ; CWRLD-NEXT:    br label [[TMP21]]
631 ; CWRLD:       12:
632 ; CWRLD-NEXT:    [[TMP13:%.*]] = icmp eq ptr [[FP_AS0]], @retFloatTakeFloat
633 ; CWRLD-NEXT:    br i1 [[TMP13]], label [[TMP14:%.*]], label [[TMP15:%.*]]
634 ; CWRLD:       14:
635 ; CWRLD-NEXT:    call void @retFloatTakeFloat()
636 ; CWRLD-NEXT:    br label [[TMP21]]
637 ; CWRLD:       15:
638 ; CWRLD-NEXT:    [[TMP16:%.*]] = icmp eq ptr [[FP_AS0]], @retFloatTakeFloatFloatNoundef
639 ; CWRLD-NEXT:    br i1 [[TMP16]], label [[TMP17:%.*]], label [[TMP18:%.*]]
640 ; CWRLD:       17:
641 ; CWRLD-NEXT:    call void @retFloatTakeFloatFloatNoundef()
642 ; CWRLD-NEXT:    br label [[TMP21]]
643 ; CWRLD:       18:
644 ; CWRLD-NEXT:    br i1 true, label [[TMP19:%.*]], label [[TMP20:%.*]]
645 ; CWRLD:       19:
646 ; CWRLD-NEXT:    tail call void @void()
647 ; CWRLD-NEXT:    br label [[TMP21]]
648 ; CWRLD:       20:
649 ; CWRLD-NEXT:    unreachable
650 ; CWRLD:       21:
651 ; CWRLD-NEXT:    ret void
653   %fp = load ptr addrspace(1), ptr %arg, align 8
654   tail call addrspace(1) void %fp()
655   ret void
658 !0 = !{!1}
659 !1 = !{i64 0, i1 false}
660 !2 = !{ptr @func3, ptr @func4}
661 !3 = distinct !{ptr undef, ptr null}
663 ; UTC_ARGS: --disable
665 ; DOT-DAG: Node[[FUNC1:0x[a-z0-9]+]] [shape=record,label="{func1}"];
666 ; DOT-DAG: Node[[FUNC2:0x[a-z0-9]+]] [shape=record,label="{func2}"];
667 ; DOT-DAG: Node[[FUNC3:0x[a-z0-9]+]] [shape=record,label="{func3}"];
668 ; DOT-DAG: Node[[FUNC4:0x[a-z0-9]+]] [shape=record,label="{func4}"];
669 ; DOT-DAG: Node[[FUNC5:0x[a-z0-9]+]] [shape=record,label="{func5}"];
670 ; DOT-DAG: Node[[FUNC6:0x[a-z0-9]+]] [shape=record,label="{func6}"];
671 ; DOT-DAG: Node[[FUNC7:0x[a-z0-9]+]] [shape=record,label="{func7}"];
673 ; DOT-DAG: Node[[BROKER:0x[a-z0-9]+]] [shape=record,label="{broker}"];
675 ; DOT-DAG: Node[[FUNC1]] -> Node[[FUNC3]];
676 ; DOT-DAG: Node[[FUNC2]] -> Node[[FUNC4]];
677 ; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC3]];
678 ; DOT-DAG: Node[[FUNC5]] -> Node[[FUNC4]];
680 ; DOT-DAG: Node[[FUNC6]] -> Node[[BROKER]];
682 ; This one gets added because of the callback metadata.
683 ; DOT-DAG: Node[[FUNC6]] -> Node[[FUNC3]];
685 ; These ones are added because of the callees metadata.
686 ; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC3]];
687 ; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC4]];
689 ; UTC_ARGS: --enable
692 ; CHECK: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
694 ; UNLIM: [[META0:![0-9]+]] = !{!1}
695 ; UNLIM: [[META1:![0-9]+]] = !{i64 0, i1 false}
696 ; UNLIM: [[META2:![0-9]+]] = distinct !{ptr undef, ptr null}
698 ; LIMI2: [[META0:![0-9]+]] = !{ptr @void, ptr @retFloatTakeFloat}
699 ; LIMI2: [[META1:![0-9]+]] = !{ptr @void}
700 ; LIMI2: [[META2:![0-9]+]] = !{!3}
701 ; LIMI2: [[META3:![0-9]+]] = !{i64 0, i1 false}
702 ; LIMI2: [[META4:![0-9]+]] = distinct !{ptr undef, ptr null}
704 ; LIMI0: [[META0:![0-9]+]] = !{ptr @func4, ptr @internal_good}
705 ; LIMI0: [[META1:![0-9]+]] = !{ptr @func3, ptr @func4}
706 ; LIMI0: [[META2:![0-9]+]] = !{ptr @takeI32, ptr @retI32, ptr @void, ptr @retFloatTakeFloat}
707 ; LIMI0: [[META3:![0-9]+]] = !{ptr @takeI32, ptr @retI32, ptr @void}
708 ; LIMI0: [[META4:![0-9]+]] = !{!5}
709 ; LIMI0: [[META5:![0-9]+]] = !{i64 0, i1 false}
710 ; LIMI0: [[META6:![0-9]+]] = distinct !{ptr undef, ptr null}
712 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
713 ; DOT: {{.*}}