Skip to content

Commit 732f5d7

Browse files
committed
[MergeFuncs] Don't introduce calls to weak_odr functions.
Avoid creating new calls to weak_odr functions when merging 2 functions. Consider 2 functions below, both present in 2 modules. Without this patch, MergeFuncs in the first module may optimize A to call B and in the second module B to call A. Note that the 2 optimizations are vaild in isolation, but the linker then could pick A from module 1 (which calls B) and B from module 2 which calls A, introducing an infinte call cycle. There may be other linkage types we need to be more careful about as well. define weak_odr hidden void @"A"(ptr %p) { entry: tail call void @"foo"(ptr %p) ret void } define weak_odr hidden void @"B"(ptr %p) { entry: tail call void @"foo"(ptr %p) ret void }
1 parent 3a6108b commit 732f5d7

File tree

2 files changed

+2
-63
lines changed

2 files changed

+2
-63
lines changed

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,8 +891,8 @@ 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-
if (F->isInterposable()) {
895-
assert(G->isInterposable());
894+
if (F->isInterposable() || G->hasWeakODRLinkage()) {
895+
assert(G->isInterposable() || G->hasWeakODRLinkage());
896896

897897
// Both writeThunkOrAlias() calls below must succeed, either because we can
898898
// create aliases for G and NewF, or because a thunk for F is profitable.

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

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -85,66 +85,5 @@ 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_1(ptr [[P]])
92-
; CHECK-NEXT: call void @weak_odr_caller_of_foo_1(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_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 weak_odr hidden void @weak_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 weak_odr hidden void @weak_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-
;
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_1(ptr [[TMP0]])
131-
; CHECK-NEXT: ret void
132-
;
133-
;
134-
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_3(
135-
; CHECK-SAME: ptr [[TMP0:%.*]]) {
136-
; CHECK-NEXT: tail call void @weak_odr_caller_of_foo_1(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 @weak_odr_caller_of_bar_2(ptr [[TMP0]])
143-
; CHECK-NEXT: ret void
144-
;
145-
;
146-
; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_zar_2(
147-
; CHECK-SAME: ptr [[TMP0:%.*]]) {
148-
; CHECK-NEXT: tail call void @hidden_caller_of_zar_1(ptr [[TMP0]])
14988
; CHECK-NEXT: ret void
15089
;

0 commit comments

Comments
 (0)