Skip to content

Commit 6a6de10

Browse files
committed
[MergeFunc] Remove discardables function before writing alias or thunk.
Update writeThunkOrAlias to only create an alias or thunk if it is actually needed. Drop discardable linkone_odr functions if they are not used before.
1 parent 7b6abd8 commit 6a6de10

File tree

4 files changed

+25
-41
lines changed

4 files changed

+25
-41
lines changed

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -283,9 +283,10 @@ class MergeFunctions {
283283
// Replace G with an alias to F (deleting function G)
284284
void writeAlias(Function *F, Function *G);
285285

286-
// Replace G with an alias to F if possible, or a thunk to F if possible.
287-
// Returns false if neither is the case.
288-
bool writeThunkOrAlias(Function *F, Function *G);
286+
// If needed, replace G with an alias to F if possible, or a thunk to F if
287+
// profitable. Returns false if neither is the case. If \p G is not needed
288+
// (e.g. it is discardable and linkonce_odr), \p G is removed directly.
289+
bool writeThunkOrAliasIfNeeded(Function *F, Function *G);
289290

290291
/// Replace function F with function G in the function tree.
291292
void replaceFunctionInTree(const FunctionNode &FN, Function *G);
@@ -875,9 +876,15 @@ void MergeFunctions::writeAlias(Function *F, Function *G) {
875876
++NumAliasesWritten;
876877
}
877878

878-
// Replace G with an alias to F if possible, or a thunk to F if
879-
// profitable. Returns false if neither is the case.
880-
bool MergeFunctions::writeThunkOrAlias(Function *F, Function *G) {
879+
// If needed, replace G with an alias to F if possible, or a thunk to F if
880+
// profitable. Returns false if neither is the case. If \p G is not needed (e.g.
881+
// it is discardable and linkonce_odr), \p G is removed directly.
882+
bool MergeFunctions::writeThunkOrAliasIfNeeded(Function *F, Function *G) {
883+
if (G->isDiscardableIfUnused() &&
884+
G->use_empty() && !MergeFunctionsPDI) {
885+
G->eraseFromParent();
886+
return true;
887+
}
881888
if (canCreateAliasFor(G)) {
882889
writeAlias(F, G);
883890
return true;
@@ -904,9 +911,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
904911
assert((!isODR(G) || isODR(F)) &&
905912
"if G is ODR, F must also be ODR due to ordering");
906913

907-
// Both writeThunkOrAlias() calls below must succeed, either because we can
908-
// create aliases for G and NewF, or because a thunk for F is profitable.
909-
// F here has the same signature as NewF below, so that's what we check.
914+
// Both writeThunkOrAliasIfNeeded() calls below must succeed, either because
915+
// we can create aliases for G and NewF, or because a thunk for F is
916+
// profitable. F here has the same signature as NewF below, so that's what
917+
// we check.
910918
if (!canCreateThunkFor(F) &&
911919
(!canCreateAliasFor(F) || !canCreateAliasFor(G)))
912920
return;
@@ -930,13 +938,13 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
930938
if (isODR(F))
931939
replaceDirectCallers(NewF, F);
932940

933-
// We collect alignment before writeThunkOrAlias that overwrites NewF and
934-
// G's content.
941+
// We collect alignment before writeThunkOrAliasIfNeeded that overwrites
942+
// NewF and G's content.
935943
const MaybeAlign NewFAlign = NewF->getAlign();
936944
const MaybeAlign GAlign = G->getAlign();
937945

938-
writeThunkOrAlias(F, G);
939-
writeThunkOrAlias(F, NewF);
946+
writeThunkOrAliasIfNeeded(F, G);
947+
writeThunkOrAliasIfNeeded(F, NewF);
940948

941949
if (NewFAlign || GAlign)
942950
F->setAlignment(std::max(NewFAlign.valueOrOne(), GAlign.valueOrOne()));
@@ -975,7 +983,7 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
975983
return;
976984
}
977985

978-
if (writeThunkOrAlias(F, G)) {
986+
if (writeThunkOrAliasIfNeeded(F, G)) {
979987
++NumFunctionsMerged;
980988
}
981989
}

llvm/test/Transforms/MergeFunc/linkonce.ll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,8 @@ define linkonce i32 @funA(i32 %x, i32 %y) {
4343
; CHECK-NEXT: ret i32 [[SUM3]]
4444
;
4545
;
46-
; CHECK-LABEL: define linkonce i32 @funC(
47-
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
48-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0:[0-9]+]](i32 [[TMP0]], i32 [[TMP1]])
49-
; CHECK-NEXT: ret i32 [[TMP3]]
50-
;
51-
;
5246
; CHECK-LABEL: define linkonce i32 @funB(
5347
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
54-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]], i32 [[TMP1]])
48+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0:[0-9]+]](i32 [[TMP0]], i32 [[TMP1]])
5549
; CHECK-NEXT: ret i32 [[TMP3]]
5650
;

llvm/test/Transforms/MergeFunc/linkonce_odr.ll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,8 @@ define linkonce_odr i32 @funA(i32 %x, i32 %y) {
4343
; CHECK-NEXT: ret i32 [[SUM3]]
4444
;
4545
;
46-
; CHECK-LABEL: define linkonce_odr i32 @funC(
47-
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
48-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0:[0-9]+]](i32 [[TMP0]], i32 [[TMP1]])
49-
; CHECK-NEXT: ret i32 [[TMP3]]
50-
;
51-
;
5246
; CHECK-LABEL: define linkonce_odr i32 @funB(
5347
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
54-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]], i32 [[TMP1]])
48+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0:[0-9]+]](i32 [[TMP0]], i32 [[TMP1]])
5549
; CHECK-NEXT: ret i32 [[TMP3]]
5650
;

llvm/test/Transforms/MergeFunc/merge-linkonce-odr.ll

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2-
; RUN: opt -p mergefunc -S %s | FileCheck %s
2+
; RUN: opt -p mergefunc -S %s | FileCheck --implicit-check-not=linkonce_odr_caller_of_foo_2 --implicit-check-not=linkonce_odr_caller_of_foo_1 %s
33

44
define void @caller_of_callers(ptr %p) {
55
call void @linkonce_odr_caller_of_foo_1(ptr %p)
@@ -125,15 +125,3 @@ declare void @zar(ptr)
125125
; CHECK-NEXT: tail call void @zar(ptr [[P]])
126126
; CHECK-NEXT: ret void
127127
;
128-
;
129-
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_2(
130-
; CHECK-SAME: ptr [[TMP0:%.*]]) {
131-
; CHECK-NEXT: tail call void @[[GLOB0]](ptr [[TMP0]])
132-
; CHECK-NEXT: ret void
133-
;
134-
;
135-
; CHECK-LABEL: define linkonce_odr hidden void @linkonce_odr_caller_of_foo_1(
136-
; CHECK-SAME: ptr [[TMP0:%.*]]) {
137-
; CHECK-NEXT: tail call void @[[GLOB0]](ptr [[TMP0]])
138-
; CHECK-NEXT: ret void
139-
;

0 commit comments

Comments
 (0)