Skip to content

Commit ad40253

Browse files
committed
!fixup also include linkonce_odr
1 parent c20f3dd commit ad40253

File tree

4 files changed

+126
-4
lines changed

4 files changed

+126
-4
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() || G->hasWeakODRLinkage()) {
895-
assert(G->isInterposable() || G->hasWeakODRLinkage());
894+
if (F->isInterposable() || G->hasWeakODRLinkage() || G->hasLinkOnceODRLinkage()) {
895+
assert(G->isInterposable() || G->hasWeakODRLinkage()|| G->hasLinkOnceODRLinkage());
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/comdat.ll

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ define linkonce_odr hidden i32 @g(i32 %x, i32 %y) comdat {
1919
ret i32 %sum3
2020
}
2121

22-
; CHECK-DAG: define linkonce_odr hidden i32 @f(i32 %x, i32 %y) comdat
23-
; CHECK-DAG: define linkonce_odr hidden i32 @g(i32 %0, i32 %1) comdat
22+
; CHECK-DAG: define private i32 @0(i32 %x, i32 %y) comdat($f)
23+
; CHECK-DAG: define linkonce_odr hidden i32 @g(i32 %0, i32 %1) comdat {
24+
; CHECK-DAG: define linkonce_odr hidden i32 @f(i32 %0, i32 %1) {
2425

llvm/test/Transforms/MergeFunc/linkonce_odr.ll

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,19 @@
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+
; Even a total order based on the names may not be enough, e.g. if @funA calls
11+
; @funB via function pointer in the other module. Then we could end up in
12+
; situations where @funB -> @funA in one module (after merging functions) and
13+
; @funA -> @funB via the a function pointer in the other module.
14+
1015
; CHECK-LABEL: define linkonce_odr i32 @funA
1116
; CHECK-NEXT: add
1217
; CHECK: ret
1318

19+
; CHECK-LABEL: define linkonce_odr i32 @funC
20+
; CHECK-NEXT: tail call i32 @funA(i32 %0, i32 %1)
21+
; CHECK-NEXT: ret
22+
1423
; CHECK-LABEL: define linkonce_odr i32 @funB
1524
; CHECK-NEXT: tail call i32 @funA(i32 %0, i32 %1)
1625
; CHECK-NEXT: ret
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
2+
; RUN: opt -p mergefunc -S %s | FileCheck %s
3+
4+
define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(ptr %p) {
5+
entry:
6+
tail call void @foo(ptr %p)
7+
tail call void @foo(ptr %p)
8+
tail call void @foo(ptr %p)
9+
ret void
10+
}
11+
12+
define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(ptr %p) {
13+
entry:
14+
tail call void @foo(ptr %p)
15+
tail call void @foo(ptr %p)
16+
tail call void @foo(ptr %p)
17+
ret void
18+
}
19+
20+
declare void @foo(ptr)
21+
22+
define hidden void @linkonce_odr_caller_of_bar_1(ptr %p) {
23+
entry:
24+
tail call void @bar(ptr %p)
25+
tail call void @bar(ptr %p)
26+
tail call void @bar(ptr %p)
27+
ret void
28+
}
29+
30+
define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(ptr %p) {
31+
entry:
32+
tail call void @bar(ptr %p)
33+
tail call void @bar(ptr %p)
34+
tail call void @bar(ptr %p)
35+
ret void
36+
}
37+
38+
declare void @bar(ptr)
39+
40+
define hidden void @non_linkonce_caller_of_zar_1(ptr %p) {
41+
entry:
42+
tail call void @zar(ptr %p)
43+
tail call void @zar(ptr %p)
44+
tail call void @zar(ptr %p)
45+
ret void
46+
}
47+
48+
define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(ptr %p) {
49+
entry:
50+
tail call void @zar(ptr %p)
51+
tail call void @zar(ptr %p)
52+
tail call void @zar(ptr %p)
53+
ret void
54+
}
55+
56+
declare void @zar(ptr)
57+
; CHECK-LABEL: define private void @0(
58+
; CHECK-SAME: ptr [[P:%.*]]) {
59+
; CHECK-NEXT: [[ENTRY:.*:]]
60+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
61+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
62+
; CHECK-NEXT: tail call void @foo(ptr [[P]])
63+
; CHECK-NEXT: ret void
64+
;
65+
;
66+
; CHECK-LABEL: define private void @1(
67+
; CHECK-SAME: ptr [[P:%.*]]) {
68+
; CHECK-NEXT: [[ENTRY:.*:]]
69+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
70+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
71+
; CHECK-NEXT: tail call void @bar(ptr [[P]])
72+
; CHECK-NEXT: ret void
73+
;
74+
;
75+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(
76+
; CHECK-SAME: ptr [[P:%.*]]) {
77+
; CHECK-NEXT: [[ENTRY:.*:]]
78+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
79+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
80+
; CHECK-NEXT: tail call void @zar(ptr [[P]])
81+
; CHECK-NEXT: ret void
82+
;
83+
;
84+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(
85+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
86+
; CHECK-NEXT: tail call void @[[GLOB0:[0-9]+]](ptr [[TMP0]])
87+
; CHECK-NEXT: ret void
88+
;
89+
;
90+
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
91+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
92+
; CHECK-NEXT: tail call void @[[GLOB0]](ptr [[TMP0]])
93+
; CHECK-NEXT: ret void
94+
;
95+
;
96+
; CHECK-LABEL: define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(
97+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
98+
; CHECK-NEXT: tail call void @[[GLOB1:[0-9]+]](ptr [[TMP0]])
99+
; CHECK-NEXT: ret void
100+
;
101+
;
102+
; CHECK-LABEL: define hidden void @linkonce_odr_caller_of_bar_1(
103+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
104+
; CHECK-NEXT: tail call void @[[GLOB1]](ptr [[TMP0]])
105+
; CHECK-NEXT: ret void
106+
;
107+
;
108+
; CHECK-LABEL: define hidden void @non_linkonce_caller_of_zar_1(
109+
; CHECK-SAME: ptr [[TMP0:%.*]]) {
110+
; CHECK-NEXT: tail call void @linkonce_odr_caller_of_zar_2(ptr [[TMP0]])
111+
; CHECK-NEXT: ret void
112+
;

0 commit comments

Comments
 (0)