Skip to content

Commit 3afc3f4

Browse files
authored
[MergeFunc] Remove discardables function before writing alias or thunk. (#128865)
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. PR: #128865
1 parent 61aab82 commit 3afc3f4

File tree

4 files changed

+26
-45
lines changed

4 files changed

+26
-45
lines changed

llvm/lib/Transforms/IPO/MergeFunctions.cpp

Lines changed: 21 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+
// (i.e. it is discardable and not used), \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,14 @@ 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 (i.e.
881+
// it is discardable and unused), \p G is removed directly.
882+
bool MergeFunctions::writeThunkOrAliasIfNeeded(Function *F, Function *G) {
883+
if (G->isDiscardableIfUnused() && G->use_empty() && !MergeFunctionsPDI) {
884+
G->eraseFromParent();
885+
return true;
886+
}
881887
if (canCreateAliasFor(G)) {
882888
writeAlias(F, G);
883889
return true;
@@ -904,9 +910,10 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
904910
assert((!isODR(G) || isODR(F)) &&
905911
"if G is ODR, F must also be ODR due to ordering");
906912

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.
913+
// Both writeThunkOrAliasIfNeeded() calls below must succeed, either because
914+
// we can create aliases for G and NewF, or because a thunk for F is
915+
// profitable. F here has the same signature as NewF below, so that's what
916+
// we check.
910917
if (!canCreateThunkFor(F) &&
911918
(!canCreateAliasFor(F) || !canCreateAliasFor(G)))
912919
return;
@@ -930,13 +937,13 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
930937
if (isODR(F))
931938
replaceDirectCallers(NewF, F);
932939

933-
// We collect alignment before writeThunkOrAlias that overwrites NewF and
934-
// G's content.
940+
// We collect alignment before writeThunkOrAliasIfNeeded that overwrites
941+
// NewF and G's content.
935942
const MaybeAlign NewFAlign = NewF->getAlign();
936943
const MaybeAlign GAlign = G->getAlign();
937944

938-
writeThunkOrAlias(F, G);
939-
writeThunkOrAlias(F, NewF);
945+
writeThunkOrAliasIfNeeded(F, G);
946+
writeThunkOrAliasIfNeeded(F, NewF);
940947

941948
if (NewFAlign || GAlign)
942949
F->setAlignment(std::max(NewFAlign.valueOrOne(), GAlign.valueOrOne()));
@@ -975,7 +982,7 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
975982
return;
976983
}
977984

978-
if (writeThunkOrAlias(F, G)) {
985+
if (writeThunkOrAliasIfNeeded(F, G)) {
979986
++NumFunctionsMerged;
980987
}
981988
}

llvm/test/Transforms/MergeFunc/linkonce.ll

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2-
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s -implicit-check-not=funC
1+
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s -implicit-check-not=funA -implicit-check-not=funC
32

43
; Replacments should be totally ordered on the function name.
54
; If we don't do this we can end up with one module defining a thunk for @funA
@@ -43,14 +42,8 @@ define linkonce i32 @funA(i32 %x, i32 %y) {
4342
; CHECK-NEXT: ret i32 [[SUM3]]
4443
;
4544
;
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-
;
5245
; CHECK-LABEL: define linkonce i32 @funB(
5346
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
54-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]], i32 [[TMP1]])
47+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @0(i32 [[TMP0]], i32 [[TMP1]])
5548
; CHECK-NEXT: ret i32 [[TMP3]]
5649
;

llvm/test/Transforms/MergeFunc/linkonce_odr.ll

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --include-generated-funcs --version 5
2-
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s -implicit-check-not=funC
1+
; RUN: opt -S -passes=mergefunc < %s | FileCheck %s -implicit-check-not=funA -implicit-check-not=funC
32

43
; Replacments should be totally ordered on the function name.
54
; If we don't do this we can end up with one module defining a thunk for @funA
@@ -43,14 +42,8 @@ define linkonce_odr i32 @funA(i32 %x, i32 %y) {
4342
; CHECK-NEXT: ret i32 [[SUM3]]
4443
;
4544
;
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-
;
5245
; CHECK-LABEL: define linkonce_odr i32 @funB(
5346
; CHECK-SAME: i32 [[TMP0:%.*]], i32 [[TMP1:%.*]]) {
54-
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @[[GLOB0]](i32 [[TMP0]], i32 [[TMP1]])
47+
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @0(i32 [[TMP0]], i32 [[TMP1]])
5548
; CHECK-NEXT: ret i32 [[TMP3]]
5649
;

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)