| 1 | //===- ReduceInlineCallSites.cpp ------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #include "ReduceInlineCallSites.h" |
| 10 | #include "llvm/IR/InstrTypes.h" |
| 11 | #include "llvm/Support/CommandLine.h" |
| 12 | #include "llvm/Transforms/Utils/Cloning.h" |
| 13 | |
| 14 | using namespace llvm; |
| 15 | |
| 16 | extern cl::OptionCategory LLVMReduceOptions; |
| 17 | |
| 18 | static cl::opt<int> CallsiteInlineThreshold( |
| 19 | "reduce-callsite-inline-threshold" , |
| 20 | cl::desc("Number of instructions in a function to unconditionally inline " |
| 21 | "(-1 for inline all)" ), |
| 22 | cl::init(Val: 5), cl::cat(LLVMReduceOptions)); |
| 23 | |
| 24 | static bool functionHasMoreThanNonTerminatorInsts(const Function &F, |
| 25 | uint64_t NumInsts) { |
| 26 | uint64_t InstCount = 0; |
| 27 | for (const BasicBlock &BB : F) { |
| 28 | for (const Instruction &I : make_range(x: BB.begin(), y: std::prev(x: BB.end()))) { |
| 29 | (void)I; |
| 30 | if (InstCount++ > NumInsts) |
| 31 | return true; |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | return false; |
| 36 | } |
| 37 | |
| 38 | static bool hasOnlyOneCallUse(const Function &F) { |
| 39 | unsigned UseCount = 0; |
| 40 | for (const Use &U : F.uses()) { |
| 41 | const CallBase *CB = dyn_cast<CallBase>(Val: U.getUser()); |
| 42 | if (!CB || !CB->isCallee(U: &U)) |
| 43 | return false; |
| 44 | if (UseCount++ > 1) |
| 45 | return false; |
| 46 | } |
| 47 | |
| 48 | return UseCount == 1; |
| 49 | } |
| 50 | |
| 51 | // TODO: This could use more thought. |
| 52 | static bool inlineWillReduceComplexity(const Function &Caller, |
| 53 | const Function &Callee) { |
| 54 | // Backdoor to force all possible inlining. |
| 55 | if (CallsiteInlineThreshold < 0) |
| 56 | return true; |
| 57 | |
| 58 | if (!hasOnlyOneCallUse(F: Callee)) |
| 59 | return false; |
| 60 | |
| 61 | // Permit inlining small functions into big functions, or big functions into |
| 62 | // small functions. |
| 63 | if (!functionHasMoreThanNonTerminatorInsts(F: Callee, NumInsts: CallsiteInlineThreshold) && |
| 64 | !functionHasMoreThanNonTerminatorInsts(F: Caller, NumInsts: CallsiteInlineThreshold)) |
| 65 | return true; |
| 66 | |
| 67 | return false; |
| 68 | } |
| 69 | |
| 70 | static void reduceCallSites(Oracle &O, Function &F) { |
| 71 | std::vector<std::pair<CallBase *, InlineFunctionInfo>> CallSitesToInline; |
| 72 | |
| 73 | for (Use &U : F.uses()) { |
| 74 | if (CallBase *CB = dyn_cast<CallBase>(Val: U.getUser())) { |
| 75 | // Ignore callsites with wrong call type. |
| 76 | if (!CB->isCallee(U: &U)) |
| 77 | continue; |
| 78 | |
| 79 | // We do not consider isInlineViable here. It is overly conservative in |
| 80 | // cases that the inliner should handle correctly (e.g. disallowing inline |
| 81 | // of of functions with indirectbr). Some of the other cases are for other |
| 82 | // correctness issues which we do need to worry about here. |
| 83 | |
| 84 | // TODO: Should we delete the function body? |
| 85 | InlineFunctionInfo IFI; |
| 86 | if (CanInlineCallSite(CB: *CB, IFI).isSuccess() && |
| 87 | inlineWillReduceComplexity(Caller: *CB->getFunction(), Callee: F) && !O.shouldKeep()) |
| 88 | CallSitesToInline.emplace_back(args&: CB, args: std::move(IFI)); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | // TODO: InlineFunctionImpl will implicitly perform some simplifications / |
| 93 | // optimizations which we should be able to opt-out of. |
| 94 | for (auto [CB, IFI] : CallSitesToInline) |
| 95 | InlineFunctionImpl(CB&: *CB, IFI); |
| 96 | } |
| 97 | |
| 98 | void llvm::reduceInlineCallSitesDeltaPass(Oracle &O, ReducerWorkItem &Program) { |
| 99 | for (Function &F : Program.getModule()) { |
| 100 | if (!F.isDeclaration()) |
| 101 | reduceCallSites(O, F); |
| 102 | } |
| 103 | } |
| 104 | |