Index: lib/Transforms/IPO/MergeFunctions.cpp =================================================================== --- lib/Transforms/IPO/MergeFunctions.cpp +++ lib/Transforms/IPO/MergeFunctions.cpp @@ -628,9 +628,15 @@ // call sites to point to F even when within the same translation unit. void MergeFunctions::writeThunk(Function *F, Function *G) { if (!G->isInterposable() && !MergeFunctionsPDI) { - // Redirect direct callers of G to F. (See note on MergeFunctionsPDI - // above). - replaceDirectCallers(G, F); + if (G->hasGlobalUnnamedAddr()) { + // If G's address is not significant, replace it entirely. + Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); + G->replaceAllUsesWith(BitcastF); + } else { + // Redirect direct callers of G to F. (See note on MergeFunctionsPDI + // above). + replaceDirectCallers(G, F); + } } // If G was internal then we may have replaced all uses of G with F. If so, Index: test/Transforms/MergeFunc/merge-unnamed-addr-bitcast.ll =================================================================== --- /dev/null +++ test/Transforms/MergeFunc/merge-unnamed-addr-bitcast.ll @@ -0,0 +1,30 @@ +; RUN: opt -S -mergefunc < %s | FileCheck %s + +%A = type { i32 } +%B = type { i32 } + +; CHECK-NOT: @b + +@x = constant { i32 (i32)*, i32 (i32)* } + { i32 (i32)* bitcast (i32 (%A)* @a to i32 (i32)*), + i32 (i32)* bitcast (i32 (%B)* @b to i32 (i32)*) } +; CHECK: { i32 (i32)* bitcast (i32 (%A)* @a to i32 (i32)*), i32 (i32)* bitcast (i32 (%A)* @a to i32 (i32)*) } + +define internal i32 @a(%A) unnamed_addr { + extractvalue %A %0, 0 + xor i32 %2, 0 + ret i32 %3 +} + +define internal i32 @b(%B) unnamed_addr { + extractvalue %B %0, 0 + xor i32 %2, 0 + ret i32 %3 +} + +define i32 @c(i32) { + insertvalue %B undef, i32 %0, 0 + call i32 @b(%B %2) +; CHECK: call i32 bitcast (i32 (%A)* @a to i32 (%B)*)(%B %2) + ret i32 %3 +} Index: test/Transforms/MergeFunc/merge-unnamed-addr.ll =================================================================== --- /dev/null +++ test/Transforms/MergeFunc/merge-unnamed-addr.ll @@ -0,0 +1,18 @@ +; RUN: opt -S -mergefunc < %s | FileCheck %s + +; CHECK-NOT: @b + +@x = constant { i32 (i32)*, i32 (i32)* } { i32 (i32)* @a, i32 (i32)* @b } +; CHECK: { i32 (i32)* @a, i32 (i32)* @a } + +define internal i32 @a(i32 %a) unnamed_addr { + %b = xor i32 %a, 0 + %c = xor i32 %b, 0 + ret i32 %c +} + +define internal i32 @b(i32 %a) unnamed_addr { + %b = xor i32 %a, 0 + %c = xor i32 %b, 0 + ret i32 %c +}