================ @@ -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() && ---------------- nickdesaulniers wrote:
Would you also filter with `isInlineViable` or no? https://github.com/llvm/llvm-project/pull/134223 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits