[llvm] [MergeFuncs] Don't introduce calls to {linkonce,weak}_odr functions. (PR #125050)

Florian Hahn via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 3 10:37:50 PST 2025


https://github.com/fhahn updated https://github.com/llvm/llvm-project/pull/125050

>From bac50fc3f1284eb425811d185a8b0c0a94a7daec Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Jan 2025 11:32:06 +0000
Subject: [PATCH 1/5] [MergeFunc] Add tests for merging weak_odr functions.

---
 .../Transforms/MergeFunc/merge-weak-odr.ll    | 100 ++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 llvm/test/Transforms/MergeFunc/merge-weak-odr.ll

diff --git a/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
new file mode 100644
index 00000000000000..6afa14c7ec439f
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
+; RUN: opt -p mergefunc -S %s | FileCheck %s
+
+define weak_odr hidden void @weak_odr_caller_of_foo_1(ptr %p) {
+entry:
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  ret void
+}
+
+define weak_odr hidden void @weak_odr_caller_of_foo_2(ptr %p) {
+entry:
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  ret void
+}
+
+declare void @foo(ptr)
+
+define hidden void @weak_odr_caller_of_bar_1(ptr %p) {
+entry:
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  ret void
+}
+
+define weak_odr hidden void @non_weak_caller_of_bar_2(ptr %p) {
+entry:
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  ret void
+}
+
+declare void @bar(ptr)
+
+define hidden void @non_weak_caller_of_zar_1(ptr %p) {
+entry:
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  ret void
+}
+
+define weak_odr hidden void @weak_odr_caller_of_zar_2(ptr %p) {
+entry:
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  ret void
+}
+
+declare void @zar(ptr)
+; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_1(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define weak_odr hidden void @non_weak_caller_of_bar_2(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define hidden void @non_weak_caller_of_zar_1(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_2(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define hidden void @weak_odr_caller_of_bar_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @non_weak_caller_of_bar_2(ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_zar_2(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @non_weak_caller_of_zar_1(ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;

>From b63fe110bd098e839c55d590e0602e3d57095229 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Jan 2025 11:33:12 +0000
Subject: [PATCH 2/5] [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
    }
---
 llvm/lib/Transforms/IPO/MergeFunctions.cpp    |  4 ++--
 .../Transforms/MergeFunc/merge-weak-odr.ll    | 20 +++++++++++++++----
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index e8508416f54275..d991ec64445ee9 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -891,8 +891,8 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
 
 // Merge two equivalent functions. Upon completion, Function G is deleted.
 void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
-  if (F->isInterposable()) {
-    assert(G->isInterposable());
+  if (F->isInterposable() || G->hasWeakODRLinkage()) {
+    assert(G->isInterposable() || G->hasWeakODRLinkage());
 
     // Both writeThunkOrAlias() calls below must succeed, either because we can
     // create aliases for G and NewF, or because a thunk for F is profitable.
diff --git a/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
index 6afa14c7ec439f..d2e89092b9a826 100644
--- a/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
+++ b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
@@ -54,7 +54,7 @@ entry:
 }
 
 declare void @zar(ptr)
-; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_1(
+; CHECK-LABEL: define private void @0(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    tail call void @foo(ptr [[P]])
@@ -72,7 +72,7 @@ declare void @zar(ptr)
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define hidden void @non_weak_caller_of_zar_1(
+; CHECK-LABEL: define private void @1(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    tail call void @zar(ptr [[P]])
@@ -83,7 +83,13 @@ declare void @zar(ptr)
 ;
 ; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_2(
 ; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @weak_odr_caller_of_foo_1(ptr [[TMP0]])
+; CHECK-NEXT:    tail call void @[[GLOB0:[0-9]+]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_foo_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB0]](ptr [[TMP0]])
 ; CHECK-NEXT:    ret void
 ;
 ;
@@ -95,6 +101,12 @@ declare void @zar(ptr)
 ;
 ; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_zar_2(
 ; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @non_weak_caller_of_zar_1(ptr [[TMP0]])
+; CHECK-NEXT:    tail call void @[[GLOB1:[0-9]+]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define hidden void @non_weak_caller_of_zar_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB1]](ptr [[TMP0]])
 ; CHECK-NEXT:    ret void
 ;

>From 0fa5a34133a76fabba4b29ce00908064ec4a436f Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Jan 2025 16:06:02 +0000
Subject: [PATCH 3/5] !fixup also include linkonce_odr

---
 llvm/lib/Transforms/IPO/MergeFunctions.cpp    |   4 +-
 llvm/test/Transforms/MergeFunc/comdat.ll      |   5 +-
 .../test/Transforms/MergeFunc/linkonce_odr.ll |   9 ++
 .../MergeFunc/merge-linkonce-odr.ll           | 112 ++++++++++++++++++
 4 files changed, 126 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll

diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index d991ec64445ee9..ea5e102156ff76 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -891,8 +891,8 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
 
 // Merge two equivalent functions. Upon completion, Function G is deleted.
 void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
-  if (F->isInterposable() || G->hasWeakODRLinkage()) {
-    assert(G->isInterposable() || G->hasWeakODRLinkage());
+  if (F->isInterposable() || G->hasWeakODRLinkage() || G->hasLinkOnceODRLinkage()) {
+    assert(G->isInterposable() || G->hasWeakODRLinkage()|| G->hasLinkOnceODRLinkage());
 
     // Both writeThunkOrAlias() calls below must succeed, either because we can
     // create aliases for G and NewF, or because a thunk for F is profitable.
diff --git a/llvm/test/Transforms/MergeFunc/comdat.ll b/llvm/test/Transforms/MergeFunc/comdat.ll
index f6e104625bc414..3770c772b3f88e 100644
--- a/llvm/test/Transforms/MergeFunc/comdat.ll
+++ b/llvm/test/Transforms/MergeFunc/comdat.ll
@@ -19,6 +19,7 @@ define linkonce_odr hidden i32 @g(i32 %x, i32 %y) comdat {
   ret i32 %sum3
 }
 
-; CHECK-DAG: define linkonce_odr hidden i32 @f(i32 %x, i32 %y) comdat
-; CHECK-DAG: define linkonce_odr hidden i32 @g(i32 %0, i32 %1) comdat
+; CHECK-DAG: define private i32 @0(i32 %x, i32 %y) comdat($f)
+; CHECK-DAG: define linkonce_odr hidden i32 @g(i32 %0, i32 %1) comdat {
+; CHECK-DAG: define linkonce_odr hidden i32 @f(i32 %0, i32 %1) {
 
diff --git a/llvm/test/Transforms/MergeFunc/linkonce_odr.ll b/llvm/test/Transforms/MergeFunc/linkonce_odr.ll
index 23305c04f7b6f4..f403d914eb0f1c 100644
--- a/llvm/test/Transforms/MergeFunc/linkonce_odr.ll
+++ b/llvm/test/Transforms/MergeFunc/linkonce_odr.ll
@@ -7,10 +7,19 @@
 ; The problem with this is that the linker could then choose these two stubs
 ; each of the two modules and we end up with two stubs calling each other.
 
+; Even a total order based on the names may not be enough, e.g. if @funA calls
+; @funB via  function pointer in the other module. Then we could end up in
+; situations where @funB -> @funA in one module (after merging functions) and
+; @funA -> @funB via the a function pointer in the other module.
+
 ; CHECK-LABEL: define linkonce_odr i32 @funA
 ; CHECK-NEXT:    add
 ; CHECK:         ret
 
+; CHECK-LABEL: define linkonce_odr i32 @funC
+; CHECK-NEXT:    tail call i32 @funA(i32 %0, i32 %1)
+; CHECK-NEXT:    ret
+
 ; CHECK-LABEL: define linkonce_odr i32 @funB
 ; CHECK-NEXT:    tail call i32 @funA(i32 %0, i32 %1)
 ; CHECK-NEXT:    ret
diff --git a/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll b/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll
new file mode 100644
index 00000000000000..96711265b7f418
--- /dev/null
+++ b/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll
@@ -0,0 +1,112 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
+; RUN: opt -p mergefunc -S %s | FileCheck %s
+
+define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(ptr %p) {
+entry:
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  ret void
+}
+
+define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(ptr %p) {
+entry:
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  tail call void @foo(ptr %p)
+  ret void
+}
+
+declare void @foo(ptr)
+
+define hidden void @linkonce_odr_caller_of_bar_1(ptr %p) {
+entry:
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  ret void
+}
+
+define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(ptr %p) {
+entry:
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  tail call void @bar(ptr %p)
+  ret void
+}
+
+declare void @bar(ptr)
+
+define hidden void @non_linkonce_caller_of_zar_1(ptr %p) {
+entry:
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  ret void
+}
+
+define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(ptr %p) {
+entry:
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  tail call void @zar(ptr %p)
+  ret void
+}
+
+declare void @zar(ptr)
+; CHECK-LABEL: define private void @0(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    tail call void @foo(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define private void @1(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    tail call void @bar(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_zar_2(
+; CHECK-SAME: ptr [[P:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*:]]
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    tail call void @zar(ptr [[P]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB0:[0-9]+]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB0]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB1:[0-9]+]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define hidden void @linkonce_odr_caller_of_bar_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @[[GLOB1]](ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;
+;
+; CHECK-LABEL: define hidden void @non_linkonce_caller_of_zar_1(
+; CHECK-SAME: ptr [[TMP0:%.*]]) {
+; CHECK-NEXT:    tail call void @linkonce_odr_caller_of_zar_2(ptr [[TMP0]])
+; CHECK-NEXT:    ret void
+;

>From bc627d5e043b42d2ae9264087cdc8664761bd149 Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Thu, 30 Jan 2025 16:16:08 +0000
Subject: [PATCH 4/5] !fixup fix formatting

---
 llvm/lib/Transforms/IPO/MergeFunctions.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index ea5e102156ff76..7130e8ce04817c 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -891,8 +891,10 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
 
 // Merge two equivalent functions. Upon completion, Function G is deleted.
 void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
-  if (F->isInterposable() || G->hasWeakODRLinkage() || G->hasLinkOnceODRLinkage()) {
-    assert(G->isInterposable() || G->hasWeakODRLinkage()|| G->hasLinkOnceODRLinkage());
+  if (F->isInterposable() || G->hasWeakODRLinkage() ||
+      G->hasLinkOnceODRLinkage()) {
+    assert(G->isInterposable() || G->hasWeakODRLinkage() ||
+           G->hasLinkOnceODRLinkage());
 
     // Both writeThunkOrAlias() calls below must succeed, either because we can
     // create aliases for G and NewF, or because a thunk for F is profitable.

>From 293f3ec8da4debc3e9a1dafe090f8742edfe64bf Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Mon, 3 Feb 2025 18:15:38 +0000
Subject: [PATCH 5/5] !fixup Document and sort by weak/linkince ODR.

---
 llvm/lib/Transforms/IPO/MergeFunctions.cpp          | 13 +++++++++++++
 .../test/Transforms/MergeFunc/merge-linkonce-odr.ll | 10 ++--------
 llvm/test/Transforms/MergeFunc/merge-weak-odr.ll    | 10 ++--------
 3 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Transforms/IPO/MergeFunctions.cpp b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
index 7130e8ce04817c..11720d65a72a2b 100644
--- a/llvm/lib/Transforms/IPO/MergeFunctions.cpp
+++ b/llvm/lib/Transforms/IPO/MergeFunctions.cpp
@@ -891,6 +891,10 @@ bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
 
 // Merge two equivalent functions. Upon completion, Function G is deleted.
 void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
+
+  // Create a new thunk that both F and G can call, if F cannot call G directly.
+  // That is the case if F is either interposable or if G is either weak_odr or
+  // linkonce_odr.
   if (F->isInterposable() || G->hasWeakODRLinkage() ||
       G->hasLinkOnceODRLinkage()) {
     assert(G->isInterposable() || G->hasWeakODRLinkage() ||
@@ -993,11 +997,20 @@ static bool isFuncOrderCorrect(const Function *F, const Function *G) {
     // one, but not the other way around.
     return !F->isInterposable();
   }
+
+  if (F->hasWeakODRLinkage() != G->hasWeakODRLinkage() ||
+      F->hasLinkOnceODRLinkage() != G->hasLinkOnceODRLinkage()) {
+    // ODR functions before non-ODR functions. A ODR function can call a non-ODR
+    // function if it is not interposable, but not the other way around.
+    return F->hasWeakODRLinkage() || F->hasLinkOnceODRLinkage();
+  }
+
   if (F->hasLocalLinkage() != G->hasLocalLinkage()) {
     // External before local, because we definitely have to keep the external
     // function, but may be able to drop the local one.
     return !F->hasLocalLinkage();
   }
+
   // Impose a total order (by name) on the replacement of functions. This is
   // important when operating on more than one module independently to prevent
   // cycles of thunks calling each other when the modules are linked together.
diff --git a/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll b/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll
index 96711265b7f418..4d635d29a515e2 100644
--- a/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll
+++ b/llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll
@@ -63,7 +63,7 @@ declare void @zar(ptr)
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define private void @1(
+; CHECK-LABEL: define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    tail call void @bar(ptr [[P]])
@@ -93,15 +93,9 @@ declare void @zar(ptr)
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define linkonce_odr hidden void @non_linkonce_caller_of_bar_2(
-; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @[[GLOB1:[0-9]+]](ptr [[TMP0]])
-; CHECK-NEXT:    ret void
-;
-;
 ; CHECK-LABEL: define hidden void @linkonce_odr_caller_of_bar_1(
 ; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @[[GLOB1]](ptr [[TMP0]])
+; CHECK-NEXT:    tail call void @non_linkonce_caller_of_bar_2(ptr [[TMP0]])
 ; CHECK-NEXT:    ret void
 ;
 ;
diff --git a/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
index d2e89092b9a826..aefeeae6b672c4 100644
--- a/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
+++ b/llvm/test/Transforms/MergeFunc/merge-weak-odr.ll
@@ -72,7 +72,7 @@ declare void @zar(ptr)
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define private void @1(
+; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_zar_2(
 ; CHECK-SAME: ptr [[P:%.*]]) {
 ; CHECK-NEXT:  [[ENTRY:.*:]]
 ; CHECK-NEXT:    tail call void @zar(ptr [[P]])
@@ -99,14 +99,8 @@ declare void @zar(ptr)
 ; CHECK-NEXT:    ret void
 ;
 ;
-; CHECK-LABEL: define weak_odr hidden void @weak_odr_caller_of_zar_2(
-; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @[[GLOB1:[0-9]+]](ptr [[TMP0]])
-; CHECK-NEXT:    ret void
-;
-;
 ; CHECK-LABEL: define hidden void @non_weak_caller_of_zar_1(
 ; CHECK-SAME: ptr [[TMP0:%.*]]) {
-; CHECK-NEXT:    tail call void @[[GLOB1]](ptr [[TMP0]])
+; CHECK-NEXT:    tail call void @weak_odr_caller_of_zar_2(ptr [[TMP0]])
 ; CHECK-NEXT:    ret void
 ;



More information about the llvm-commits mailing list