104 lines · cpp
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-exception6//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 14using namespace llvm;15 16extern cl::OptionCategory LLVMReduceOptions;17 18static 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(5), cl::cat(LLVMReduceOptions));23 24static 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(BB.begin(), std::prev(BB.end()))) {29 (void)I;30 if (InstCount++ > NumInsts)31 return true;32 }33 }34 35 return false;36}37 38static bool hasOnlyOneCallUse(const Function &F) {39 unsigned UseCount = 0;40 for (const Use &U : F.uses()) {41 const CallBase *CB = dyn_cast<CallBase>(U.getUser());42 if (!CB || !CB->isCallee(&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.52static 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(Callee))59 return false;60 61 // Permit inlining small functions into big functions, or big functions into62 // small functions.63 if (!functionHasMoreThanNonTerminatorInsts(Callee, CallsiteInlineThreshold) &&64 !functionHasMoreThanNonTerminatorInsts(Caller, CallsiteInlineThreshold))65 return true;66 67 return false;68}69 70static 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>(U.getUser())) {75 // Ignore callsites with wrong call type.76 if (!CB->isCallee(&U))77 continue;78 79 // We do not consider isInlineViable here. It is overly conservative in80 // cases that the inliner should handle correctly (e.g. disallowing inline81 // of of functions with indirectbr). Some of the other cases are for other82 // 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, IFI).isSuccess() &&87 inlineWillReduceComplexity(*CB->getFunction(), F) && !O.shouldKeep())88 CallSitesToInline.emplace_back(CB, 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, IFI);96}97 98void llvm::reduceInlineCallSitesDeltaPass(Oracle &O, ReducerWorkItem &Program) {99 for (Function &F : Program.getModule()) {100 if (!F.isDeclaration())101 reduceCallSites(O, F);102 }103}104