xref: /llvm-project/llvm/test/Transforms/Attributor/callgraph.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
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
7
8;.
9; CHECK: @G = global ptr @usedByGlobal
10;.
11define 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
19;
20  %1 = icmp ne i32 0, 0
21  br i1 %1, label %2, label %3
22
232:                                                ; preds = %0
24  call void @func2(i1 false)
25  br label %3
26
273:                                                ; preds = %2, %0
28  call void () @func3()
29  ret void
30}
31
32declare void @func3()
33define internal void @func4() {
34; CHECK-LABEL: @func4(
35; CHECK-NEXT:    call void @func3()
36; CHECK-NEXT:    ret void
37;
38  call void @func3()
39  ret void
40}
41define internal void @internal_good() {
42; CHECK-LABEL: @internal_good(
43; CHECK-NEXT:    call void @void(ptr @func4)
44; CHECK-NEXT:    ret void
45;
46  call void @void(ptr @func4)
47  ret void
48}
49
50define 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
67;
68; LIMI0-LABEL: @func2(
69; LIMI0-NEXT:    [[F:%.*]] = select i1 [[C:%.*]], ptr @internal_good, ptr @func4
70; LIMI0-NEXT:    call void [[F]](), !callees [[META0:![0-9]+]]
71; LIMI0-NEXT:    ret void
72;
73  %f = select i1 %c, ptr @internal_good, ptr @func4
74  call void %f()
75  ret void
76}
77
78
79define 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
97;
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 [[META1:![0-9]+]]
102; LIMI0-NEXT:    ret void
103;
104  %2 = icmp ne i32 %0, 0
105  %3 = select i1 %2, ptr @func4, ptr @func3
106  call void () %3()
107  ret void
108}
109
110define 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]]
116;
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
121}
122
123declare i32 @retI32()
124declare void @takeI32(i32)
125declare float @retFloatTakeFloat(float)
126; This callee is always filtered out because of the noundef argument
127declare float @retFloatTakeFloatFloatNoundef(float, float noundef)
128declare void @void()
129
130define 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]]
164;
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 [[META0:![0-9]+]]
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]]
186;
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 [[META2:![0-9]+]]
192; LIMI0-NEXT:    ret i32 [[CALL]]
193;
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
199}
200
201define 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]]
227;
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 [[META1:![0-9]+]]
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]]
249;
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 [[META3:![0-9]+]]
255; LIMI0-NEXT:    ret i32 [[CALL]]
256;
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
262}
263
264define 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
291;
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
312;
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
319;
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
368;
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
374}
375
376define 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]]
390;
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]]
404;
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]]
409;
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]]
459;
460  %fp = select i1 %c, ptr @retI32, ptr %fn
461  %call = call i32 %fp(i32 42)
462  ret i32 %call
463}
464
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.
468declare void @usedOnlyInCastedDirectCall(i32)
469define void @usedOnlyInCastedDirectCallCaller() {
470; CHECK-LABEL: @usedOnlyInCastedDirectCallCaller(
471; CHECK-NEXT:    call void @usedOnlyInCastedDirectCall()
472; CHECK-NEXT:    ret void
473;
474  call void @usedOnlyInCastedDirectCall()
475  ret void
476}
477
478define internal void @usedByGlobal() {
479; CHECK-LABEL: @usedByGlobal(
480; CHECK-NEXT:    ret void
481;
482  ret void
483}
484@G = global ptr @usedByGlobal
485
486define void @broker(ptr %unknown) !callback !0 {
487; OWRDL-LABEL: @broker(
488; OWRDL-NEXT:    call void [[UNKNOWN:%.*]]()
489; OWRDL-NEXT:    ret void
490;
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
536;
537  call void %unknown()
538  ret void
539}
540
541define void @func6() {
542; CHECK-LABEL: @func6(
543; CHECK-NEXT:    call void @broker(ptr nofree noundef nonnull captures(none) @func3)
544; CHECK-NEXT:    ret void
545;
546  call void @broker(ptr @func3)
547  ret void
548}
549
550; Cannot be internal_good as it is internal and we see all uses.
551; Can be func4 since it escapes.
552define 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
568;
569; LIMI0-LABEL: @func7(
570; LIMI0-NEXT:    call void [[UNKNOWN:%.*]](), !callees [[META1]]
571; LIMI0-NEXT:    ret void
572;
573  call void %unknown(), !callees !2
574  ret void
575}
576
577; Check there's no crash if something that isn't a function appears in !callees
578define 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 [[META2:![0-9]+]]
582; UNLIM-NEXT:    ret void
583;
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 [[META4:![0-9]+]]
587; LIMI2-NEXT:    ret void
588;
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 [[META6:![0-9]+]]
592; LIMI0-NEXT:    ret void
593;
594cond.end.i:
595  call void undef(ptr undef, i32 undef, ptr undef), !callees !3
596  ret void
597}
598
599define 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
604;
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
652;
653  %fp = load ptr addrspace(1), ptr %arg, align 8
654  tail call addrspace(1) void %fp()
655  ret void
656}
657
658!0 = !{!1}
659!1 = !{i64 0, i1 false}
660!2 = !{ptr @func3, ptr @func4}
661!3 = distinct !{ptr undef, ptr null}
662
663; UTC_ARGS: --disable
664
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}"];
672
673; DOT-DAG: Node[[BROKER:0x[a-z0-9]+]] [shape=record,label="{broker}"];
674
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]];
679
680; DOT-DAG: Node[[FUNC6]] -> Node[[BROKER]];
681
682; This one gets added because of the callback metadata.
683; DOT-DAG: Node[[FUNC6]] -> Node[[FUNC3]];
684
685; These ones are added because of the callees metadata.
686; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC3]];
687; DOT-DAG: Node[[FUNC7]] -> Node[[FUNC4]];
688
689; UTC_ARGS: --enable
690
691;.
692; OUNLM: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
693;.
694; LIMI2: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
695;.
696; LIMI0: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
697;.
698; CWRLD: attributes #[[ATTR0:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
699;.
700; OUNLM: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]}
701; OUNLM: [[META1]] = !{i64 0, i1 false}
702; OUNLM: [[META2]] = distinct !{ptr undef, ptr null}
703;.
704; LIMI2: [[META0]] = !{ptr @void, ptr @retFloatTakeFloat}
705; LIMI2: [[META1]] = !{ptr @void}
706; LIMI2: [[META2:![0-9]+]] = !{[[META3:![0-9]+]]}
707; LIMI2: [[META3]] = !{i64 0, i1 false}
708; LIMI2: [[META4]] = distinct !{ptr undef, ptr null}
709;.
710; LIMI0: [[META0]] = !{ptr @func4, ptr @internal_good}
711; LIMI0: [[META1]] = !{ptr @func3, ptr @func4}
712; LIMI0: [[META2]] = !{ptr @takeI32, ptr @retI32, ptr @void, ptr @retFloatTakeFloat}
713; LIMI0: [[META3]] = !{ptr @takeI32, ptr @retI32, ptr @void}
714; LIMI0: [[META4:![0-9]+]] = !{[[META5:![0-9]+]]}
715; LIMI0: [[META5]] = !{i64 0, i1 false}
716; LIMI0: [[META6]] = distinct !{ptr undef, ptr null}
717;.
718; CWRLD: [[META0:![0-9]+]] = !{[[META1:![0-9]+]]}
719; CWRLD: [[META1]] = !{i64 0, i1 false}
720; CWRLD: [[META2]] = distinct !{ptr undef, ptr null}
721;.
722;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
723; DOT: {{.*}}
724