1; RUN: opt < %s -instcombine -attributor-cgscc -print-callgraph -disable-output -verify 2>&1 -enable-new-pm=0 | FileCheck %s
2
3; CHECK: Call graph node <<null function>><<{{.*}}>>  #uses=0
4; CHECK:   CS<None> calls function 'dead_fork_call'
5; CHECK:   CS<None> calls function '.omp_outlined..0'
6; CHECK:   CS<None> calls function '__kmpc_fork_call'
7; CHECK:   CS<None> calls function 'live_fork_call'
8; CHECK:   CS<None> calls function '.omp_outlined..1'
9; CHECK:   CS<None> calls function 'd'
10;
11; CHECK: Call graph node for function: '.omp_outlined..0'<<{{.*}}>>  #uses=1
12;
13; CHECK: Call graph node for function: '.omp_outlined..1'<<{{.*}}>>  #uses=3
14; CHECK:   CS<{{.*}}> calls function 'd'
15;
16; CHECK: Call graph node for function: '__kmpc_fork_call'<<{{.*}}>>  #uses=3
17; CHECK:   CS<None> calls external node
18;
19; CHECK: Call graph node for function: 'd'<<{{.*}}>>  #uses=2
20; CHECK:   CS<None> calls external node
21;
22; CHECK: Call graph node for function: 'dead_fork_call'<<{{.*}}>>  #uses=1
23;
24; CHECK: Call graph node for function: 'dead_fork_call2'<<{{.*}}>>  #uses=0
25; CHECK:   CS<{{.*}}> calls function '__kmpc_fork_call'
26; CHECK:   CS<None> calls function '.omp_outlined..1'
27;
28; CHECK: Call graph node for function: 'live_fork_call'<<{{.*}}>>  #uses=1
29; CHECK:   CS<{{.*}}> calls function '__kmpc_fork_call'
30; CHECK:   CS<None> calls function '.omp_outlined..1'
31
32
33%struct.ident_t = type { i32, i32, i32, i32, i8* }
34
35@.str = private unnamed_addr constant [23 x i8] c";unknown;unknown;0;0;;\00", align 1
36@0 = private unnamed_addr global %struct.ident_t { i32 0, i32 2, i32 0, i32 0, i8* getelementptr inbounds ([23 x i8], [23 x i8]* @.str, i32 0, i32 0) }, align 8
37
38define dso_local void @dead_fork_call() {
39entry:
40  br i1 true, label %if.then, label %if.else
41
42if.then:                                          ; preds = %entry
43  br label %if.end
44
45if.else:                                          ; preds = %entry
46  call void @dead_fork_call2()
47  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..0 to void (i32*, i32*, ...)*))
48  br label %if.end
49
50if.end:                                           ; preds = %if.else, %if.then
51  ret void
52}
53
54define internal void @dead_fork_call2() {
55entry:
56  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*))
57  ret void
58}
59
60define internal void @.omp_outlined..0(i32* noalias %.global_tid., i32* noalias %.bound_tid.) {
61entry:
62  %.global_tid..addr = alloca i32*, align 8
63  %.bound_tid..addr = alloca i32*, align 8
64  store i32* %.global_tid., i32** %.global_tid..addr, align 8
65  store i32* %.bound_tid., i32** %.bound_tid..addr, align 8
66  ret void
67}
68
69declare !callback !2 void @__kmpc_fork_call(%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...)
70
71define dso_local void @live_fork_call() {
72entry:
73  call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @0, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* @.omp_outlined..1 to void (i32*, i32*, ...)*))
74  ret void
75}
76
77define internal void @.omp_outlined..1(i32* noalias %.global_tid., i32* noalias %.bound_tid.) {
78entry:
79  %.global_tid..addr = alloca i32*, align 8
80  %.bound_tid..addr = alloca i32*, align 8
81  store i32* %.global_tid., i32** %.global_tid..addr, align 8
82  store i32* %.bound_tid., i32** %.bound_tid..addr, align 8
83  call void (...) @d()
84  ret void
85}
86
87declare dso_local void @d(...)
88
89!0 = !{i32 1, !"wchar_size", i32 4}
90!1 = !{!"clang version 11.0.0"}
91!2 = !{!3}
92!3 = !{i64 2, i64 -1, i64 -1, i1 true}
93