Skip to content

Commit 6d33732

Browse files
committed
!fixup Document and sort by weak/linkince ODR.
1 parent e088a9b commit 6d33732

File tree

7 files changed

+143
-27
lines changed

7 files changed

+143
-27
lines changed

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,10 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
891891

892892
// Merge two equivalent functions. Upon completion, Function G is deleted.
893893
void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
894+
895+
// Create a new thunk that both F and G can call, if F cannot call G directly.
896+
// That is the case if F is either interposable or if G is either weak_odr or
897+
// linkonce_odr.
894898
if (F->isInterposable() || G->hasWeakODRLinkage() ||
895899
G->hasLinkOnceODRLinkage()) {
896900
assert(G->isInterposable() || G->hasWeakODRLinkage() ||
@@ -993,11 +997,20 @@ static bool isFuncOrderCorrect(const Function *F, const Function *G) {
993997
// one, but not the other way around.
994998
return !F->isInterposable();
995999
}
1000+
1001+
if (F->hasWeakODRLinkage() != G->hasWeakODRLinkage() ||
1002+
F->hasLinkOnceODRLinkage() != G->hasLinkOnceODRLinkage()) {
1003+
// ODR functions before non-ODR functions. A ODR function can call a non-ODR
1004+
// function if it is not interposable, but not the other way around.
1005+
return F->hasWeakODRLinkage() || F->hasLinkOnceODRLinkage();
1006+
}
1007+
9961008
if (F->hasLocalLinkage() != G->hasLocalLinkage()) {
9971009
// External before local, because we definitely have to keep the external
9981010
// function, but may be able to drop the local one.
9991011
return !F->hasLocalLinkage();
10001012
}
1013+
10011014
// Impose a total order (by name) on the replacement of functions. This is
10021015
// important when operating on more than one module independently to prevent
10031016
// cycles of thunks calling each other when the modules are linked together.

llvm/test/Transforms/MergeFunc/linkonce_odr.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,12 @@ define linkonce_odr i32 @funA(i32 %x, i32 %y) {
4545
; CHECK-NEXT: ret i32 [[SUM3]]
4646
;
4747
;
48+
; CHECK-LABEL: define linkonce_odr i32 @funC(
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+
;
53+
;
4854
; CHECK-LABEL: define linkonce_odr i32 @funB(
4955
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
5056
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @funA(i32 [[TMP0]], i32 [[TMP1]])

llvm/test/Transforms/MergeFunc/merge-linkonce-odr-used.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ declare void @foo(ptr)
4242
; CHECK-LABEL: define void @caller_of_callers(
4343
; CHECK-SAME: ptr [[P:%.*]]) {
4444
; 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]])
45+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_2(ptr [[P]])
46+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_3(ptr [[P]])
4747
; CHECK-NEXT: ret void
4848
;
4949
;
50-
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_1(
50+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_3(
5151
; CHECK-SAME: ptr [[P:%.*]]) {
5252
; CHECK-NEXT: [[ENTRY:.*:]]
5353
; CHECK-NEXT: tail call void @foo(ptr [[P]])
@@ -58,12 +58,12 @@ declare void @foo(ptr)
5858
;
5959
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_2(
6060
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61-
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_1(ptr [[TMP0]])
61+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_3(ptr [[TMP0]])
6262
; CHECK-NEXT: ret void
6363
;
6464
;
65-
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_3(
65+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_1(
6666
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67-
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_1(ptr [[TMP0]])
67+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_3(ptr [[TMP0]])
6868
; CHECK-NEXT: ret void
6969
;

llvm/test/Transforms/MergeFunc/merge-linkonce-odr-weak-odr-mixed-used.ll

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ declare void @foo(ptr)
4141
;.
4242
; CHECK-LABEL: define void @caller_of_callers(
4343
; CHECK-SAME: ptr [[P:%.*]]) {
44+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(ptr [[P]])
4445
; 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]])
46+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_3(ptr [[P]])
4747
; CHECK-NEXT: ret void
4848
;
4949
;
50-
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_2(
50+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
5151
; CHECK-SAME: ptr [[P:%.*]]) {
5252
; CHECK-NEXT: [[ENTRY:.*:]]
5353
; CHECK-NEXT: tail call void @foo(ptr [[P]])
@@ -56,14 +56,14 @@ declare void @foo(ptr)
5656
; CHECK-NEXT: ret void
5757
;
5858
;
59-
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
59+
; CHECK-LABEL: define linkonce_odr void @linkonce_odr_caller_of_foo_2(
6060
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61-
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_2(ptr [[TMP0]])
61+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
6262
; CHECK-NEXT: ret void
6363
;
6464
;
65-
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
65+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
6666
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67-
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_2(ptr [[TMP0]])
67+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
6868
; CHECK-NEXT: ret void
6969
;

llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,17 @@ declare void @zar(ptr)
8888
; CHECK-LABEL: define void @caller_of_callers(
8989
; CHECK-SAME: ptr [[P:%.*]]) {
9090
; 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]])
91+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_2(ptr [[P]])
92+
; CHECK-NEXT: call void @linkonce_odr_caller_of_foo_3(ptr [[P]])
9493
; CHECK-NEXT: call void @linkonce_odr_caller_of_bar_2(ptr [[P]])
9594
; 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]])
95+
; CHECK-NEXT: call void @linkonce_odr_caller_of_bar_3(ptr [[P]])
96+
; CHECK-NEXT: call void @linkonce_odr_caller_of_zar_2(ptr [[P]])
97+
; CHECK-NEXT: call void @linkonce_odr_caller_of_zar_2(ptr [[P]])
9898
; CHECK-NEXT: ret void
9999
;
100100
;
101-
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
101+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_3(
102102
; CHECK-SAME: ptr [[P:%.*]]) {
103103
; CHECK-NEXT: [[ENTRY:.*:]]
104104
; CHECK-NEXT: tail call void @foo(ptr [[P]])
@@ -107,7 +107,7 @@ declare void @zar(ptr)
107107
; CHECK-NEXT: ret void
108108
;
109109
;
110-
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_bar_2(
110+
; CHECK-LABEL: define private void @0(
111111
; CHECK-SAME: ptr [[P:%.*]]) {
112112
; CHECK-NEXT: [[ENTRY:.*:]]
113113
; CHECK-NEXT: tail call void @bar(ptr [[P]])
@@ -116,11 +116,41 @@ declare void @zar(ptr)
116116
; CHECK-NEXT: ret void
117117
;
118118
;
119-
; CHECK-LABEL: define hidden void @hidden_caller_of_zar_1(
119+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(
120120
; CHECK-SAME: ptr [[P:%.*]]) {
121121
; CHECK-NEXT: [[ENTRY:.*:]]
122122
; CHECK-NEXT: tail call void @zar(ptr [[P]])
123123
; CHECK-NEXT: tail call void @zar(ptr [[P]])
124124
; CHECK-NEXT: tail call void @zar(ptr [[P]])
125125
; CHECK-NEXT: ret void
126126
;
127+
;
128+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(
129+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
130+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_3(ptr [[TMP0]])
131+
; CHECK-NEXT: ret void
132+
;
133+
;
134+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
135+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
136+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_foo_3(ptr [[TMP0]])
137+
; CHECK-NEXT: ret void
138+
;
139+
;
140+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_bar_3(
141+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
142+
; CHECK-NEXT: tail call void @[[GLOB0:[0-9]+]](ptr [[TMP0]])
143+
; CHECK-NEXT: ret void
144+
;
145+
;
146+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_bar_2(
147+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
148+
; CHECK-NEXT: tail call void @[[GLOB0]](ptr [[TMP0]])
149+
; CHECK-NEXT: ret void
150+
;
151+
;
152+
; CHECK-LABEL: define hidden void @hidden_caller_of_zar_1(
153+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
154+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_zar_2(ptr [[TMP0]])
155+
; CHECK-NEXT: ret void
156+
;

llvm/test/Transforms/MergeFunc/merge-weak-odr-used.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ declare void @foo(ptr)
4242
; CHECK-LABEL: define void @caller_of_callers(
4343
; CHECK-SAME: ptr [[P:%.*]]) {
4444
; 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]])
45+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_2(ptr [[P]])
46+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_3(ptr [[P]])
4747
; CHECK-NEXT: ret void
4848
;
4949
;
50-
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
50+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
5151
; CHECK-SAME: ptr [[P:%.*]]) {
5252
; CHECK-NEXT: [[ENTRY:.*:]]
5353
; CHECK-NEXT: tail call void @foo(ptr [[P]])
@@ -58,12 +58,12 @@ declare void @foo(ptr)
5858
;
5959
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_2(
6060
; CHECK-SAME: ptr [[TMP0:%.*]]) {
61-
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
61+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
6262
; CHECK-NEXT: ret void
6363
;
6464
;
65-
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_3(
65+
; CHECK-LABEL: define weak_odr void @weak_odr_caller_of_foo_1(
6666
; CHECK-SAME: ptr [[TMP0:%.*]]) {
67-
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
67+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
6868
; CHECK-NEXT: ret void
6969
;

llvm/test/Transforms/MergeFunc/merge-weak-odr.ll

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,72 @@ entry:
8585
}
8686

8787
declare void @zar(ptr)
88+
; CHECK-LABEL: define void @caller_of_callers(
89+
; CHECK-SAME: ptr [[P:%.*]]) {
90+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(ptr [[P]])
91+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_2(ptr [[P]])
92+
; CHECK-NEXT: call void @weak_odr_caller_of_foo_3(ptr [[P]])
93+
; CHECK-NEXT: call void @weak_odr_caller_of_bar_2(ptr [[P]])
94+
; CHECK-NEXT: call void @weak_odr_caller_of_bar_2(ptr [[P]])
95+
; CHECK-NEXT: call void @weak_odr_caller_of_bar_3(ptr [[P]])
96+
; CHECK-NEXT: call void @weak_odr_caller_of_zar_2(ptr [[P]])
97+
; CHECK-NEXT: call void @weak_odr_caller_of_zar_2(ptr [[P]])
98+
; CHECK-NEXT: ret void
99+
;
100+
;
101+
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_3(
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 private void @0(
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 weak_odr hidden void @weak_odr_caller_of_zar_2(
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+
;
127+
;
128+
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_2(
129+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
130+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
131+
; CHECK-NEXT: ret void
132+
;
133+
;
134+
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_1(
135+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
136+
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_3(ptr [[TMP0]])
137+
; CHECK-NEXT: ret void
138+
;
139+
;
140+
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_bar_3(
141+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
142+
; CHECK-NEXT: tail call void @[[GLOB0:[0-9]+]](ptr [[TMP0]])
143+
; CHECK-NEXT: ret void
144+
;
145+
;
146+
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_bar_2(
147+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
148+
; CHECK-NEXT: tail call void @[[GLOB0]](ptr [[TMP0]])
149+
; CHECK-NEXT: ret void
150+
;
151+
;
152+
; CHECK-LABEL: define hidden void @hidden_caller_of_zar_1(
153+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
154+
; CHECK-NEXT: tail call void @weak_odr_caller_of_zar_2(ptr [[TMP0]])
88155
; CHECK-NEXT: ret void
89156
;

0 commit comments

Comments
 (0)