aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-reduce
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-reduce')
-rw-r--r--llvm/tools/llvm-reduce/CMakeLists.txt1
-rw-r--r--llvm/tools/llvm-reduce/DeltaManager.cpp1
-rw-r--r--llvm/tools/llvm-reduce/DeltaPasses.def2
-rw-r--r--llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.cpp103
-rw-r--r--llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.h18
5 files changed, 124 insertions, 1 deletions
diff --git a/llvm/tools/llvm-reduce/CMakeLists.txt b/llvm/tools/llvm-reduce/CMakeLists.txt
index 7be90bc..c8673b4 100644
--- a/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -39,6 +39,7 @@ add_llvm_tool(llvm-reduce
deltas/ReduceGlobalValues.cpp
deltas/ReduceGlobalVarInitializers.cpp
deltas/ReduceGlobalVars.cpp
+ deltas/ReduceInlineCallSites.cpp
deltas/ReduceInstructions.cpp
deltas/ReduceInstructionFlags.cpp
deltas/ReduceInvokes.cpp
diff --git a/llvm/tools/llvm-reduce/DeltaManager.cpp b/llvm/tools/llvm-reduce/DeltaManager.cpp
index f5c6276..9b13202 100644
--- a/llvm/tools/llvm-reduce/DeltaManager.cpp
+++ b/llvm/tools/llvm-reduce/DeltaManager.cpp
@@ -28,6 +28,7 @@
#include "deltas/ReduceGlobalVarInitializers.h"
#include "deltas/ReduceGlobalVars.h"
#include "deltas/ReduceIRReferences.h"
+#include "deltas/ReduceInlineCallSites.h"
#include "deltas/ReduceInstructionFlags.h"
#include "deltas/ReduceInstructionFlagsMIR.h"
#include "deltas/ReduceInstructions.h"
diff --git a/llvm/tools/llvm-reduce/DeltaPasses.def b/llvm/tools/llvm-reduce/DeltaPasses.def
index 3aed0cc..845b106 100644
--- a/llvm/tools/llvm-reduce/DeltaPasses.def
+++ b/llvm/tools/llvm-reduce/DeltaPasses.def
@@ -58,7 +58,7 @@ DELTA_PASS_IR("volatile", reduceVolatileInstructionsDeltaPass, "Reducing Volatil
DELTA_PASS_IR("atomic-ordering", reduceAtomicOrderingDeltaPass, "Reducing Atomic Ordering")
DELTA_PASS_IR("syncscopes", reduceAtomicSyncScopesDeltaPass, "Reducing Atomic Sync Scopes")
DELTA_PASS_IR("instruction-flags", reduceInstructionFlagsDeltaPass, "Reducing Instruction Flags")
-
+DELTA_PASS_IR("inline-call-sites", reduceInlineCallSitesDeltaPass, "Inlining callsites")
#ifndef DELTA_PASS_MIR
#define DELTA_PASS_MIR(NAME, FUNC, DESC)
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.cpp b/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.cpp
new file mode 100644
index 0000000..cfef367
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.cpp
@@ -0,0 +1,103 @@
+//===- ReduceInlineCallSites.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceInlineCallSites.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+using namespace llvm;
+
+extern cl::OptionCategory LLVMReduceOptions;
+
+static cl::opt<int> CallsiteInlineThreshold(
+ "reduce-callsite-inline-threshold",
+ cl::desc("Number of instructions in a function to unconditionally inline "
+ "(-1 for inline all)"),
+ cl::init(5), cl::cat(LLVMReduceOptions));
+
+static bool functionHasMoreThanNonTerminatorInsts(const Function &F,
+ uint64_t NumInsts) {
+ uint64_t InstCount = 0;
+ for (const BasicBlock &BB : F) {
+ for (const Instruction &I : make_range(BB.begin(), std::prev(BB.end()))) {
+ (void)I;
+ if (InstCount++ > NumInsts)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static bool hasOnlyOneCallUse(const Function &F) {
+ unsigned UseCount = 0;
+ for (const Use &U : F.uses()) {
+ const CallBase *CB = dyn_cast<CallBase>(U.getUser());
+ if (!CB || !CB->isCallee(&U))
+ return false;
+ if (UseCount++ > 1)
+ return false;
+ }
+
+ return UseCount == 1;
+}
+
+// TODO: This could use more thought.
+static bool inlineWillReduceComplexity(const Function &Caller,
+ const Function &Callee) {
+ // Backdoor to force all possible inlining.
+ if (CallsiteInlineThreshold < 0)
+ return true;
+
+ if (!hasOnlyOneCallUse(Callee))
+ return false;
+
+ // Permit inlining small functions into big functions, or big functions into
+ // small functions.
+ if (!functionHasMoreThanNonTerminatorInsts(Callee, CallsiteInlineThreshold) &&
+ !functionHasMoreThanNonTerminatorInsts(Caller, CallsiteInlineThreshold))
+ return true;
+
+ return false;
+}
+
+static void reduceCallSites(Oracle &O, Function &F) {
+ std::vector<std::pair<CallBase *, InlineFunctionInfo>> CallSitesToInline;
+
+ for (Use &U : F.uses()) {
+ if (CallBase *CB = dyn_cast<CallBase>(U.getUser())) {
+ // Ignore callsites with wrong call type.
+ if (!CB->isCallee(&U))
+ continue;
+
+ // We do not consider isInlineViable here. It is overly conservative in
+ // cases that the inliner should handle correctly (e.g. disallowing inline
+ // of of functions with indirectbr). Some of the other cases are for other
+ // correctness issues which we do need to worry about here.
+
+ // TODO: Should we delete the function body?
+ InlineFunctionInfo IFI;
+ if (CanInlineCallSite(*CB, IFI).isSuccess() &&
+ inlineWillReduceComplexity(*CB->getFunction(), F) && !O.shouldKeep())
+ CallSitesToInline.emplace_back(CB, std::move(IFI));
+ }
+ }
+
+ // TODO: InlineFunctionImpl will implicitly perform some simplifications /
+ // optimizations which we should be able to opt-out of.
+ for (auto [CB, IFI] : CallSitesToInline)
+ InlineFunctionImpl(*CB, IFI);
+}
+
+void llvm::reduceInlineCallSitesDeltaPass(Oracle &O, ReducerWorkItem &Program) {
+ for (Function &F : Program.getModule()) {
+ if (!F.isDeclaration())
+ reduceCallSites(O, F);
+ }
+}
diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.h b/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.h
new file mode 100644
index 0000000..1df31a1
--- /dev/null
+++ b/llvm/tools/llvm-reduce/deltas/ReduceInlineCallSites.h
@@ -0,0 +1,18 @@
+//===- ReduceInlineCallSites.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINLINECALLSITES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINLINECALLSITES_H
+
+#include "Delta.h"
+
+namespace llvm {
+void reduceInlineCallSitesDeltaPass(Oracle &O, ReducerWorkItem &Program);
+} // namespace llvm
+
+#endif