Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 1abfd0e

Browse files
authored
Merge pull request #114 from nox/mergefunc
[MergeFunctions] Fix merging of small weak functions
2 parents da0cb60 + efbf5cc commit 1abfd0e

File tree

2 files changed

+65
-38
lines changed

2 files changed

+65
-38
lines changed

lib/Transforms/IPO/MergeFunctions.cpp

+49-38
Original file line numberDiff line numberDiff line change
@@ -638,48 +638,25 @@ void MergeFunctions::filterInstsUnrelatedToPDI(
638638
DEBUG(dbgs() << " }\n");
639639
}
640640

641-
// Replace G with a simple tail call to bitcast(F). Also (unless
642-
// MergeFunctionsPDI holds) replace direct uses of G with bitcast(F),
643-
// delete G. Under MergeFunctionsPDI, we use G itself for creating
644-
// the thunk as we preserve the debug info (and associated instructions)
645-
// from G's entry block pertaining to G's incoming arguments which are
646-
// passed on as corresponding arguments in the call that G makes to F.
647-
// For better debugability, under MergeFunctionsPDI, we do not modify G's
648-
// call sites to point to F even when within the same translation unit.
649-
void MergeFunctions::writeThunk(Function *F, Function *G) {
650-
if (!G->isInterposable() && !MergeFunctionsPDI) {
651-
if (G->hasGlobalUnnamedAddr()) {
652-
// G might have been a key in our GlobalNumberState, and it's illegal
653-
// to replace a key in ValueMap<GlobalValue *> with a non-global.
654-
GlobalNumbers.erase(G);
655-
// If G's address is not significant, replace it entirely.
656-
Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType());
657-
G->replaceAllUsesWith(BitcastF);
658-
} else {
659-
// Redirect direct callers of G to F. (See note on MergeFunctionsPDI
660-
// above).
661-
replaceDirectCallers(G, F);
662-
}
663-
}
664-
665-
// If G was internal then we may have replaced all uses of G with F. If so,
666-
// stop here and delete G. There's no need for a thunk. (See note on
667-
// MergeFunctionsPDI above).
668-
if (G->hasLocalLinkage() && G->use_empty() && !MergeFunctionsPDI) {
669-
G->eraseFromParent();
670-
return;
671-
}
672-
673-
// Don't merge tiny functions using a thunk, since it can just end up
674-
// making the function larger.
641+
// Don't merge tiny functions using a thunk, since it can just end up
642+
// making the function larger.
643+
static bool isThunkProfitable(Function *F) {
675644
if (F->size() == 1) {
676645
if (F->front().size() <= 2) {
677-
DEBUG(dbgs() << "writeThunk: " << F->getName()
646+
DEBUG(dbgs() << "isThunkProfitable: " << F->getName()
678647
<< " is too small to bother creating a thunk for\n");
679-
return;
648+
return false;
680649
}
681650
}
651+
return true;
652+
}
682653

654+
// Replace G with a simple tail call to bitcast(F). Under MergeFunctionsPDI,
655+
// we use G itself for creating the thunk as we preserve the debug info
656+
// (and associated instructions) from G's entry block pertaining to G's
657+
// incoming arguments which are passed on as corresponding arguments in
658+
// the call that G makes to F.
659+
void MergeFunctions::writeThunk(Function *F, Function *G) {
683660
BasicBlock *GEntryBlock = nullptr;
684661
std::vector<Instruction *> PDIUnrelatedWL;
685662
BasicBlock *BB = nullptr;
@@ -754,6 +731,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
754731
if (F->isInterposable()) {
755732
assert(G->isInterposable());
756733

734+
if (!isThunkProfitable(F)) {
735+
return;
736+
}
737+
757738
// Make them both thunks to the same internal function.
758739
Function *H = Function::Create(F->getFunctionType(), F->getLinkage(), "",
759740
F->getParent());
@@ -770,11 +751,41 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
770751
F->setAlignment(MaxAlignment);
771752
F->setLinkage(GlobalValue::PrivateLinkage);
772753
++NumDoubleWeak;
754+
++NumFunctionsMerged;
773755
} else {
756+
// For better debugability, under MergeFunctionsPDI, we do not modify G's
757+
// call sites to point to F even when within the same translation unit.
758+
if (!G->isInterposable() && !MergeFunctionsPDI) {
759+
if (G->hasGlobalUnnamedAddr()) {
760+
// G might have been a key in our GlobalNumberState, and it's illegal
761+
// to replace a key in ValueMap<GlobalValue *> with a non-global.
762+
GlobalNumbers.erase(G);
763+
// If G's address is not significant, replace it entirely.
764+
Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType());
765+
G->replaceAllUsesWith(BitcastF);
766+
} else {
767+
// Redirect direct callers of G to F. (See note on MergeFunctionsPDI
768+
// above).
769+
replaceDirectCallers(G, F);
770+
}
771+
}
772+
773+
// If G was internal then we may have replaced all uses of G with F. If so,
774+
// stop here and delete G. There's no need for a thunk. (See note on
775+
// MergeFunctionsPDI above).
776+
if (G->hasLocalLinkage() && G->use_empty() && !MergeFunctionsPDI) {
777+
G->eraseFromParent();
778+
++NumFunctionsMerged;
779+
return;
780+
}
781+
782+
if (!isThunkProfitable(F)) {
783+
return;
784+
}
785+
774786
writeThunk(F, G);
787+
++NumFunctionsMerged;
775788
}
776-
777-
++NumFunctionsMerged;
778789
}
779790

780791
/// Replace function F by function G.
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
; RUN: opt -mergefunc -S < %s | FileCheck %s
2+
3+
; Weak functions too small for merging to be profitable
4+
5+
; CHECK: define weak i32 @foo(i8*, i32)
6+
; CHECK-NEXT: ret i32 %1
7+
; CHECK: define weak i32 @bar(i8*, i32)
8+
; CHECK-NEXT: ret i32 %1
9+
10+
define weak i32 @foo(i8*, i32) #0 {
11+
ret i32 %1
12+
}
13+
14+
define weak i32 @bar(i8*, i32) #0 {
15+
ret i32 %1
16+
}

0 commit comments

Comments
 (0)