brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.4 KiB · cfef367 Raw
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