From f431f04c96597273a81a2e39b14d74fd5e1dc896 Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 15 Oct 2017 12:29:01 +0000 Subject: [PATCH] [MergeFunctions] Replace all uses of unnamed_addr functions. This reduces code size for constructs like vtables or interrupt tables that refer to functions in global initializers. Differential Revision: https://reviews.llvm.org/D34805 llvm-svn: 315852 --- lib/Transforms/IPO/MergeFunctions.cpp | 12 ++++++-- .../MergeFunc/merge-unnamed-addr-bitcast.ll | 30 +++++++++++++++++++ .../MergeFunc/merge-unnamed-addr.ll | 18 +++++++++++ 3 files changed, 57 insertions(+), 3 deletions(-) create mode 100644 test/Transforms/MergeFunc/merge-unnamed-addr-bitcast.ll create mode 100644 test/Transforms/MergeFunc/merge-unnamed-addr.ll diff --git a/lib/Transforms/IPO/MergeFunctions.cpp b/lib/Transforms/IPO/MergeFunctions.cpp index a43b69f3413..95a05d87348 100644 --- a/lib/Transforms/IPO/MergeFunctions.cpp +++ b/lib/Transforms/IPO/MergeFunctions.cpp @@ -628,9 +628,15 @@ void MergeFunctions::filterInstsUnrelatedToPDI( // 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, diff --git a/test/Transforms/MergeFunc/merge-unnamed-addr-bitcast.ll b/test/Transforms/MergeFunc/merge-unnamed-addr-bitcast.ll new file mode 100644 index 00000000000..3cefc3eb819 --- /dev/null +++ b/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 +} diff --git a/test/Transforms/MergeFunc/merge-unnamed-addr.ll b/test/Transforms/MergeFunc/merge-unnamed-addr.ll new file mode 100644 index 00000000000..cb34d43c08f --- /dev/null +++ b/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 +}