Skip to content

Commit

Permalink
[MergeFunctions] Merge small functions if possible without a thunk.
Browse files Browse the repository at this point in the history
This can result in significant code size savings in some cases,
e.g. an interrupt table all filled with the same assembly stub
in a certain Cortex-M BSP results in code blowup by a factor of 2.5.

Differential Revision: https://reviews.llvm.org/D34806

llvm-svn: 315853
  • Loading branch information
whitequark committed Oct 15, 2017
1 parent b2ce9ff commit ae12efa
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 12 deletions.
22 changes: 10 additions & 12 deletions llvm/lib/Transforms/IPO/MergeFunctions.cpp
Expand Up @@ -647,6 +647,16 @@ void MergeFunctions::writeThunk(Function *F, Function *G) {
return;
}

// Don't merge tiny functions using a thunk, since it can just end up
// making the function larger.
if (F->size() == 1) {
if (F->front().size() <= 2) {
DEBUG(dbgs() << "writeThunk: " << F->getName()
<< " is too small to bother creating a thunk for\n");
return;
}
}

BasicBlock *GEntryBlock = nullptr;
std::vector<Instruction *> PDIUnrelatedWL;
BasicBlock *BB = nullptr;
Expand Down Expand Up @@ -779,18 +789,6 @@ bool MergeFunctions::insert(Function *NewFunction) {

const FunctionNode &OldF = *Result.first;

// Don't merge tiny functions, since it can just end up making the function
// larger.
// FIXME: Should still merge them if they are unnamed_addr and produce an
// alias.
if (NewFunction->size() == 1) {
if (NewFunction->front().size() <= 2) {
DEBUG(dbgs() << NewFunction->getName()
<< " is to small to bother merging\n");
return false;
}
}

// 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.
Expand Down
14 changes: 14 additions & 0 deletions llvm/test/Transforms/MergeFunc/merge-small-unnamed-addr.ll
@@ -0,0 +1,14 @@
; RUN: opt -S -mergefunc < %s | FileCheck %s

; CHECK-NOT: @b

@x = constant { void ()*, void ()* } { void ()* @a, void ()* @b }
; CHECK: { void ()* @a, void ()* @a }

define internal void @a() unnamed_addr {
ret void
}

define internal void @b() unnamed_addr {
ret void
}

0 comments on commit ae12efa

Please sign in to comment.