Skip to content

Commit aa77085

Browse files
committed
[MergeFunc] Add tests for (merging weak|linkonce)_odr functions.
Tests for llvm#125050.
1 parent 363bfd6 commit aa77085

File tree

6 files changed

+500
-7
lines changed

6 files changed

+500
-7
lines changed

llvm/test/Transforms/MergeFunc/linkonce_odr.ll

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
12
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s -implicit-check-not=funC
23

34
; Replacments should be totally ordered on the function name.
45
; If we don't do this we can end up with one module defining a thunk for @funA
56
; and another module defining a thunk for @funB.
6-
;
77
; The problem with this is that the linker could then choose these two stubs
88
; each of the two modules and we end up with two stubs calling each other.
99

10-
; CHECK-LABEL: define linkonce_odr i32 @funA
11-
; CHECK-NEXT: add
12-
; CHECK: ret
1310

14-
; CHECK-LABEL: define linkonce_odr i32 @funB
15-
; CHECK-NEXT: tail call i32 @funA(i32 %0, i32 %1)
16-
; CHECK-NEXT: ret
1711

1812
define linkonce_odr i32 @funC(i32 %x, i32 %y) {
1913
%sum = add i32 %x, %y
@@ -40,3 +34,19 @@ define linkonce_odr i32 @funA(i32 %x, i32 %y) {
4034
; @funC, however, can safely be deleted as it has no uses, and is discardable
4135
; if unused.
4236
@take_addr_of_funB = global ptr @funB
37+
;.
38+
; CHECK: @take_addr_of_funB = global ptr @funB
39+
;.
40+
; CHECK-LABEL: define linkonce_odr i32 @funA(
41+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
42+
; CHECK-NEXT: [[SUM:%.*]] = add i32 [[X]], [[Y]]
43+
; CHECK-NEXT: [[SUM2:%.*]] = add i32 [[X]], [[SUM]]
44+
; CHECK-NEXT: [[SUM3:%.*]] = add i32 [[X]], [[SUM2]]
45+
; CHECK-NEXT: ret i32 [[SUM3]]
46+
;
47+
;
48+
; CHECK-LABEL: define linkonce_odr i32 @funB(
49+
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
50+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @funA(i32 [[TMP0]], i32 [[TMP1]])
51+
; CHECK-NEXT: ret i32 [[TMP3]]
52+
;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2+
; RUN: opt -p mergefunc -S %s | FileCheck %s
3+
4+
@llvm.used = appending global [3 x ptr] [ptr @linkonce_odr_caller_of_foo_1, ptr @linkonce_odr_caller_of_foo_2, ptr @linkonce_odr_caller_of_foo_3]
5+
6+
define void @caller_of_callers(ptr %p) {
7+
call void @linkonce_odr_caller_of_foo_1(ptr %p)
8+
call void @linkonce_odr_caller_of_foo_2(ptr %p)
9+
call void @linkonce_odr_caller_of_foo_3(ptr %p)
10+
ret void
11+
}
12+
13+
define linkonce_odr void @linkonce_odr_caller_of_foo_1(ptr %p) {
14+
entry:
15+
tail call void @foo(ptr %p)
16+
tail call void @foo(ptr %p)
17+
tail call void @foo(ptr %p)
18+
ret void
19+
}
20+
21+
define linkonce_odr void @linkonce_odr_caller_of_foo_2(ptr %p) {
22+
entry:
23+
tail call void @foo(ptr %p)
24+
tail call void @foo(ptr %p)
25+
tail call void @foo(ptr %p)
26+
ret void
27+
}
28+
29+
define linkonce_odr void @linkonce_odr_caller_of_foo_3(ptr %p) {
30+
entry:
31+
tail call void @foo(ptr %p)
32+
tail call void @foo(ptr %p)
33+
tail call void @foo(ptr %p)
34+
ret void
35+
}
36+
37+
declare void @foo(ptr)
38+
39+
;.
40+
; CHECK: @llvm.used = appending global [3 x ptr] [ptr @linkonce_odr_caller_of_foo_1, ptr @linkonce_odr_caller_of_foo_2, ptr @linkonce_odr_caller_of_foo_3]
41+
;.
42+
; CHECK-LABEL: define void @caller_of_callers(
43+
; CHECK-SAME: ptr [[P:%.*]]) {
44+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
45+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
46+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
47+
; CHECK-NEXT: ret void
48+
;
49+
;
50+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_1(
51+
; CHECK-SAME: ptr [[P:%.*]]) {
52+
; CHECK-NEXT: [[ENTRY:.*:]]
53+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
54+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
55+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
56+
; CHECK-NEXT: ret void
57+
;
58+
;
59+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_2(
60+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_1(ptr [[TMP0]])
62+
; CHECK-NEXT: ret void
63+
;
64+
;
65+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_3(
66+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_1(ptr [[TMP0]])
68+
; CHECK-NEXT: ret void
69+
;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2+
; RUN: opt -p mergefunc -S %s | FileCheck %s
3+
4+
@llvm.used = appending global [3 x ptr] [ptr @weak_odr_caller_of_foo_1, ptr @linkonce_odr_caller_of_foo_2, ptr @weak_odr_caller_of_foo_3]
5+
6+
define void @caller_of_callers(ptr %p) {
7+
call void @weak_odr_caller_of_foo_1(ptr %p)
8+
call void @linkonce_odr_caller_of_foo_2(ptr %p)
9+
call void @weak_odr_caller_of_foo_3(ptr %p)
10+
ret void
11+
}
12+
13+
define weak_odr void @weak_odr_caller_of_foo_1(ptr %p) {
14+
entry:
15+
tail call void @foo(ptr %p)
16+
tail call void @foo(ptr %p)
17+
tail call void @foo(ptr %p)
18+
ret void
19+
}
20+
21+
define linkonce_odr void @linkonce_odr_caller_of_foo_2(ptr %p) {
22+
entry:
23+
tail call void @foo(ptr %p)
24+
tail call void @foo(ptr %p)
25+
tail call void @foo(ptr %p)
26+
ret void
27+
}
28+
29+
define weak_odr void @weak_odr_caller_of_foo_3(ptr %p) {
30+
entry:
31+
tail call void @foo(ptr %p)
32+
tail call void @foo(ptr %p)
33+
tail call void @foo(ptr %p)
34+
ret void
35+
}
36+
37+
declare void @foo(ptr)
38+
39+
;.
40+
; CHECK: @llvm.used = appending global [3 x ptr] [ptr @weak_odr_caller_of_foo_1, ptr @linkonce_odr_caller_of_foo_2, ptr @weak_odr_caller_of_foo_3]
41+
;.
42+
; CHECK-LABEL: define void @caller_of_callers(
43+
; CHECK-SAME: ptr [[P:%.*]]) {
44+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_2(ptr [[P]])
45+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_2(ptr [[P]])
46+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_2(ptr [[P]])
47+
; CHECK-NEXT: ret void
48+
;
49+
;
50+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_2(
51+
; CHECK-SAME: ptr [[P:%.*]]) {
52+
; CHECK-NEXT: [[ENTRY:.*:]]
53+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
54+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
55+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
56+
; CHECK-NEXT: ret void
57+
;
58+
;
59+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
60+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_2(ptr [[TMP0]])
62+
; CHECK-NEXT: ret void
63+
;
64+
;
65+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
66+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_2(ptr [[TMP0]])
68+
; CHECK-NEXT: ret void
69+
;
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2+
; RUN: opt -p mergefunc -S %s | FileCheck %s
3+
4+
define void @caller_of_callers(ptr %p) {
5+
call void @linkonce_odr_caller_of_foo_1(ptr %p)
6+
call void @linkonce_odr_caller_of_foo_2(ptr %p)
7+
call void @linkonce_odr_caller_of_foo_3(ptr %p)
8+
9+
call void @internal_caller_of_bar_1(ptr %p)
10+
call void @linkonce_odr_caller_of_bar_2(ptr %p)
11+
call void @linkonce_odr_caller_of_bar_3(ptr %p)
12+
13+
call void @hidden_caller_of_zar_1(ptr %p)
14+
call void @linkonce_odr_caller_of_zar_2(ptr %p)
15+
16+
ret void
17+
}
18+
19+
define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(ptr %p) {
20+
entry:
21+
tail call void @foo(ptr %p)
22+
tail call void @foo(ptr %p)
23+
tail call void @foo(ptr %p)
24+
ret void
25+
}
26+
27+
define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(ptr %p) {
28+
entry:
29+
tail call void @foo(ptr %p)
30+
tail call void @foo(ptr %p)
31+
tail call void @foo(ptr %p)
32+
ret void
33+
}
34+
35+
define linkonce_odr hidden void @linkonce_odr_caller_of_foo_3(ptr %p) {
36+
entry:
37+
tail call void @foo(ptr %p)
38+
tail call void @foo(ptr %p)
39+
tail call void @foo(ptr %p)
40+
ret void
41+
}
42+
43+
declare void @foo(ptr)
44+
45+
define internal void @internal_caller_of_bar_1(ptr %p) {
46+
entry:
47+
tail call void @bar(ptr %p)
48+
tail call void @bar(ptr %p)
49+
tail call void @bar(ptr %p)
50+
ret void
51+
}
52+
53+
define linkonce_odr hidden void @linkonce_odr_caller_of_bar_2(ptr %p) {
54+
entry:
55+
tail call void @bar(ptr %p)
56+
tail call void @bar(ptr %p)
57+
tail call void @bar(ptr %p)
58+
ret void
59+
}
60+
61+
define linkonce_odr hidden void @linkonce_odr_caller_of_bar_3(ptr %p) {
62+
entry:
63+
tail call void @bar(ptr %p)
64+
tail call void @bar(ptr %p)
65+
tail call void @bar(ptr %p)
66+
ret void
67+
}
68+
69+
declare void @bar(ptr)
70+
71+
define hidden void @hidden_caller_of_zar_1(ptr %p) {
72+
entry:
73+
tail call void @zar(ptr %p)
74+
tail call void @zar(ptr %p)
75+
tail call void @zar(ptr %p)
76+
ret void
77+
}
78+
79+
define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(ptr %p) {
80+
entry:
81+
tail call void @zar(ptr %p)
82+
tail call void @zar(ptr %p)
83+
tail call void @zar(ptr %p)
84+
ret void
85+
}
86+
87+
declare void @zar(ptr)
88+
; CHECK-LABEL: define void @caller_of_callers(
89+
; CHECK-SAME: ptr [[P:%.*]]) {
90+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
91+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
92+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_1(ptr [[P]])
93+
; CHECK-NEXT: call void @linkonce_odr_caller_of_bar_2(ptr [[P]])
94+
; CHECK-NEXT: call void @linkonce_odr_caller_of_bar_2(ptr [[P]])
95+
; CHECK-NEXT: call void @linkonce_odr_caller_of_bar_2(ptr [[P]])
96+
; CHECK-NEXT: call void @hidden_caller_of_zar_1(ptr [[P]])
97+
; CHECK-NEXT: call void @hidden_caller_of_zar_1(ptr [[P]])
98+
; CHECK-NEXT: ret void
99+
;
100+
;
101+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
102+
; CHECK-SAME: ptr [[P:%.*]]) {
103+
; CHECK-NEXT: [[ENTRY:.*:]]
104+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
105+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
106+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
107+
; CHECK-NEXT: ret void
108+
;
109+
;
110+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_bar_2(
111+
; CHECK-SAME: ptr [[P:%.*]]) {
112+
; CHECK-NEXT: [[ENTRY:.*:]]
113+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
114+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
115+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
116+
; CHECK-NEXT: ret void
117+
;
118+
;
119+
; CHECK-LABEL: define hidden void @hidden_caller_of_zar_1(
120+
; CHECK-SAME: ptr [[P:%.*]]) {
121+
; CHECK-NEXT: [[ENTRY:.*:]]
122+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
123+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
124+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
125+
; CHECK-NEXT: ret void
126+
;
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2+
; RUN: opt -p mergefunc -S %s | FileCheck %s
3+
4+
@llvm.used = appending global [3 x ptr] [ptr @weak_odr_caller_of_foo_1, ptr @weak_odr_caller_of_foo_2, ptr @weak_odr_caller_of_foo_3]
5+
6+
define void @caller_of_callers(ptr %p) {
7+
call void @weak_odr_caller_of_foo_1(ptr %p)
8+
call void @weak_odr_caller_of_foo_2(ptr %p)
9+
call void @weak_odr_caller_of_foo_3(ptr %p)
10+
ret void
11+
}
12+
13+
define weak_odr void @weak_odr_caller_of_foo_1(ptr %p) {
14+
entry:
15+
tail call void @foo(ptr %p)
16+
tail call void @foo(ptr %p)
17+
tail call void @foo(ptr %p)
18+
ret void
19+
}
20+
21+
define weak_odr void @weak_odr_caller_of_foo_2(ptr %p) {
22+
entry:
23+
tail call void @foo(ptr %p)
24+
tail call void @foo(ptr %p)
25+
tail call void @foo(ptr %p)
26+
ret void
27+
}
28+
29+
define weak_odr void @weak_odr_caller_of_foo_3(ptr %p) {
30+
entry:
31+
tail call void @foo(ptr %p)
32+
tail call void @foo(ptr %p)
33+
tail call void @foo(ptr %p)
34+
ret void
35+
}
36+
37+
declare void @foo(ptr)
38+
39+
;.
40+
; CHECK: @llvm.used = appending global [3 x ptr] [ptr @weak_odr_caller_of_foo_1, ptr @weak_odr_caller_of_foo_2, ptr @weak_odr_caller_of_foo_3]
41+
;.
42+
; CHECK-LABEL: define void @caller_of_callers(
43+
; CHECK-SAME: ptr [[P:%.*]]) {
44+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(ptr [[P]])
45+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(ptr [[P]])
46+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(ptr [[P]])
47+
; CHECK-NEXT: ret void
48+
;
49+
;
50+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
51+
; CHECK-SAME: ptr [[P:%.*]]) {
52+
; CHECK-NEXT: [[ENTRY:.*:]]
53+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
54+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
55+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
56+
; CHECK-NEXT: ret void
57+
;
58+
;
59+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_2(
60+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
62+
; CHECK-NEXT: ret void
63+
;
64+
;
65+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
66+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
68+
; CHECK-NEXT: ret void
69+
;

0 commit comments

Comments
 (0)