[llvm] 335a316 - [Inline] Attempt to delete any discardable if unused functions
Arthur Eubanks via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 7 11:05:39 PST 2022
Author: Arthur Eubanks
Date: 2022-01-07T11:05:26-08:00
New Revision: 335a3163aab4ab3a52c7c15d03bcf1ce9ba79fbb
URL: https://github.com/llvm/llvm-project/commit/335a3163aab4ab3a52c7c15d03bcf1ce9ba79fbb
DIFF: https://github.com/llvm/llvm-project/commit/335a3163aab4ab3a52c7c15d03bcf1ce9ba79fbb.diff
LOG: [Inline] Attempt to delete any discardable if unused functions
Previously we limited ourselves to only internal/private functions. We
can also delete linkonce_odr functions.
Minor compile time wins:
https://llvm-compile-time-tracker.com/compare.php?from=d51e3474e060cb0e90dc2e2487f778b0d3e6a8de&to=bccffe3f8d5dd4dda884c9ac1f93e51772519cad&stat=instructions
Major memory wins on tramp3d:
https://llvm-compile-time-tracker.com/compare.php?from=d51e3474e060cb0e90dc2e2487f778b0d3e6a8de&to=bccffe3f8d5dd4dda884c9ac1f93e51772519cad&stat=max-rss
Reviewed By: nikic
Differential Revision: https://reviews.llvm.org/D115545
Added:
llvm/test/Transforms/Inline/delete-unused-function.ll
Modified:
llvm/lib/Transforms/IPO/Inliner.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/Inliner.cpp b/llvm/lib/Transforms/IPO/Inliner.cpp
index 81b9ad04571a9..a9cc25f26e048 100644
--- a/llvm/lib/Transforms/IPO/Inliner.cpp
+++ b/llvm/lib/Transforms/IPO/Inliner.cpp
@@ -823,6 +823,10 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// defer deleting these to make it easier to handle the call graph updates.
SmallVector<Function *, 4> DeadFunctions;
+ // Track potentially dead non-local functions with comdats to see if they can
+ // be deleted as a batch after inlining.
+ SmallVector<Function *, 4> DeadFunctionsInComdats;
+
// Loop forward over all of the calls.
while (!Calls->empty()) {
// We expect the calls to typically be batched with sequences of calls that
@@ -935,28 +939,33 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
// Merge the attributes based on the inlining.
AttributeFuncs::mergeAttributesForInlining(F, Callee);
- // For local functions, check whether this makes the callee trivially
- // dead. In that case, we can drop the body of the function eagerly
- // which may reduce the number of callers of other functions to one,
- // changing inline cost thresholds.
+ // For local functions or discardable functions without comdats, check
+ // whether this makes the callee trivially dead. In that case, we can drop
+ // the body of the function eagerly which may reduce the number of callers
+ // of other functions to one, changing inline cost thresholds. Non-local
+ // discardable functions with comdats are checked later on.
bool CalleeWasDeleted = false;
- if (Callee.hasLocalLinkage()) {
+ if (Callee.isDiscardableIfUnused()) {
// To check this we also need to nuke any dead constant uses (perhaps
// made dead by this operation on other functions).
Callee.removeDeadConstantUsers();
if (Callee.use_empty() && !CG.isLibFunction(Callee)) {
- Calls->erase_if([&](const std::pair<CallBase *, int> &Call) {
- return Call.first->getCaller() == &Callee;
- });
- // Clear the body and queue the function itself for deletion when we
- // finish inlining and call graph updates.
- // Note that after this point, it is an error to do anything other
- // than use the callee's address or delete it.
- Callee.dropAllReferences();
- assert(!is_contained(DeadFunctions, &Callee) &&
- "Cannot put cause a function to become dead twice!");
- DeadFunctions.push_back(&Callee);
- CalleeWasDeleted = true;
+ if (Callee.hasLocalLinkage() || !Callee.hasComdat()) {
+ Calls->erase_if([&](const std::pair<CallBase *, int> &Call) {
+ return Call.first->getCaller() == &Callee;
+ });
+ // Clear the body and queue the function itself for deletion when we
+ // finish inlining and call graph updates.
+ // Note that after this point, it is an error to do anything other
+ // than use the callee's address or delete it.
+ Callee.dropAllReferences();
+ assert(!is_contained(DeadFunctions, &Callee) &&
+ "Cannot put cause a function to become dead twice!");
+ DeadFunctions.push_back(&Callee);
+ CalleeWasDeleted = true;
+ } else {
+ DeadFunctionsInComdats.push_back(&Callee);
+ }
}
}
if (CalleeWasDeleted)
@@ -1019,6 +1028,15 @@ PreservedAnalyses InlinerPass::run(LazyCallGraph::SCC &InitialC,
FAM.invalidate(F, PreservedAnalyses::none());
}
+ // We must ensure that we only delete functions with comdats if every function
+ // in the comdat is going to be deleted.
+ if (!DeadFunctionsInComdats.empty()) {
+ filterDeadComdatFunctions(DeadFunctionsInComdats);
+ for (auto *Callee : DeadFunctionsInComdats)
+ Callee->dropAllReferences();
+ DeadFunctions.append(DeadFunctionsInComdats);
+ }
+
// Now that we've finished inlining all of the calls across this SCC, delete
// all of the trivially dead functions, updating the call graph and the CGSCC
// pass manager in the process.
diff --git a/llvm/test/Transforms/Inline/delete-unused-function.ll b/llvm/test/Transforms/Inline/delete-unused-function.ll
new file mode 100644
index 0000000000000..319a6a6bcab53
--- /dev/null
+++ b/llvm/test/Transforms/Inline/delete-unused-function.ll
@@ -0,0 +1,63 @@
+; RUN: opt -passes=inline < %s -S | FileCheck %s
+
+; CHECK: define {{.*}}@caller
+; CHECK: define {{.*}}@f1
+; CHECK-NOT: define {{.*}}@f2
+; CHECK-NOT: define {{.*}}@f3
+; CHECK-NOT: define {{.*}}@f4
+; CHECK-NOT: define {{.*}}@f5
+; CHECK: define {{.*}}@f6
+; CHECK-NOT: define {{.*}}@f7
+; CHECK-NOT: define {{.*}}@f8
+
+$c1 = comdat any
+$c2 = comdat any
+$c3 = comdat any
+
+define void @caller() {
+ call void @f1()
+ call void @f2()
+ call void @f3()
+ call void @f4()
+ call void @f5()
+ call void @f6()
+ call void @f7()
+ call void @f8()
+ ret void
+}
+
+define void @f1() {
+ ret void
+}
+
+define internal void @f2() {
+ ret void
+}
+
+define private void @f3() {
+ ret void
+}
+
+define linkonce_odr void @f4() {
+ ret void
+}
+
+define linkonce_odr void @f5() comdat($c1) {
+ ret void
+}
+
+define linkonce_odr void @f6() comdat($c2) {
+ ret void
+}
+
+define linkonce_odr void @g() comdat($c2) {
+ ret void
+}
+
+define linkonce_odr void @f7() comdat($c3) {
+ ret void
+}
+
+define linkonce_odr void @f8() comdat($c3) {
+ ret void
+}
More information about the llvm-commits
mailing list