//===- InlineCost.cpp - Cost analysis for inliner -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This file implements inline cost analysis.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/InlineCost.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/CodeMetrics.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomConditionCache.h"
#include "llvm/Analysis/EphemeralValuesCache.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/AssemblyAnnotationWriter.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/raw_ostream.h"
#include <climits>
#include <limits>
#include <optional>

using namespace llvm;

#define DEBUG_TYPE "inline-cost"

STATISTIC(NumCallsAnalyzed, "Number of call sites analyzed");

static cl::opt<int>
    DefaultThreshold("inlinedefault-threshold", cl::Hidden, cl::init(225),
                     cl::desc("Default amount of inlining to perform"));

// We introduce this option since there is a minor compile-time win by avoiding
// addition of TTI attributes (target-features in particular) to inline
// candidates when they are guaranteed to be the same as top level methods in
// some use cases. If we avoid adding the attribute, we need an option to avoid
// checking these attributes.
static cl::opt<bool> IgnoreTTIInlineCompatible(
    "ignore-tti-inline-compatible", cl::Hidden, cl::init(false),
    cl::desc("Ignore TTI attributes compatibility check between callee/caller "
             "during inline cost calculation"));

static cl::opt<bool> PrintInstructionComments(
    "print-instruction-comments", cl::Hidden, cl::init(false),
    cl::desc("Prints comments for instruction based on inline cost analysis"));

static cl::opt<int> InlineThreshold(
    "inline-threshold", cl::Hidden, cl::init(225),
    cl::desc("Control the amount of inlining to perform (default = 225)"));

static cl::opt<int> HintThreshold(
    "inlinehint-threshold", cl::Hidden, cl::init(325),
    cl::desc("Threshold for inlining functions with inline hint"));

static cl::opt<int>
    ColdCallSiteThreshold("inline-cold-callsite-threshold", cl::Hidden,
                          cl::init(45),
                          cl::desc("Threshold for inlining cold callsites"));

static cl::opt<bool> InlineEnableCostBenefitAnalysis(
    "inline-enable-cost-benefit-analysis", cl::Hidden, cl::init(false),
    cl::desc("Enable the cost-benefit analysis for the inliner"));

// InlineSavingsMultiplier overrides per TTI multipliers iff it is
// specified explicitly in command line options. This option is exposed
// for tuning and testing.
static cl::opt<int> InlineSavingsMultiplier(
    "inline-savings-multiplier", cl::Hidden, cl::init(8),
    cl::desc("Multiplier to multiply cycle savings by during inlining"));

// InlineSavingsProfitableMultiplier overrides per TTI multipliers iff it is
// specified explicitly in command line options. This option is exposed
// for tuning and testing.
static cl::opt<int> InlineSavingsProfitableMultiplier(
    "inline-savings-profitable-multiplier", cl::Hidden, cl::init(4),
    cl::desc("A multiplier on top of cycle savings to decide whether the "
             "savings won't justify the cost"));

static cl::opt<int>
    InlineSizeAllowance("inline-size-allowance", cl::Hidden, cl::init(100),
                        cl::desc("The maximum size of a callee that get's "
                                 "inlined without sufficient cycle savings"));

// We introduce this threshold to help performance of instrumentation based
// PGO before we actually hook up inliner with analysis passes such as BPI and
// BFI.
static cl::opt<int> ColdThreshold(
    "inlinecold-threshold", cl::Hidden, cl::init(45),
    cl::desc("Threshold for inlining functions with cold attribute"));

static cl::opt<int>
    HotCallSiteThreshold("hot-callsite-threshold", cl::Hidden, cl::init(3000),
                         cl::desc("Threshold for hot callsites "));

static cl::opt<int> LocallyHotCallSiteThreshold(
    "locally-hot-callsite-threshold", cl::Hidden, cl::init(525),
    cl::desc("Threshold for locally hot callsites "));

static cl::opt<int> ColdCallSiteRelFreq(
    "cold-callsite-rel-freq", cl::Hidden, cl::init(2),
    cl::desc("Maximum block frequency, expressed as a percentage of caller's "
             "entry frequency, for a callsite to be cold in the absence of "
             "profile information."));

static cl::opt<uint64_t> HotCallSiteRelFreq(
    "hot-callsite-rel-freq", cl::Hidden, cl::init(60),
    cl::desc("Minimum block frequency, expressed as a multiple of caller's "
             "entry frequency, for a callsite to be hot in the absence of "
             "profile information."));

static cl::opt<int>
    InstrCost("inline-instr-cost", cl::Hidden, cl::init(5),
              cl::desc("Cost of a single instruction when inlining"));

static cl::opt<int> InlineAsmInstrCost(
    "inline-asm-instr-cost", cl::Hidden, cl::init(0),
    cl::desc("Cost of a single inline asm instruction when inlining"));

static cl::opt<int>
    MemAccessCost("inline-memaccess-cost", cl::Hidden, cl::init(0),
                  cl::desc("Cost of load/store instruction when inlining"));

static cl::opt<int> CallPenalty(
    "inline-call-penalty", cl::Hidden, cl::init(25),
    cl::desc("Call penalty that is applied per callsite when inlining"));

static cl::opt<size_t>
    StackSizeThreshold("inline-max-stacksize", cl::Hidden,
                       cl::init(std::numeric_limits<size_t>::max()),
                       cl::desc("Do not inline functions with a stack size "
                                "that exceeds the specified limit"));

static cl::opt<size_t> RecurStackSizeThreshold(
    "recursive-inline-max-stacksize", cl::Hidden,
    cl::init(InlineConstants::TotalAllocaSizeRecursiveCaller),
    cl::desc("Do not inline recursive functions with a stack "
             "size that exceeds the specified limit"));

static cl::opt<bool> OptComputeFullInlineCost(
    "inline-cost-full", cl::Hidden,
    cl::desc("Compute the full inline cost of a call site even when the cost "
             "exceeds the threshold."));

static cl::opt<bool> InlineCallerSupersetNoBuiltin(
    "inline-caller-superset-nobuiltin", cl::Hidden, cl::init(true),
    cl::desc("Allow inlining when caller has a superset of callee's nobuiltin "
             "attributes."));

static cl::opt<bool> DisableGEPConstOperand(
    "disable-gep-const-evaluation", cl::Hidden, cl::init(false),
    cl::desc("Disables evaluation of GetElementPtr with constant operands"));

namespace llvm {
std::optional<int> getStringFnAttrAsInt(const Attribute &Attr) {
  if (Attr.isValid()) {
    int AttrValue = 0;
    if (!Attr.getValueAsString().getAsInteger(10, AttrValue))
      return AttrValue;
  }
  return std::nullopt;
}

std::optional<int> getStringFnAttrAsInt(CallBase &CB, StringRef AttrKind) {
  return getStringFnAttrAsInt(CB.getFnAttr(AttrKind));
}

std::optional<int> getStringFnAttrAsInt(Function *F, StringRef AttrKind) {
  return getStringFnAttrAsInt(F->getFnAttribute(AttrKind));
}

namespace InlineConstants {
int getInstrCost() { return InstrCost; }

} // namespace InlineConstants

} // namespace llvm

namespace {
class InlineCostCallAnalyzer;

// This struct is used to store information about inline cost of a
// particular instruction
struct InstructionCostDetail {
  int CostBefore = 0;
  int CostAfter = 0;
  int ThresholdBefore = 0;
  int ThresholdAfter = 0;

  int getThresholdDelta() const { return ThresholdAfter - ThresholdBefore; }

  int getCostDelta() const { return CostAfter - CostBefore; }

  bool hasThresholdChanged() const { return ThresholdAfter != ThresholdBefore; }
};

class InlineCostAnnotationWriter : public AssemblyAnnotationWriter {
private:
  InlineCostCallAnalyzer *const ICCA;

public:
  InlineCostAnnotationWriter(InlineCostCallAnalyzer *ICCA) : ICCA(ICCA) {}
  void emitInstructionAnnot(const Instruction *I,
                            formatted_raw_ostream &OS) override;
};

/// Carry out call site analysis, in order to evaluate inlinability.
/// NOTE: the type is currently used as implementation detail of functions such
/// as llvm::getInlineCost. Note the function_ref constructor parameters - the
/// expectation is that they come from the outer scope, from the wrapper
/// functions. If we want to support constructing CallAnalyzer objects where
/// lambdas are provided inline at construction, or where the object needs to
/// otherwise survive past the scope of the provided functions, we need to
/// revisit the argument types.
class CallAnalyzer : public InstVisitor<CallAnalyzer, bool> {
  typedef InstVisitor<CallAnalyzer, bool> Base;
  friend class InstVisitor<CallAnalyzer, bool>;

protected:
  virtual ~CallAnalyzer() = default;
  /// The TargetTransformInfo available for this compilation.
  const TargetTransformInfo &TTI;

  /// Getter for the cache of @llvm.assume intrinsics.
  function_ref<AssumptionCache &(Function &)> GetAssumptionCache;

  /// Getter for BlockFrequencyInfo
  function_ref<BlockFrequencyInfo &(Function &)> GetBFI;

  /// Getter for TargetLibraryInfo
  function_ref<const TargetLibraryInfo &(Function &)> GetTLI;

  /// Profile summary information.
  ProfileSummaryInfo *PSI;

  /// The called function.
  Function &F;

  // Cache the DataLayout since we use it a lot.
  const DataLayout &DL;

  /// The OptimizationRemarkEmitter available for this compilation.
  OptimizationRemarkEmitter *ORE;

  /// The candidate callsite being analyzed. Please do not use this to do
  /// analysis in the caller function; we want the inline cost query to be
  /// easily cacheable. Instead, use the cover function paramHasAttr.
  CallBase &CandidateCall;

  /// Getter for the cache of ephemeral values.
  function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache = nullptr;

  /// Extension points for handling callsite features.
  // Called before a basic block was analyzed.
  virtual void onBlockStart(const BasicBlock *BB) {}

  /// Called after a basic block was analyzed.
  virtual void onBlockAnalyzed(const BasicBlock *BB) {}

  /// Called before an instruction was analyzed
  virtual void onInstructionAnalysisStart(const Instruction *I) {}

  /// Called after an instruction was analyzed
  virtual void onInstructionAnalysisFinish(const Instruction *I) {}

  /// Called at the end of the analysis of the callsite. Return the outcome of
  /// the analysis, i.e. 'InlineResult(true)' if the inlining may happen, or
  /// the reason it can't.
  virtual InlineResult finalizeAnalysis() { return InlineResult::success(); }
  /// Called when we're about to start processing a basic block, and every time
  /// we are done processing an instruction. Return true if there is no point in
  /// continuing the analysis (e.g. we've determined already the call site is
  /// too expensive to inline)
  virtual bool shouldStop() { return false; }

  /// Called before the analysis of the callee body starts (with callsite
  /// contexts propagated).  It checks callsite-specific information. Return a
  /// reason analysis can't continue if that's the case, or 'true' if it may
  /// continue.
  virtual InlineResult onAnalysisStart() { return InlineResult::success(); }
  /// Called if the analysis engine decides SROA cannot be done for the given
  /// alloca.
  virtual void onDisableSROA(AllocaInst *Arg) {}

  /// Called the analysis engine determines load elimination won't happen.
  virtual void onDisableLoadElimination() {}

  /// Called when we visit a CallBase, before the analysis starts. Return false
  /// to stop further processing of the instruction.
  virtual bool onCallBaseVisitStart(CallBase &Call) { return true; }

  /// Called to account for a call.
  virtual void onCallPenalty() {}

  /// Called to account for a load or store.
  virtual void onMemAccess(){};

  /// Called to account for the expectation the inlining would result in a load
  /// elimination.
  virtual void onLoadEliminationOpportunity() {}

  /// Called to account for the cost of argument setup for the Call in the
  /// callee's body (not the callsite currently under analysis).
  virtual void onCallArgumentSetup(const CallBase &Call) {}

  /// Called to account for a load relative intrinsic.
  virtual void onLoadRelativeIntrinsic() {}

  /// Called to account for a lowered call.
  virtual void onLoweredCall(Function *F, CallBase &Call, bool IsIndirectCall) {
  }

  /// Account for a jump table of given size. Return false to stop further
  /// processing the switch instruction
  virtual bool onJumpTable(unsigned JumpTableSize) { return true; }

  /// Account for a case cluster of given size. Return false to stop further
  /// processing of the instruction.
  virtual bool onCaseCluster(unsigned NumCaseCluster) { return true; }

  /// Called at the end of processing a switch instruction, with the given
  /// number of case clusters.
  virtual void onFinalizeSwitch(unsigned JumpTableSize, unsigned NumCaseCluster,
                                bool DefaultDestUnreachable) {}

  /// Called to account for any other instruction not specifically accounted
  /// for.
  virtual void onMissedSimplification() {}

  /// Account for inline assembly instructions.
  virtual void onInlineAsm(const InlineAsm &Arg) {}

  /// Start accounting potential benefits due to SROA for the given alloca.
  virtual void onInitializeSROAArg(AllocaInst *Arg) {}

  /// Account SROA savings for the AllocaInst value.
  virtual void onAggregateSROAUse(AllocaInst *V) {}

  bool handleSROA(Value *V, bool DoNotDisable) {
    // Check for SROA candidates in comparisons.
    if (auto *SROAArg = getSROAArgForValueOrNull(V)) {
      if (DoNotDisable) {
        onAggregateSROAUse(SROAArg);
        return true;
      }
      disableSROAForArg(SROAArg);
    }
    return false;
  }

  bool IsCallerRecursive = false;
  bool IsRecursiveCall = false;
  bool ExposesReturnsTwice = false;
  bool HasDynamicAlloca = false;
  bool ContainsNoDuplicateCall = false;
  bool HasReturn = false;
  bool HasIndirectBr = false;
  bool HasUninlineableIntrinsic = false;
  bool InitsVargArgs = false;

  /// Number of bytes allocated statically by the callee.
  uint64_t AllocatedSize = 0;
  unsigned NumInstructions = 0;
  unsigned NumInlineAsmInstructions = 0;
  unsigned NumVectorInstructions = 0;

  /// While we walk the potentially-inlined instructions, we build up and
  /// maintain a mapping of simplified values specific to this callsite. The
  /// idea is to propagate any special information we have about arguments to
  /// this call through the inlinable section of the function, and account for
  /// likely simplifications post-inlining. The most important aspect we track
  /// is CFG altering simplifications -- when we prove a basic block dead, that
  /// can cause dramatic shifts in the cost of inlining a function.
  /// Note: The simplified Value may be owned by the caller function.
  DenseMap<Value *, Value *> SimplifiedValues;

  /// Keep track of the values which map back (through function arguments) to
  /// allocas on the caller stack which could be simplified through SROA.
  DenseMap<Value *, AllocaInst *> SROAArgValues;

  /// Keep track of Allocas for which we believe we may get SROA optimization.
  DenseSet<AllocaInst *> EnabledSROAAllocas;

  /// Keep track of values which map to a pointer base and constant offset.
  DenseMap<Value *, std::pair<Value *, APInt>> ConstantOffsetPtrs;

  /// Keep track of dead blocks due to the constant arguments.
  SmallPtrSet<BasicBlock *, 16> DeadBlocks;

  /// The mapping of the blocks to their known unique successors due to the
  /// constant arguments.
  DenseMap<BasicBlock *, BasicBlock *> KnownSuccessors;

  /// Model the elimination of repeated loads that is expected to happen
  /// whenever we simplify away the stores that would otherwise cause them to be
  /// loads.
  bool EnableLoadElimination = true;

  /// Whether we allow inlining for recursive call.
  bool AllowRecursiveCall = false;

  SmallPtrSet<Value *, 16> LoadAddrSet;

  AllocaInst *getSROAArgForValueOrNull(Value *V) const {
    auto It = SROAArgValues.find(V);
    if (It == SROAArgValues.end() || EnabledSROAAllocas.count(It->second) == 0)
      return nullptr;
    return It->second;
  }

  /// Use a value in its given form directly if possible, otherwise try looking
  /// for it in SimplifiedValues.
  template <typename T> T *getDirectOrSimplifiedValue(Value *V) const {
    if (auto *Direct = dyn_cast<T>(V))
      return Direct;
    return getSimplifiedValue<T>(V);
  }

  // Custom simplification helper routines.
  bool isAllocaDerivedArg(Value *V);
  void disableSROAForArg(AllocaInst *SROAArg);
  void disableSROA(Value *V);
  void findDeadBlocks(BasicBlock *CurrBB, BasicBlock *NextBB);
  void disableLoadElimination();
  bool isGEPFree(GetElementPtrInst &GEP);
  bool canFoldInboundsGEP(GetElementPtrInst &I);
  bool accumulateGEPOffset(GEPOperator &GEP, APInt &Offset);
  bool simplifyCallSite(Function *F, CallBase &Call);
  bool simplifyCmpInstForRecCall(CmpInst &Cmp);
  bool simplifyInstruction(Instruction &I);
  bool simplifyIntrinsicCallIsConstant(CallBase &CB);
  bool simplifyIntrinsicCallObjectSize(CallBase &CB);
  ConstantInt *stripAndComputeInBoundsConstantOffsets(Value *&V);
  bool isLoweredToCall(Function *F, CallBase &Call);

  /// Return true if the given argument to the function being considered for
  /// inlining has the given attribute set either at the call site or the
  /// function declaration.  Primarily used to inspect call site specific
  /// attributes since these can be more precise than the ones on the callee
  /// itself.
  bool paramHasAttr(Argument *A, Attribute::AttrKind Attr);

  /// Return true if the given value is known non null within the callee if
  /// inlined through this particular callsite.
  bool isKnownNonNullInCallee(Value *V);

  /// Return true if size growth is allowed when inlining the callee at \p Call.
  bool allowSizeGrowth(CallBase &Call);

  // Custom analysis routines.
  InlineResult analyzeBlock(BasicBlock *BB,
                            const SmallPtrSetImpl<const Value *> &EphValues);

  // Disable several entry points to the visitor so we don't accidentally use
  // them by declaring but not defining them here.
  void visit(Module *);
  void visit(Module &);
  void visit(Function *);
  void visit(Function &);
  void visit(BasicBlock *);
  void visit(BasicBlock &);

  // Provide base case for our instruction visit.
  bool visitInstruction(Instruction &I);

  // Our visit overrides.
  bool visitAlloca(AllocaInst &I);
  bool visitPHI(PHINode &I);
  bool visitGetElementPtr(GetElementPtrInst &I);
  bool visitBitCast(BitCastInst &I);
  bool visitPtrToInt(PtrToIntInst &I);
  bool visitIntToPtr(IntToPtrInst &I);
  bool visitCastInst(CastInst &I);
  bool visitCmpInst(CmpInst &I);
  bool visitSub(BinaryOperator &I);
  bool visitBinaryOperator(BinaryOperator &I);
  bool visitFNeg(UnaryOperator &I);
  bool visitLoad(LoadInst &I);
  bool visitStore(StoreInst &I);
  bool visitExtractValue(ExtractValueInst &I);
  bool visitInsertValue(InsertValueInst &I);
  bool visitCallBase(CallBase &Call);
  bool visitReturnInst(ReturnInst &RI);
  bool visitBranchInst(BranchInst &BI);
  bool visitSelectInst(SelectInst &SI);
  bool visitSwitchInst(SwitchInst &SI);
  bool visitIndirectBrInst(IndirectBrInst &IBI);
  bool visitResumeInst(ResumeInst &RI);
  bool visitCleanupReturnInst(CleanupReturnInst &RI);
  bool visitCatchReturnInst(CatchReturnInst &RI);
  bool visitUnreachableInst(UnreachableInst &I);

public:
  CallAnalyzer(
      Function &Callee, CallBase &Call, const TargetTransformInfo &TTI,
      function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
      function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
      function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
      ProfileSummaryInfo *PSI = nullptr,
      OptimizationRemarkEmitter *ORE = nullptr,
      function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache =
          nullptr)
      : TTI(TTI), GetAssumptionCache(GetAssumptionCache), GetBFI(GetBFI),
        GetTLI(GetTLI), PSI(PSI), F(Callee), DL(F.getDataLayout()), ORE(ORE),
        CandidateCall(Call), GetEphValuesCache(GetEphValuesCache) {}

  InlineResult analyze();

  /// Lookup simplified Value. May return a value owned by the caller.
  Value *getSimplifiedValueUnchecked(Value *V) const {
    return SimplifiedValues.lookup(V);
  }

  /// Lookup simplified Value, but return nullptr if the simplified value is
  /// owned by the caller.
  template <typename T> T *getSimplifiedValue(Value *V) const {
    Value *SimpleV = SimplifiedValues.lookup(V);
    if (!SimpleV)
      return nullptr;

    // Skip checks if we know T is a global. This has a small, but measurable
    // impact on compile-time.
    if constexpr (std::is_base_of_v<Constant, T>)
      return dyn_cast<T>(SimpleV);

    // Make sure the simplified Value is owned by this function
    if (auto *I = dyn_cast<Instruction>(SimpleV)) {
      if (I->getFunction() != &F)
        return nullptr;
    } else if (auto *Arg = dyn_cast<Argument>(SimpleV)) {
      if (Arg->getParent() != &F)
        return nullptr;
    } else if (!isa<Constant>(SimpleV))
      return nullptr;
    return dyn_cast<T>(SimpleV);
  }

  // Keep a bunch of stats about the cost savings found so we can print them
  // out when debugging.
  unsigned NumConstantArgs = 0;
  unsigned NumConstantOffsetPtrArgs = 0;
  unsigned NumAllocaArgs = 0;
  unsigned NumConstantPtrCmps = 0;
  unsigned NumConstantPtrDiffs = 0;
  unsigned NumInstructionsSimplified = 0;

  void dump();
};

// Considering forming a binary search, we should find the number of nodes
// which is same as the number of comparisons when lowered. For a given
// number of clusters, n, we can define a recursive function, f(n), to find
// the number of nodes in the tree. The recursion is :
// f(n) = 1 + f(n/2) + f (n - n/2), when n > 3,
// and f(n) = n, when n <= 3.
// This will lead a binary tree where the leaf should be either f(2) or f(3)
// when n > 3.  So, the number of comparisons from leaves should be n, while
// the number of non-leaf should be :
//   2^(log2(n) - 1) - 1
//   = 2^log2(n) * 2^-1 - 1
//   = n / 2 - 1.
// Considering comparisons from leaf and non-leaf nodes, we can estimate the
// number of comparisons in a simple closed form :
//   n + n / 2 - 1 = n * 3 / 2 - 1
int64_t getExpectedNumberOfCompare(int NumCaseCluster) {
  return 3 * static_cast<int64_t>(NumCaseCluster) / 2 - 1;
}

/// FIXME: if it is necessary to derive from InlineCostCallAnalyzer, note
/// the FIXME in onLoweredCall, when instantiating an InlineCostCallAnalyzer
class InlineCostCallAnalyzer final : public CallAnalyzer {
  const bool ComputeFullInlineCost;
  int LoadEliminationCost = 0;
  /// Bonus to be applied when percentage of vector instructions in callee is
  /// high (see more details in updateThreshold).
  int VectorBonus = 0;
  /// Bonus to be applied when the callee has only one reachable basic block.
  int SingleBBBonus = 0;

  /// Tunable parameters that control the analysis.
  const InlineParams &Params;

  // This DenseMap stores the delta change in cost and threshold after
  // accounting for the given instruction. The map is filled only with the
  // flag PrintInstructionComments on.
  DenseMap<const Instruction *, InstructionCostDetail> InstructionCostDetailMap;

  /// Upper bound for the inlining cost. Bonuses are being applied to account
  /// for speculative "expected profit" of the inlining decision.
  int Threshold = 0;

  /// The amount of StaticBonus applied.
  int StaticBonusApplied = 0;

  /// Attempt to evaluate indirect calls to boost its inline cost.
  const bool BoostIndirectCalls;

  /// Ignore the threshold when finalizing analysis.
  const bool IgnoreThreshold;

  // True if the cost-benefit-analysis-based inliner is enabled.
  const bool CostBenefitAnalysisEnabled;

  /// Inlining cost measured in abstract units, accounts for all the
  /// instructions expected to be executed for a given function invocation.
  /// Instructions that are statically proven to be dead based on call-site
  /// arguments are not counted here.
  int Cost = 0;

  // The cumulative cost at the beginning of the basic block being analyzed.  At
  // the end of analyzing each basic block, "Cost - CostAtBBStart" represents
  // the size of that basic block.
  int CostAtBBStart = 0;

  // The static size of live but cold basic blocks.  This is "static" in the
  // sense that it's not weighted by profile counts at all.
  int ColdSize = 0;

  // Whether inlining is decided by cost-threshold analysis.
  bool DecidedByCostThreshold = false;

  // Whether inlining is decided by cost-benefit analysis.
  bool DecidedByCostBenefit = false;

  // The cost-benefit pair computed by cost-benefit analysis.
  std::optional<CostBenefitPair> CostBenefit;

  bool SingleBB = true;

  unsigned SROACostSavings = 0;
  unsigned SROACostSavingsLost = 0;

  /// The mapping of caller Alloca values to their accumulated cost savings. If
  /// we have to disable SROA for one of the allocas, this tells us how much
  /// cost must be added.
  DenseMap<AllocaInst *, int> SROAArgCosts;

  /// Return true if \p Call is a cold callsite.
  bool isColdCallSite(CallBase &Call, BlockFrequencyInfo *CallerBFI);

  /// Update Threshold based on callsite properties such as callee
  /// attributes and callee hotness for PGO builds. The Callee is explicitly
  /// passed to support analyzing indirect calls whose target is inferred by
  /// analysis.
  void updateThreshold(CallBase &Call, Function &Callee);
  /// Return a higher threshold if \p Call is a hot callsite.
  std::optional<int> getHotCallSiteThreshold(CallBase &Call,
                                             BlockFrequencyInfo *CallerBFI);

  /// Handle a capped 'int' increment for Cost.
  void addCost(int64_t Inc) {
    Inc = std::clamp<int64_t>(Inc, INT_MIN, INT_MAX);
    Cost = std::clamp<int64_t>(Inc + Cost, INT_MIN, INT_MAX);
  }

  void onDisableSROA(AllocaInst *Arg) override {
    auto CostIt = SROAArgCosts.find(Arg);
    if (CostIt == SROAArgCosts.end())
      return;
    addCost(CostIt->second);
    SROACostSavings -= CostIt->second;
    SROACostSavingsLost += CostIt->second;
    SROAArgCosts.erase(CostIt);
  }

  void onDisableLoadElimination() override {
    addCost(LoadEliminationCost);
    LoadEliminationCost = 0;
  }

  bool onCallBaseVisitStart(CallBase &Call) override {
    if (std::optional<int> AttrCallThresholdBonus =
            getStringFnAttrAsInt(Call, "call-threshold-bonus"))
      Threshold += *AttrCallThresholdBonus;

    if (std::optional<int> AttrCallCost =
            getStringFnAttrAsInt(Call, "call-inline-cost")) {
      addCost(*AttrCallCost);
      // Prevent further processing of the call since we want to override its
      // inline cost, not just add to it.
      return false;
    }
    return true;
  }

  void onCallPenalty() override { addCost(CallPenalty); }

  void onMemAccess() override { addCost(MemAccessCost); }

  void onCallArgumentSetup(const CallBase &Call) override {
    // Pay the price of the argument setup. We account for the average 1
    // instruction per call argument setup here.
    addCost(Call.arg_size() * InstrCost);
  }
  void onLoadRelativeIntrinsic() override {
    // This is normally lowered to 4 LLVM instructions.
    addCost(3 * InstrCost);
  }
  void onLoweredCall(Function *F, CallBase &Call,
                     bool IsIndirectCall) override {
    // We account for the average 1 instruction per call argument setup here.
    addCost(Call.arg_size() * InstrCost);

    // If we have a constant that we are calling as a function, we can peer
    // through it and see the function target. This happens not infrequently
    // during devirtualization and so we want to give it a hefty bonus for
    // inlining, but cap that bonus in the event that inlining wouldn't pan out.
    // Pretend to inline the function, with a custom threshold.
    if (IsIndirectCall && BoostIndirectCalls) {
      auto IndirectCallParams = Params;
      IndirectCallParams.DefaultThreshold =
          InlineConstants::IndirectCallThreshold;
      /// FIXME: if InlineCostCallAnalyzer is derived from, this may need
      /// to instantiate the derived class.
      InlineCostCallAnalyzer CA(*F, Call, IndirectCallParams, TTI,
                                GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
                                false);
      if (CA.analyze().isSuccess()) {
        // We were able to inline the indirect call! Subtract the cost from the
        // threshold to get the bonus we want to apply, but don't go below zero.
        Cost -= std::max(0, CA.getThreshold() - CA.getCost());
      }
    } else
      // Otherwise simply add the cost for merely making the call.
      addCost(TTI.getInlineCallPenalty(CandidateCall.getCaller(), Call,
                                       CallPenalty));
  }

  void onFinalizeSwitch(unsigned JumpTableSize, unsigned NumCaseCluster,
                        bool DefaultDestUnreachable) override {
    // If suitable for a jump table, consider the cost for the table size and
    // branch to destination.
    // Maximum valid cost increased in this function.
    if (JumpTableSize) {
      // Suppose a default branch includes one compare and one conditional
      // branch if it's reachable.
      if (!DefaultDestUnreachable)
        addCost(2 * InstrCost);
      // Suppose a jump table requires one load and one jump instruction.
      int64_t JTCost =
          static_cast<int64_t>(JumpTableSize) * InstrCost + 2 * InstrCost;
      addCost(JTCost);
      return;
    }

    if (NumCaseCluster <= 3) {
      // Suppose a comparison includes one compare and one conditional branch.
      // We can reduce a set of instructions if the default branch is
      // undefined.
      addCost((NumCaseCluster - DefaultDestUnreachable) * 2 * InstrCost);
      return;
    }

    int64_t ExpectedNumberOfCompare =
        getExpectedNumberOfCompare(NumCaseCluster);
    int64_t SwitchCost = ExpectedNumberOfCompare * 2 * InstrCost;

    addCost(SwitchCost);
  }

  // Parses the inline assembly argument to account for its cost. Inline
  // assembly instructions incur higher costs for inlining since they cannot be
  // analyzed and optimized.
  void onInlineAsm(const InlineAsm &Arg) override {
    if (!InlineAsmInstrCost)
      return;
    SmallVector<StringRef, 4> AsmStrs;
    Arg.collectAsmStrs(AsmStrs);
    int SectionLevel = 0;
    int InlineAsmInstrCount = 0;
    for (StringRef AsmStr : AsmStrs) {
      // Trim whitespaces and comments.
      StringRef Trimmed = AsmStr.trim();
      size_t hashPos = Trimmed.find('#');
      if (hashPos != StringRef::npos)
        Trimmed = Trimmed.substr(0, hashPos);
      // Ignore comments.
      if (Trimmed.empty())
        continue;
      // Filter out the outlined assembly instructions from the cost by keeping
      // track of the section level and only accounting for instrutions at
      // section level of zero. Note there will be duplication in outlined
      // sections too, but is not accounted in the inlining cost model.
      if (Trimmed.starts_with(".pushsection")) {
        ++SectionLevel;
        continue;
      }
      if (Trimmed.starts_with(".popsection")) {
        --SectionLevel;
        continue;
      }
      // Ignore directives and labels.
      if (Trimmed.starts_with(".") || Trimmed.contains(":"))
        continue;
      if (SectionLevel == 0)
        ++InlineAsmInstrCount;
    }
    NumInlineAsmInstructions += InlineAsmInstrCount;
    addCost(InlineAsmInstrCount * InlineAsmInstrCost);
  }

  void onMissedSimplification() override { addCost(InstrCost); }

  void onInitializeSROAArg(AllocaInst *Arg) override {
    assert(Arg != nullptr &&
           "Should not initialize SROA costs for null value.");
    auto SROAArgCost = TTI.getCallerAllocaCost(&CandidateCall, Arg);
    SROACostSavings += SROAArgCost;
    SROAArgCosts[Arg] = SROAArgCost;
  }

  void onAggregateSROAUse(AllocaInst *SROAArg) override {
    auto CostIt = SROAArgCosts.find(SROAArg);
    assert(CostIt != SROAArgCosts.end() &&
           "expected this argument to have a cost");
    CostIt->second += InstrCost;
    SROACostSavings += InstrCost;
  }

  void onBlockStart(const BasicBlock *BB) override { CostAtBBStart = Cost; }

  void onBlockAnalyzed(const BasicBlock *BB) override {
    if (CostBenefitAnalysisEnabled) {
      // Keep track of the static size of live but cold basic blocks.  For now,
      // we define a cold basic block to be one that's never executed.
      assert(GetBFI && "GetBFI must be available");
      BlockFrequencyInfo *BFI = &(GetBFI(F));
      assert(BFI && "BFI must be available");
      auto ProfileCount = BFI->getBlockProfileCount(BB);
      if (*ProfileCount == 0)
        ColdSize += Cost - CostAtBBStart;
    }

    auto *TI = BB->getTerminator();
    // If we had any successors at this point, than post-inlining is likely to
    // have them as well. Note that we assume any basic blocks which existed
    // due to branches or switches which folded above will also fold after
    // inlining.
    if (SingleBB && TI->getNumSuccessors() > 1) {
      // Take off the bonus we applied to the threshold.
      Threshold -= SingleBBBonus;
      SingleBB = false;
    }
  }

  void onInstructionAnalysisStart(const Instruction *I) override {
    // This function is called to store the initial cost of inlining before
    // the given instruction was assessed.
    if (!PrintInstructionComments)
      return;
    auto &CostDetail = InstructionCostDetailMap[I];
    CostDetail.CostBefore = Cost;
    CostDetail.ThresholdBefore = Threshold;
  }

  void onInstructionAnalysisFinish(const Instruction *I) override {
    // This function is called to find new values of cost and threshold after
    // the instruction has been assessed.
    if (!PrintInstructionComments)
      return;
    auto &CostDetail = InstructionCostDetailMap[I];
    CostDetail.CostAfter = Cost;
    CostDetail.ThresholdAfter = Threshold;
  }

  bool isCostBenefitAnalysisEnabled() {
    if (!PSI || !PSI->hasProfileSummary())
      return false;

    if (!GetBFI)
      return false;

    if (InlineEnableCostBenefitAnalysis.getNumOccurrences()) {
      // Honor the explicit request from the user.
      if (!InlineEnableCostBenefitAnalysis)
        return false;
    } else {
      // Otherwise, require instrumentation profile.
      if (!PSI->hasInstrumentationProfile())
        return false;
    }

    auto *Caller = CandidateCall.getParent()->getParent();
    if (!Caller->getEntryCount())
      return false;

    BlockFrequencyInfo *CallerBFI = &(GetBFI(*Caller));
    if (!CallerBFI)
      return false;

    // For now, limit to hot call site.
    if (!PSI->isHotCallSite(CandidateCall, CallerBFI))
      return false;

    // Make sure we have a nonzero entry count.
    auto EntryCount = F.getEntryCount();
    if (!EntryCount || !EntryCount->getCount())
      return false;

    BlockFrequencyInfo *CalleeBFI = &(GetBFI(F));
    if (!CalleeBFI)
      return false;

    return true;
  }

  // A helper function to choose between command line override and default.
  unsigned getInliningCostBenefitAnalysisSavingsMultiplier() const {
    if (InlineSavingsMultiplier.getNumOccurrences())
      return InlineSavingsMultiplier;
    return TTI.getInliningCostBenefitAnalysisSavingsMultiplier();
  }

  // A helper function to choose between command line override and default.
  unsigned getInliningCostBenefitAnalysisProfitableMultiplier() const {
    if (InlineSavingsProfitableMultiplier.getNumOccurrences())
      return InlineSavingsProfitableMultiplier;
    return TTI.getInliningCostBenefitAnalysisProfitableMultiplier();
  }

  void OverrideCycleSavingsAndSizeForTesting(APInt &CycleSavings, int &Size) {
    if (std::optional<int> AttrCycleSavings = getStringFnAttrAsInt(
            CandidateCall, "inline-cycle-savings-for-test")) {
      CycleSavings = *AttrCycleSavings;
    }

    if (std::optional<int> AttrRuntimeCost = getStringFnAttrAsInt(
            CandidateCall, "inline-runtime-cost-for-test")) {
      Size = *AttrRuntimeCost;
    }
  }

  // Determine whether we should inline the given call site, taking into account
  // both the size cost and the cycle savings.  Return std::nullopt if we don't
  // have sufficient profiling information to determine.
  std::optional<bool> costBenefitAnalysis() {
    if (!CostBenefitAnalysisEnabled)
      return std::nullopt;

    // buildInlinerPipeline in the pass builder sets HotCallSiteThreshold to 0
    // for the prelink phase of the AutoFDO + ThinLTO build.  Honor the logic by
    // falling back to the cost-based metric.
    // TODO: Improve this hacky condition.
    if (Threshold == 0)
      return std::nullopt;

    assert(GetBFI);
    BlockFrequencyInfo *CalleeBFI = &(GetBFI(F));
    assert(CalleeBFI);

    // The cycle savings expressed as the sum of InstrCost
    // multiplied by the estimated dynamic count of each instruction we can
    // avoid.  Savings come from the call site cost, such as argument setup and
    // the call instruction, as well as the instructions that are folded.
    //
    // We use 128-bit APInt here to avoid potential overflow.  This variable
    // should stay well below 10^^24 (or 2^^80) in practice.  This "worst" case
    // assumes that we can avoid or fold a billion instructions, each with a
    // profile count of 10^^15 -- roughly the number of cycles for a 24-hour
    // period on a 4GHz machine.
    APInt CycleSavings(128, 0);

    for (auto &BB : F) {
      APInt CurrentSavings(128, 0);
      for (auto &I : BB) {
        if (BranchInst *BI = dyn_cast<BranchInst>(&I)) {
          // Count a conditional branch as savings if it becomes unconditional.
          if (BI->isConditional() &&
              getSimplifiedValue<ConstantInt>(BI->getCondition())) {
            CurrentSavings += InstrCost;
          }
        } else if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) {
          if (getSimplifiedValue<ConstantInt>(SI->getCondition()))
            CurrentSavings += InstrCost;
        } else if (Value *V = dyn_cast<Value>(&I)) {
          // Count an instruction as savings if we can fold it.
          if (SimplifiedValues.count(V)) {
            CurrentSavings += InstrCost;
          }
        }
      }

      auto ProfileCount = CalleeBFI->getBlockProfileCount(&BB);
      CurrentSavings *= *ProfileCount;
      CycleSavings += CurrentSavings;
    }

    // Compute the cycle savings per call.
    auto EntryProfileCount = F.getEntryCount();
    assert(EntryProfileCount && EntryProfileCount->getCount());
    auto EntryCount = EntryProfileCount->getCount();
    CycleSavings += EntryCount / 2;
    CycleSavings = CycleSavings.udiv(EntryCount);

    // Compute the total savings for the call site.
    auto *CallerBB = CandidateCall.getParent();
    BlockFrequencyInfo *CallerBFI = &(GetBFI(*(CallerBB->getParent())));
    CycleSavings += getCallsiteCost(TTI, this->CandidateCall, DL);
    CycleSavings *= *CallerBFI->getBlockProfileCount(CallerBB);

    // Remove the cost of the cold basic blocks to model the runtime cost more
    // accurately. Both machine block placement and function splitting could
    // place cold blocks further from hot blocks.
    int Size = Cost - ColdSize;

    // Allow tiny callees to be inlined regardless of whether they meet the
    // savings threshold.
    Size = Size > InlineSizeAllowance ? Size - InlineSizeAllowance : 1;

    OverrideCycleSavingsAndSizeForTesting(CycleSavings, Size);
    CostBenefit.emplace(APInt(128, Size), CycleSavings);

    // Let R be the ratio of CycleSavings to Size.  We accept the inlining
    // opportunity if R is really high and reject if R is really low.  If R is
    // somewhere in the middle, we fall back to the cost-based analysis.
    //
    // Specifically, let R = CycleSavings / Size, we accept the inlining
    // opportunity if:
    //
    //             PSI->getOrCompHotCountThreshold()
    // R > -------------------------------------------------
    //     getInliningCostBenefitAnalysisSavingsMultiplier()
    //
    // and reject the inlining opportunity if:
    //
    //                PSI->getOrCompHotCountThreshold()
    // R <= ----------------------------------------------------
    //      getInliningCostBenefitAnalysisProfitableMultiplier()
    //
    // Otherwise, we fall back to the cost-based analysis.
    //
    // Implementation-wise, use multiplication (CycleSavings * Multiplier,
    // HotCountThreshold * Size) rather than division to avoid precision loss.
    APInt Threshold(128, PSI->getOrCompHotCountThreshold());
    Threshold *= Size;

    APInt UpperBoundCycleSavings = CycleSavings;
    UpperBoundCycleSavings *= getInliningCostBenefitAnalysisSavingsMultiplier();
    if (UpperBoundCycleSavings.uge(Threshold))
      return true;

    APInt LowerBoundCycleSavings = CycleSavings;
    LowerBoundCycleSavings *=
        getInliningCostBenefitAnalysisProfitableMultiplier();
    if (LowerBoundCycleSavings.ult(Threshold))
      return false;

    // Otherwise, fall back to the cost-based analysis.
    return std::nullopt;
  }

  InlineResult finalizeAnalysis() override {
    // Loops generally act a lot like calls in that they act like barriers to
    // movement, require a certain amount of setup, etc. So when optimising for
    // size, we penalise any call sites that perform loops. We do this after all
    // other costs here, so will likely only be dealing with relatively small
    // functions (and hence DT and LI will hopefully be cheap).
    auto *Caller = CandidateCall.getFunction();
    if (Caller->hasMinSize()) {
      DominatorTree DT(F);
      LoopInfo LI(DT);
      int NumLoops = 0;
      for (Loop *L : LI) {
        // Ignore loops that will not be executed
        if (DeadBlocks.count(L->getHeader()))
          continue;
        NumLoops++;
      }
      addCost(NumLoops * InlineConstants::LoopPenalty);
    }

    // We applied the maximum possible vector bonus at the beginning. Now,
    // subtract the excess bonus, if any, from the Threshold before
    // comparing against Cost.
    if (NumVectorInstructions <= NumInstructions / 10)
      Threshold -= VectorBonus;
    else if (NumVectorInstructions <= NumInstructions / 2)
      Threshold -= VectorBonus / 2;

    if (std::optional<int> AttrCost =
            getStringFnAttrAsInt(CandidateCall, "function-inline-cost"))
      Cost = *AttrCost;

    if (std::optional<int> AttrCostMult = getStringFnAttrAsInt(
            CandidateCall,
            InlineConstants::FunctionInlineCostMultiplierAttributeName))
      Cost *= *AttrCostMult;

    if (std::optional<int> AttrThreshold =
            getStringFnAttrAsInt(CandidateCall, "function-inline-threshold"))
      Threshold = *AttrThreshold;

    if (auto Result = costBenefitAnalysis()) {
      DecidedByCostBenefit = true;
      if (*Result)
        return InlineResult::success();
      else
        return InlineResult::failure("Cost over threshold.");
    }

    if (IgnoreThreshold)
      return InlineResult::success();

    DecidedByCostThreshold = true;
    return Cost < std::max(1, Threshold)
               ? InlineResult::success()
               : InlineResult::failure("Cost over threshold.");
  }

  bool shouldStop() override {
    if (IgnoreThreshold || ComputeFullInlineCost)
      return false;
    // Bail out the moment we cross the threshold. This means we'll under-count
    // the cost, but only when undercounting doesn't matter.
    if (Cost < Threshold)
      return false;
    DecidedByCostThreshold = true;
    return true;
  }

  void onLoadEliminationOpportunity() override {
    LoadEliminationCost += InstrCost;
  }

  InlineResult onAnalysisStart() override {
    // Perform some tweaks to the cost and threshold based on the direct
    // callsite information.

    // We want to more aggressively inline vector-dense kernels, so up the
    // threshold, and we'll lower it if the % of vector instructions gets too
    // low. Note that these bonuses are some what arbitrary and evolved over
    // time by accident as much as because they are principled bonuses.
    //
    // FIXME: It would be nice to remove all such bonuses. At least it would be
    // nice to base the bonus values on something more scientific.
    assert(NumInstructions == 0);
    assert(NumVectorInstructions == 0);

    // Update the threshold based on callsite properties
    updateThreshold(CandidateCall, F);

    // While Threshold depends on commandline options that can take negative
    // values, we want to enforce the invariant that the computed threshold and
    // bonuses are non-negative.
    assert(Threshold >= 0);
    assert(SingleBBBonus >= 0);
    assert(VectorBonus >= 0);

    // Speculatively apply all possible bonuses to Threshold. If cost exceeds
    // this Threshold any time, and cost cannot decrease, we can stop processing
    // the rest of the function body.
    Threshold += (SingleBBBonus + VectorBonus);

    // Give out bonuses for the callsite, as the instructions setting them up
    // will be gone after inlining.
    addCost(-getCallsiteCost(TTI, this->CandidateCall, DL));

    // If this function uses the coldcc calling convention, prefer not to inline
    // it.
    if (F.getCallingConv() == CallingConv::Cold)
      Cost += InlineConstants::ColdccPenalty;

    LLVM_DEBUG(dbgs() << "      Initial cost: " << Cost << "\n");

    // Check if we're done. This can happen due to bonuses and penalties.
    if (Cost >= Threshold && !ComputeFullInlineCost)
      return InlineResult::failure("high cost");

    return InlineResult::success();
  }

public:
  InlineCostCallAnalyzer(
      Function &Callee, CallBase &Call, const InlineParams &Params,
      const TargetTransformInfo &TTI,
      function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
      function_ref<BlockFrequencyInfo &(Function &)> GetBFI = nullptr,
      function_ref<const TargetLibraryInfo &(Function &)> GetTLI = nullptr,
      ProfileSummaryInfo *PSI = nullptr,
      OptimizationRemarkEmitter *ORE = nullptr, bool BoostIndirect = true,
      bool IgnoreThreshold = false,
      function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache =
          nullptr)
      : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI, PSI,
                     ORE, GetEphValuesCache),
        ComputeFullInlineCost(OptComputeFullInlineCost ||
                              Params.ComputeFullInlineCost || ORE ||
                              isCostBenefitAnalysisEnabled()),
        Params(Params), Threshold(Params.DefaultThreshold),
        BoostIndirectCalls(BoostIndirect), IgnoreThreshold(IgnoreThreshold),
        CostBenefitAnalysisEnabled(isCostBenefitAnalysisEnabled()),
        Writer(this) {
    AllowRecursiveCall = *Params.AllowRecursiveCall;
  }

  /// Annotation Writer for instruction details
  InlineCostAnnotationWriter Writer;

  void dump();

  // Prints the same analysis as dump(), but its definition is not dependent
  // on the build.
  void print(raw_ostream &OS);

  std::optional<InstructionCostDetail> getCostDetails(const Instruction *I) {
    auto It = InstructionCostDetailMap.find(I);
    if (It != InstructionCostDetailMap.end())
      return It->second;
    return std::nullopt;
  }

  virtual ~InlineCostCallAnalyzer() = default;
  int getThreshold() const { return Threshold; }
  int getCost() const { return Cost; }
  int getStaticBonusApplied() const { return StaticBonusApplied; }
  std::optional<CostBenefitPair> getCostBenefitPair() { return CostBenefit; }
  bool wasDecidedByCostBenefit() const { return DecidedByCostBenefit; }
  bool wasDecidedByCostThreshold() const { return DecidedByCostThreshold; }
};

// Return true if CB is the sole call to local function Callee.
static bool isSoleCallToLocalFunction(const CallBase &CB,
                                      const Function &Callee) {
  return Callee.hasLocalLinkage() && Callee.hasOneLiveUse() &&
         &Callee == CB.getCalledFunction();
}

class InlineCostFeaturesAnalyzer final : public CallAnalyzer {
private:
  InlineCostFeatures Cost = {};

  // FIXME: These constants are taken from the heuristic-based cost visitor.
  // These should be removed entirely in a later revision to avoid reliance on
  // heuristics in the ML inliner.
  static constexpr int JTCostMultiplier = 2;
  static constexpr int CaseClusterCostMultiplier = 2;
  static constexpr int SwitchDefaultDestCostMultiplier = 2;
  static constexpr int SwitchCostMultiplier = 2;

  // FIXME: These are taken from the heuristic-based cost visitor: we should
  // eventually abstract these to the CallAnalyzer to avoid duplication.
  unsigned SROACostSavingOpportunities = 0;
  int VectorBonus = 0;
  int SingleBBBonus = 0;
  int Threshold = 5;

  DenseMap<AllocaInst *, unsigned> SROACosts;

  void increment(InlineCostFeatureIndex Feature, int64_t Delta = 1) {
    Cost[static_cast<size_t>(Feature)] += Delta;
  }

  void set(InlineCostFeatureIndex Feature, int64_t Value) {
    Cost[static_cast<size_t>(Feature)] = Value;
  }

  void onDisableSROA(AllocaInst *Arg) override {
    auto CostIt = SROACosts.find(Arg);
    if (CostIt == SROACosts.end())
      return;

    increment(InlineCostFeatureIndex::sroa_losses, CostIt->second);
    SROACostSavingOpportunities -= CostIt->second;
    SROACosts.erase(CostIt);
  }

  void onDisableLoadElimination() override {
    set(InlineCostFeatureIndex::load_elimination, 1);
  }

  void onCallPenalty() override {
    increment(InlineCostFeatureIndex::call_penalty, CallPenalty);
  }

  void onCallArgumentSetup(const CallBase &Call) override {
    increment(InlineCostFeatureIndex::call_argument_setup,
              Call.arg_size() * InstrCost);
  }

  void onLoadRelativeIntrinsic() override {
    increment(InlineCostFeatureIndex::load_relative_intrinsic, 3 * InstrCost);
  }

  void onLoweredCall(Function *F, CallBase &Call,
                     bool IsIndirectCall) override {
    increment(InlineCostFeatureIndex::lowered_call_arg_setup,
              Call.arg_size() * InstrCost);

    if (IsIndirectCall) {
      InlineParams IndirectCallParams = {/* DefaultThreshold*/ 0,
                                         /*HintThreshold*/ {},
                                         /*ColdThreshold*/ {},
                                         /*OptSizeThreshold*/ {},
                                         /*OptMinSizeThreshold*/ {},
                                         /*HotCallSiteThreshold*/ {},
                                         /*LocallyHotCallSiteThreshold*/ {},
                                         /*ColdCallSiteThreshold*/ {},
                                         /*ComputeFullInlineCost*/ true,
                                         /*EnableDeferral*/ true};
      IndirectCallParams.DefaultThreshold =
          InlineConstants::IndirectCallThreshold;

      InlineCostCallAnalyzer CA(*F, Call, IndirectCallParams, TTI,
                                GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
                                false, true);
      if (CA.analyze().isSuccess()) {
        increment(InlineCostFeatureIndex::nested_inline_cost_estimate,
                  CA.getCost());
        increment(InlineCostFeatureIndex::nested_inlines, 1);
      }
    } else {
      onCallPenalty();
    }
  }

  void onFinalizeSwitch(unsigned JumpTableSize, unsigned NumCaseCluster,
                        bool DefaultDestUnreachable) override {
    if (JumpTableSize) {
      if (!DefaultDestUnreachable)
        increment(InlineCostFeatureIndex::switch_default_dest_penalty,
                  SwitchDefaultDestCostMultiplier * InstrCost);
      int64_t JTCost = static_cast<int64_t>(JumpTableSize) * InstrCost +
                       JTCostMultiplier * InstrCost;
      increment(InlineCostFeatureIndex::jump_table_penalty, JTCost);
      return;
    }

    if (NumCaseCluster <= 3) {
      increment(InlineCostFeatureIndex::case_cluster_penalty,
                (NumCaseCluster - DefaultDestUnreachable) *
                    CaseClusterCostMultiplier * InstrCost);
      return;
    }

    int64_t ExpectedNumberOfCompare =
        getExpectedNumberOfCompare(NumCaseCluster);

    int64_t SwitchCost =
        ExpectedNumberOfCompare * SwitchCostMultiplier * InstrCost;
    increment(InlineCostFeatureIndex::switch_penalty, SwitchCost);
  }

  void onMissedSimplification() override {
    increment(InlineCostFeatureIndex::unsimplified_common_instructions,
              InstrCost);
  }

  void onInitializeSROAArg(AllocaInst *Arg) override {
    auto SROAArgCost = TTI.getCallerAllocaCost(&CandidateCall, Arg);
    SROACosts[Arg] = SROAArgCost;
    SROACostSavingOpportunities += SROAArgCost;
  }

  void onAggregateSROAUse(AllocaInst *Arg) override {
    SROACosts.find(Arg)->second += InstrCost;
    SROACostSavingOpportunities += InstrCost;
  }

  void onBlockAnalyzed(const BasicBlock *BB) override {
    if (BB->getTerminator()->getNumSuccessors() > 1)
      set(InlineCostFeatureIndex::is_multiple_blocks, 1);
    Threshold -= SingleBBBonus;
  }

  InlineResult finalizeAnalysis() override {
    auto *Caller = CandidateCall.getFunction();
    if (Caller->hasMinSize()) {
      DominatorTree DT(F);
      LoopInfo LI(DT);
      for (Loop *L : LI) {
        // Ignore loops that will not be executed
        if (DeadBlocks.count(L->getHeader()))
          continue;
        increment(InlineCostFeatureIndex::num_loops,
                  InlineConstants::LoopPenalty);
      }
    }
    set(InlineCostFeatureIndex::dead_blocks, DeadBlocks.size());
    set(InlineCostFeatureIndex::simplified_instructions,
        NumInstructionsSimplified);
    set(InlineCostFeatureIndex::constant_args, NumConstantArgs);
    set(InlineCostFeatureIndex::constant_offset_ptr_args,
        NumConstantOffsetPtrArgs);
    set(InlineCostFeatureIndex::sroa_savings, SROACostSavingOpportunities);

    if (NumVectorInstructions <= NumInstructions / 10)
      Threshold -= VectorBonus;
    else if (NumVectorInstructions <= NumInstructions / 2)
      Threshold -= VectorBonus / 2;

    set(InlineCostFeatureIndex::threshold, Threshold);

    return InlineResult::success();
  }

  bool shouldStop() override { return false; }

  void onLoadEliminationOpportunity() override {
    increment(InlineCostFeatureIndex::load_elimination, 1);
  }

  InlineResult onAnalysisStart() override {
    increment(InlineCostFeatureIndex::callsite_cost,
              -1 * getCallsiteCost(TTI, this->CandidateCall, DL));

    set(InlineCostFeatureIndex::cold_cc_penalty,
        (F.getCallingConv() == CallingConv::Cold));

    set(InlineCostFeatureIndex::last_call_to_static_bonus,
        isSoleCallToLocalFunction(CandidateCall, F));

    // FIXME: we shouldn't repeat this logic in both the Features and Cost
    // analyzer - instead, we should abstract it to a common method in the
    // CallAnalyzer
    int SingleBBBonusPercent = 50;
    int VectorBonusPercent = TTI.getInlinerVectorBonusPercent();
    Threshold += TTI.adjustInliningThreshold(&CandidateCall);
    Threshold *= TTI.getInliningThresholdMultiplier();
    SingleBBBonus = Threshold * SingleBBBonusPercent / 100;
    VectorBonus = Threshold * VectorBonusPercent / 100;
    Threshold += (SingleBBBonus + VectorBonus);

    return InlineResult::success();
  }

public:
  InlineCostFeaturesAnalyzer(
      const TargetTransformInfo &TTI,
      function_ref<AssumptionCache &(Function &)> &GetAssumptionCache,
      function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
      function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
      ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE, Function &Callee,
      CallBase &Call)
      : CallAnalyzer(Callee, Call, TTI, GetAssumptionCache, GetBFI, GetTLI,
                     PSI) {}

  const InlineCostFeatures &features() const { return Cost; }
};

} // namespace

/// Test whether the given value is an Alloca-derived function argument.
bool CallAnalyzer::isAllocaDerivedArg(Value *V) {
  return SROAArgValues.count(V);
}

void CallAnalyzer::disableSROAForArg(AllocaInst *SROAArg) {
  onDisableSROA(SROAArg);
  EnabledSROAAllocas.erase(SROAArg);
  disableLoadElimination();
}

void InlineCostAnnotationWriter::emitInstructionAnnot(
    const Instruction *I, formatted_raw_ostream &OS) {
  // The cost of inlining of the given instruction is printed always.
  // The threshold delta is printed only when it is non-zero. It happens
  // when we decided to give a bonus at a particular instruction.
  std::optional<InstructionCostDetail> Record = ICCA->getCostDetails(I);
  if (!Record)
    OS << "; No analysis for the instruction";
  else {
    OS << "; cost before = " << Record->CostBefore
       << ", cost after = " << Record->CostAfter
       << ", threshold before = " << Record->ThresholdBefore
       << ", threshold after = " << Record->ThresholdAfter << ", ";
    OS << "cost delta = " << Record->getCostDelta();
    if (Record->hasThresholdChanged())
      OS << ", threshold delta = " << Record->getThresholdDelta();
  }
  auto *V = ICCA->getSimplifiedValueUnchecked(const_cast<Instruction *>(I));
  if (V) {
    OS << ", simplified to ";
    V->print(OS, true);
    if (auto *VI = dyn_cast<Instruction>(V)) {
      if (VI->getFunction() != I->getFunction())
        OS << " (caller instruction)";
    } else if (auto *VArg = dyn_cast<Argument>(V)) {
      if (VArg->getParent() != I->getFunction())
        OS << " (caller argument)";
    }
  }
  OS << "\n";
}

/// If 'V' maps to a SROA candidate, disable SROA for it.
void CallAnalyzer::disableSROA(Value *V) {
  if (auto *SROAArg = getSROAArgForValueOrNull(V)) {
    disableSROAForArg(SROAArg);
  }
}

void CallAnalyzer::disableLoadElimination() {
  if (EnableLoadElimination) {
    onDisableLoadElimination();
    EnableLoadElimination = false;
  }
}

/// Accumulate a constant GEP offset into an APInt if possible.
///
/// Returns false if unable to compute the offset for any reason. Respects any
/// simplified values known during the analysis of this callsite.
bool CallAnalyzer::accumulateGEPOffset(GEPOperator &GEP, APInt &Offset) {
  unsigned IntPtrWidth = DL.getIndexTypeSizeInBits(GEP.getType());
  assert(IntPtrWidth == Offset.getBitWidth());

  for (gep_type_iterator GTI = gep_type_begin(GEP), GTE = gep_type_end(GEP);
       GTI != GTE; ++GTI) {
    ConstantInt *OpC =
        getDirectOrSimplifiedValue<ConstantInt>(GTI.getOperand());
    if (!OpC)
      return false;
    if (OpC->isZero())
      continue;

    // Handle a struct index, which adds its field offset to the pointer.
    if (StructType *STy = GTI.getStructTypeOrNull()) {
      unsigned ElementIdx = OpC->getZExtValue();
      const StructLayout *SL = DL.getStructLayout(STy);
      Offset += APInt(IntPtrWidth, SL->getElementOffset(ElementIdx));
      continue;
    }

    APInt TypeSize(IntPtrWidth, GTI.getSequentialElementStride(DL));
    Offset += OpC->getValue().sextOrTrunc(IntPtrWidth) * TypeSize;
  }
  return true;
}

/// Use TTI to check whether a GEP is free.
///
/// Respects any simplified values known during the analysis of this callsite.
bool CallAnalyzer::isGEPFree(GetElementPtrInst &GEP) {
  SmallVector<Value *, 4> Operands;
  Operands.push_back(GEP.getOperand(0));
  for (const Use &Op : GEP.indices())
    if (Constant *SimpleOp = getSimplifiedValue<Constant>(Op))
      Operands.push_back(SimpleOp);
    else
      Operands.push_back(Op);
  return TTI.getInstructionCost(&GEP, Operands,
                                TargetTransformInfo::TCK_SizeAndLatency) ==
         TargetTransformInfo::TCC_Free;
}

bool CallAnalyzer::visitAlloca(AllocaInst &I) {
  disableSROA(I.getOperand(0));

  // Check whether inlining will turn a dynamic alloca into a static
  // alloca and handle that case.
  if (I.isArrayAllocation()) {
    Constant *Size = getSimplifiedValue<Constant>(I.getArraySize());
    if (auto *AllocSize = dyn_cast_or_null<ConstantInt>(Size)) {
      // Sometimes a dynamic alloca could be converted into a static alloca
      // after this constant prop, and become a huge static alloca on an
      // unconditional CFG path. Avoid inlining if this is going to happen above
      // a threshold.
      // FIXME: If the threshold is removed or lowered too much, we could end up
      // being too pessimistic and prevent inlining non-problematic code. This
      // could result in unintended perf regressions. A better overall strategy
      // is needed to track stack usage during inlining.
      Type *Ty = I.getAllocatedType();
      AllocatedSize = SaturatingMultiplyAdd(
          AllocSize->getLimitedValue(),
          DL.getTypeAllocSize(Ty).getKnownMinValue(), AllocatedSize);
      if (AllocatedSize > InlineConstants::MaxSimplifiedDynamicAllocaToInline)
        HasDynamicAlloca = true;
      return false;
    }
  }

  // Accumulate the allocated size.
  if (I.isStaticAlloca()) {
    Type *Ty = I.getAllocatedType();
    AllocatedSize = SaturatingAdd(DL.getTypeAllocSize(Ty).getKnownMinValue(),
                                  AllocatedSize);
  }

  // FIXME: This is overly conservative. Dynamic allocas are inefficient for
  // a variety of reasons, and so we would like to not inline them into
  // functions which don't currently have a dynamic alloca. This simply
  // disables inlining altogether in the presence of a dynamic alloca.
  if (!I.isStaticAlloca())
    HasDynamicAlloca = true;

  return false;
}

bool CallAnalyzer::visitPHI(PHINode &I) {
  // FIXME: We need to propagate SROA *disabling* through phi nodes, even
  // though we don't want to propagate it's bonuses. The idea is to disable
  // SROA if it *might* be used in an inappropriate manner.

  // Phi nodes are always zero-cost.
  // FIXME: Pointer sizes may differ between different address spaces, so do we
  // need to use correct address space in the call to getPointerSizeInBits here?
  // Or could we skip the getPointerSizeInBits call completely? As far as I can
  // see the ZeroOffset is used as a dummy value, so we can probably use any
  // bit width for the ZeroOffset?
  APInt ZeroOffset = APInt::getZero(DL.getPointerSizeInBits(0));
  bool CheckSROA = I.getType()->isPointerTy();

  // Track the constant or pointer with constant offset we've seen so far.
  Constant *FirstC = nullptr;
  std::pair<Value *, APInt> FirstBaseAndOffset = {nullptr, ZeroOffset};
  Value *FirstV = nullptr;

  for (unsigned i = 0, e = I.getNumIncomingValues(); i != e; ++i) {
    BasicBlock *Pred = I.getIncomingBlock(i);
    // If the incoming block is dead, skip the incoming block.
    if (DeadBlocks.count(Pred))
      continue;
    // If the parent block of phi is not the known successor of the incoming
    // block, skip the incoming block.
    BasicBlock *KnownSuccessor = KnownSuccessors[Pred];
    if (KnownSuccessor && KnownSuccessor != I.getParent())
      continue;

    Value *V = I.getIncomingValue(i);
    // If the incoming value is this phi itself, skip the incoming value.
    if (&I == V)
      continue;

    Constant *C = getDirectOrSimplifiedValue<Constant>(V);

    std::pair<Value *, APInt> BaseAndOffset = {nullptr, ZeroOffset};
    if (!C && CheckSROA)
      BaseAndOffset = ConstantOffsetPtrs.lookup(V);

    if (!C && !BaseAndOffset.first)
      // The incoming value is neither a constant nor a pointer with constant
      // offset, exit early.
      return true;

    if (FirstC) {
      if (FirstC == C)
        // If we've seen a constant incoming value before and it is the same
        // constant we see this time, continue checking the next incoming value.
        continue;
      // Otherwise early exit because we either see a different constant or saw
      // a constant before but we have a pointer with constant offset this time.
      return true;
    }

    if (FirstV) {
      // The same logic as above, but check pointer with constant offset here.
      if (FirstBaseAndOffset == BaseAndOffset)
        continue;
      return true;
    }

    if (C) {
      // This is the 1st time we've seen a constant, record it.
      FirstC = C;
      continue;
    }

    // The remaining case is that this is the 1st time we've seen a pointer with
    // constant offset, record it.
    FirstV = V;
    FirstBaseAndOffset = BaseAndOffset;
  }

  // Check if we can map phi to a constant.
  if (FirstC) {
    SimplifiedValues[&I] = FirstC;
    return true;
  }

  // Check if we can map phi to a pointer with constant offset.
  if (FirstBaseAndOffset.first) {
    ConstantOffsetPtrs[&I] = FirstBaseAndOffset;

    if (auto *SROAArg = getSROAArgForValueOrNull(FirstV))
      SROAArgValues[&I] = SROAArg;
  }

  return true;
}

/// Check we can fold GEPs of constant-offset call site argument pointers.
/// This requires target data and inbounds GEPs.
///
/// \return true if the specified GEP can be folded.
bool CallAnalyzer::canFoldInboundsGEP(GetElementPtrInst &I) {
  // Check if we have a base + offset for the pointer.
  std::pair<Value *, APInt> BaseAndOffset =
      ConstantOffsetPtrs.lookup(I.getPointerOperand());
  if (!BaseAndOffset.first)
    return false;

  // Check if the offset of this GEP is constant, and if so accumulate it
  // into Offset.
  if (!accumulateGEPOffset(cast<GEPOperator>(I), BaseAndOffset.second))
    return false;

  // Add the result as a new mapping to Base + Offset.
  ConstantOffsetPtrs[&I] = BaseAndOffset;

  return true;
}

bool CallAnalyzer::visitGetElementPtr(GetElementPtrInst &I) {
  auto *SROAArg = getSROAArgForValueOrNull(I.getPointerOperand());

  // Lambda to check whether a GEP's indices are all constant.
  auto IsGEPOffsetConstant = [&](GetElementPtrInst &GEP) {
    for (const Use &Op : GEP.indices())
      if (!getDirectOrSimplifiedValue<Constant>(Op))
        return false;
    return true;
  };

  if (!DisableGEPConstOperand)
    if (simplifyInstruction(I))
      return true;

  if ((I.isInBounds() && canFoldInboundsGEP(I)) || IsGEPOffsetConstant(I)) {
    if (SROAArg)
      SROAArgValues[&I] = SROAArg;

    // Constant GEPs are modeled as free.
    return true;
  }

  // Variable GEPs will require math and will disable SROA.
  if (SROAArg)
    disableSROAForArg(SROAArg);
  return isGEPFree(I);
}

// Simplify \p Cmp if RHS is const and we can ValueTrack LHS.
// This handles the case only when the Cmp instruction is guarding a recursive
// call that will cause the Cmp to fail/succeed for the recursive call.
bool CallAnalyzer::simplifyCmpInstForRecCall(CmpInst &Cmp) {
  // Bail out if LHS is not a function argument or RHS is NOT const:
  if (!isa<Argument>(Cmp.getOperand(0)) || !isa<Constant>(Cmp.getOperand(1)))
    return false;
  auto *CmpOp = Cmp.getOperand(0);
  // Make sure that the callsite is recursive:
  if (CandidateCall.getCaller() != &F)
    return false;
  // Only handle the case when the callsite has a single predecessor:
  auto *CallBB = CandidateCall.getParent();
  auto *Predecessor = CallBB->getSinglePredecessor();
  if (!Predecessor)
    return false;
  // Check if the callsite is guarded by the same Cmp instruction:
  auto *Br = dyn_cast<BranchInst>(Predecessor->getTerminator());
  if (!Br || Br->isUnconditional() || Br->getCondition() != &Cmp)
    return false;

  // Check if there is any arg of the recursive callsite is affecting the cmp
  // instr:
  bool ArgFound = false;
  Value *FuncArg = nullptr, *CallArg = nullptr;
  for (unsigned ArgNum = 0;
       ArgNum < F.arg_size() && ArgNum < CandidateCall.arg_size(); ArgNum++) {
    FuncArg = F.getArg(ArgNum);
    CallArg = CandidateCall.getArgOperand(ArgNum);
    if (FuncArg == CmpOp && CallArg != CmpOp) {
      ArgFound = true;
      break;
    }
  }
  if (!ArgFound)
    return false;

  // Now we have a recursive call that is guarded by a cmp instruction.
  // Check if this cmp can be simplified:
  SimplifyQuery SQ(DL, dyn_cast<Instruction>(CallArg));
  CondContext CC(&Cmp);
  CC.Invert = (CallBB != Br->getSuccessor(0));
  SQ.CC = &CC;
  CC.AffectedValues.insert(FuncArg);
  Value *SimplifiedInstruction = llvm::simplifyInstructionWithOperands(
      cast<CmpInst>(&Cmp), {CallArg, Cmp.getOperand(1)}, SQ);
  if (auto *ConstVal = dyn_cast_or_null<ConstantInt>(SimplifiedInstruction)) {
    // Make sure that the BB of the recursive call is NOT the true successor
    // of the icmp. In other words, make sure that the recursion depth is 1.
    if ((ConstVal->isOne() && CC.Invert) ||
        (ConstVal->isZero() && !CC.Invert)) {
      SimplifiedValues[&Cmp] = ConstVal;
      return true;
    }
  }
  return false;
}

/// Simplify \p I if its operands are constants and update SimplifiedValues.
bool CallAnalyzer::simplifyInstruction(Instruction &I) {
  SmallVector<Constant *> COps;
  for (Value *Op : I.operands()) {
    Constant *COp = getDirectOrSimplifiedValue<Constant>(Op);
    if (!COp)
      return false;
    COps.push_back(COp);
  }
  auto *C = ConstantFoldInstOperands(&I, COps, DL);
  if (!C)
    return false;
  SimplifiedValues[&I] = C;
  return true;
}

/// Try to simplify a call to llvm.is.constant.
///
/// Duplicate the argument checking from CallAnalyzer::simplifyCallSite since
/// we expect calls of this specific intrinsic to be infrequent.
///
/// FIXME: Given that we know CB's parent (F) caller
/// (CandidateCall->getParent()->getParent()), we might be able to determine
/// whether inlining F into F's caller would change how the call to
/// llvm.is.constant would evaluate.
bool CallAnalyzer::simplifyIntrinsicCallIsConstant(CallBase &CB) {
  Value *Arg = CB.getArgOperand(0);
  auto *C = getDirectOrSimplifiedValue<Constant>(Arg);

  Type *RT = CB.getFunctionType()->getReturnType();
  SimplifiedValues[&CB] = ConstantInt::get(RT, C ? 1 : 0);
  return true;
}

bool CallAnalyzer::simplifyIntrinsicCallObjectSize(CallBase &CB) {
  // As per the langref, "The fourth argument to llvm.objectsize determines if
  // the value should be evaluated at runtime."
  if (cast<ConstantInt>(CB.getArgOperand(3))->isOne())
    return false;

  Value *V = lowerObjectSizeCall(&cast<IntrinsicInst>(CB), DL, nullptr,
                                 /*MustSucceed=*/true);
  Constant *C = dyn_cast_or_null<Constant>(V);
  if (C)
    SimplifiedValues[&CB] = C;
  return C;
}

bool CallAnalyzer::visitBitCast(BitCastInst &I) {
  // Propagate constants through bitcasts.
  if (simplifyInstruction(I))
    return true;

  // Track base/offsets through casts
  std::pair<Value *, APInt> BaseAndOffset =
      ConstantOffsetPtrs.lookup(I.getOperand(0));
  // Casts don't change the offset, just wrap it up.
  if (BaseAndOffset.first)
    ConstantOffsetPtrs[&I] = BaseAndOffset;

  // Also look for SROA candidates here.
  if (auto *SROAArg = getSROAArgForValueOrNull(I.getOperand(0)))
    SROAArgValues[&I] = SROAArg;

  // Bitcasts are always zero cost.
  return true;
}

bool CallAnalyzer::visitPtrToInt(PtrToIntInst &I) {
  // Propagate constants through ptrtoint.
  if (simplifyInstruction(I))
    return true;

  // Track base/offset pairs when converted to a plain integer provided the
  // integer is large enough to represent the pointer.
  unsigned IntegerSize = I.getType()->getScalarSizeInBits();
  unsigned AS = I.getOperand(0)->getType()->getPointerAddressSpace();
  if (IntegerSize == DL.getPointerSizeInBits(AS)) {
    std::pair<Value *, APInt> BaseAndOffset =
        ConstantOffsetPtrs.lookup(I.getOperand(0));
    if (BaseAndOffset.first)
      ConstantOffsetPtrs[&I] = BaseAndOffset;
  }

  // This is really weird. Technically, ptrtoint will disable SROA. However,
  // unless that ptrtoint is *used* somewhere in the live basic blocks after
  // inlining, it will be nuked, and SROA should proceed. All of the uses which
  // would block SROA would also block SROA if applied directly to a pointer,
  // and so we can just add the integer in here. The only places where SROA is
  // preserved either cannot fire on an integer, or won't in-and-of themselves
  // disable SROA (ext) w/o some later use that we would see and disable.
  if (auto *SROAArg = getSROAArgForValueOrNull(I.getOperand(0)))
    SROAArgValues[&I] = SROAArg;

  return TTI.getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
         TargetTransformInfo::TCC_Free;
}

bool CallAnalyzer::visitIntToPtr(IntToPtrInst &I) {
  // Propagate constants through ptrtoint.
  if (simplifyInstruction(I))
    return true;

  // Track base/offset pairs when round-tripped through a pointer without
  // modifications provided the integer is not too large.
  Value *Op = I.getOperand(0);
  unsigned IntegerSize = Op->getType()->getScalarSizeInBits();
  if (IntegerSize <= DL.getPointerTypeSizeInBits(I.getType())) {
    std::pair<Value *, APInt> BaseAndOffset = ConstantOffsetPtrs.lookup(Op);
    if (BaseAndOffset.first)
      ConstantOffsetPtrs[&I] = BaseAndOffset;
  }

  // "Propagate" SROA here in the same manner as we do for ptrtoint above.
  if (auto *SROAArg = getSROAArgForValueOrNull(Op))
    SROAArgValues[&I] = SROAArg;

  return TTI.getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
         TargetTransformInfo::TCC_Free;
}

bool CallAnalyzer::visitCastInst(CastInst &I) {
  // Propagate constants through casts.
  if (simplifyInstruction(I))
    return true;

  // Disable SROA in the face of arbitrary casts we don't explicitly list
  // elsewhere.
  disableSROA(I.getOperand(0));

  // If this is a floating-point cast, and the target says this operation
  // is expensive, this may eventually become a library call. Treat the cost
  // as such.
  switch (I.getOpcode()) {
  case Instruction::FPTrunc:
  case Instruction::FPExt:
  case Instruction::UIToFP:
  case Instruction::SIToFP:
  case Instruction::FPToUI:
  case Instruction::FPToSI:
    if (TTI.getFPOpCost(I.getType()) == TargetTransformInfo::TCC_Expensive)
      onCallPenalty();
    break;
  default:
    break;
  }

  return TTI.getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
         TargetTransformInfo::TCC_Free;
}

bool CallAnalyzer::paramHasAttr(Argument *A, Attribute::AttrKind Attr) {
  return CandidateCall.paramHasAttr(A->getArgNo(), Attr);
}

bool CallAnalyzer::isKnownNonNullInCallee(Value *V) {
  // Does the *call site* have the NonNull attribute set on an argument?  We
  // use the attribute on the call site to memoize any analysis done in the
  // caller. This will also trip if the callee function has a non-null
  // parameter attribute, but that's a less interesting case because hopefully
  // the callee would already have been simplified based on that.
  if (Argument *A = dyn_cast<Argument>(V))
    if (paramHasAttr(A, Attribute::NonNull))
      return true;

  // Is this an alloca in the caller?  This is distinct from the attribute case
  // above because attributes aren't updated within the inliner itself and we
  // always want to catch the alloca derived case.
  if (isAllocaDerivedArg(V))
    // We can actually predict the result of comparisons between an
    // alloca-derived value and null. Note that this fires regardless of
    // SROA firing.
    return true;

  return false;
}

bool CallAnalyzer::allowSizeGrowth(CallBase &Call) {
  // If the normal destination of the invoke or the parent block of the call
  // site is unreachable-terminated, there is little point in inlining this
  // unless there is literally zero cost.
  // FIXME: Note that it is possible that an unreachable-terminated block has a
  // hot entry. For example, in below scenario inlining hot_call_X() may be
  // beneficial :
  // main() {
  //   hot_call_1();
  //   ...
  //   hot_call_N()
  //   exit(0);
  // }
  // For now, we are not handling this corner case here as it is rare in real
  // code. In future, we should elaborate this based on BPI and BFI in more
  // general threshold adjusting heuristics in updateThreshold().
  if (InvokeInst *II = dyn_cast<InvokeInst>(&Call)) {
    if (isa<UnreachableInst>(II->getNormalDest()->getTerminator()))
      return false;
  } else if (isa<UnreachableInst>(Call.getParent()->getTerminator()))
    return false;

  return true;
}

bool InlineCostCallAnalyzer::isColdCallSite(CallBase &Call,
                                            BlockFrequencyInfo *CallerBFI) {
  // If global profile summary is available, then callsite's coldness is
  // determined based on that.
  if (PSI && PSI->hasProfileSummary())
    return PSI->isColdCallSite(Call, CallerBFI);

  // Otherwise we need BFI to be available.
  if (!CallerBFI)
    return false;

  // Determine if the callsite is cold relative to caller's entry. We could
  // potentially cache the computation of scaled entry frequency, but the added
  // complexity is not worth it unless this scaling shows up high in the
  // profiles.
  const BranchProbability ColdProb(ColdCallSiteRelFreq, 100);
  auto CallSiteBB = Call.getParent();
  auto CallSiteFreq = CallerBFI->getBlockFreq(CallSiteBB);
  auto CallerEntryFreq =
      CallerBFI->getBlockFreq(&(Call.getCaller()->getEntryBlock()));
  return CallSiteFreq < CallerEntryFreq * ColdProb;
}

std::optional<int>
InlineCostCallAnalyzer::getHotCallSiteThreshold(CallBase &Call,
                                                BlockFrequencyInfo *CallerBFI) {

  // If global profile summary is available, then callsite's hotness is
  // determined based on that.
  if (PSI && PSI->hasProfileSummary() && PSI->isHotCallSite(Call, CallerBFI))
    return Params.HotCallSiteThreshold;

  // Otherwise we need BFI to be available and to have a locally hot callsite
  // threshold.
  if (!CallerBFI || !Params.LocallyHotCallSiteThreshold)
    return std::nullopt;

  // Determine if the callsite is hot relative to caller's entry. We could
  // potentially cache the computation of scaled entry frequency, but the added
  // complexity is not worth it unless this scaling shows up high in the
  // profiles.
  const BasicBlock *CallSiteBB = Call.getParent();
  BlockFrequency CallSiteFreq = CallerBFI->getBlockFreq(CallSiteBB);
  BlockFrequency CallerEntryFreq = CallerBFI->getEntryFreq();
  std::optional<BlockFrequency> Limit = CallerEntryFreq.mul(HotCallSiteRelFreq);
  if (Limit && CallSiteFreq >= *Limit)
    return Params.LocallyHotCallSiteThreshold;

  // Otherwise treat it normally.
  return std::nullopt;
}

void InlineCostCallAnalyzer::updateThreshold(CallBase &Call, Function &Callee) {
  // If no size growth is allowed for this inlining, set Threshold to 0.
  if (!allowSizeGrowth(Call)) {
    Threshold = 0;
    return;
  }

  Function *Caller = Call.getCaller();

  // return min(A, B) if B is valid.
  auto MinIfValid = [](int A, std::optional<int> B) {
    return B ? std::min(A, *B) : A;
  };

  // return max(A, B) if B is valid.
  auto MaxIfValid = [](int A, std::optional<int> B) {
    return B ? std::max(A, *B) : A;
  };

  // Various bonus percentages. These are multiplied by Threshold to get the
  // bonus values.
  // SingleBBBonus: This bonus is applied if the callee has a single reachable
  // basic block at the given callsite context. This is speculatively applied
  // and withdrawn if more than one basic block is seen.
  //
  // LstCallToStaticBonus: This large bonus is applied to ensure the inlining
  // of the last call to a static function as inlining such functions is
  // guaranteed to reduce code size.
  //
  // These bonus percentages may be set to 0 based on properties of the caller
  // and the callsite.
  int SingleBBBonusPercent = 50;
  int VectorBonusPercent = TTI.getInlinerVectorBonusPercent();
  int LastCallToStaticBonus = TTI.getInliningLastCallToStaticBonus();

  // Lambda to set all the above bonus and bonus percentages to 0.
  auto DisallowAllBonuses = [&]() {
    SingleBBBonusPercent = 0;
    VectorBonusPercent = 0;
    LastCallToStaticBonus = 0;
  };

  // Use the OptMinSizeThreshold or OptSizeThreshold knob if they are available
  // and reduce the threshold if the caller has the necessary attribute.
  if (Caller->hasMinSize()) {
    Threshold = MinIfValid(Threshold, Params.OptMinSizeThreshold);
    // For minsize, we want to disable the single BB bonus and the vector
    // bonuses, but not the last-call-to-static bonus. Inlining the last call to
    // a static function will, at the minimum, eliminate the parameter setup and
    // call/return instructions.
    SingleBBBonusPercent = 0;
    VectorBonusPercent = 0;
  } else if (Caller->hasOptSize())
    Threshold = MinIfValid(Threshold, Params.OptSizeThreshold);

  // Adjust the threshold based on inlinehint attribute and profile based
  // hotness information if the caller does not have MinSize attribute.
  if (!Caller->hasMinSize()) {
    if (Callee.hasFnAttribute(Attribute::InlineHint))
      Threshold = MaxIfValid(Threshold, Params.HintThreshold);

    // FIXME: After switching to the new passmanager, simplify the logic below
    // by checking only the callsite hotness/coldness as we will reliably
    // have local profile information.
    //
    // Callsite hotness and coldness can be determined if sample profile is
    // used (which adds hotness metadata to calls) or if caller's
    // BlockFrequencyInfo is available.
    BlockFrequencyInfo *CallerBFI = GetBFI ? &(GetBFI(*Caller)) : nullptr;
    auto HotCallSiteThreshold = getHotCallSiteThreshold(Call, CallerBFI);
    if (!Caller->hasOptSize() && HotCallSiteThreshold) {
      LLVM_DEBUG(dbgs() << "Hot callsite.\n");
      // FIXME: This should update the threshold only if it exceeds the
      // current threshold, but AutoFDO + ThinLTO currently relies on this
      // behavior to prevent inlining of hot callsites during ThinLTO
      // compile phase.
      Threshold = *HotCallSiteThreshold;
    } else if (isColdCallSite(Call, CallerBFI)) {
      LLVM_DEBUG(dbgs() << "Cold callsite.\n");
      // Do not apply bonuses for a cold callsite including the
      // LastCallToStatic bonus. While this bonus might result in code size
      // reduction, it can cause the size of a non-cold caller to increase
      // preventing it from being inlined.
      DisallowAllBonuses();
      Threshold = MinIfValid(Threshold, Params.ColdCallSiteThreshold);
    } else if (PSI) {
      // Use callee's global profile information only if we have no way of
      // determining this via callsite information.
      if (PSI->isFunctionEntryHot(&Callee)) {
        LLVM_DEBUG(dbgs() << "Hot callee.\n");
        // If callsite hotness can not be determined, we may still know
        // that the callee is hot and treat it as a weaker hint for threshold
        // increase.
        Threshold = MaxIfValid(Threshold, Params.HintThreshold);
      } else if (PSI->isFunctionEntryCold(&Callee)) {
        LLVM_DEBUG(dbgs() << "Cold callee.\n");
        // Do not apply bonuses for a cold callee including the
        // LastCallToStatic bonus. While this bonus might result in code size
        // reduction, it can cause the size of a non-cold caller to increase
        // preventing it from being inlined.
        DisallowAllBonuses();
        Threshold = MinIfValid(Threshold, Params.ColdThreshold);
      }
    }
  }

  Threshold += TTI.adjustInliningThreshold(&Call);

  // Finally, take the target-specific inlining threshold multiplier into
  // account.
  Threshold *= TTI.getInliningThresholdMultiplier();

  SingleBBBonus = Threshold * SingleBBBonusPercent / 100;
  VectorBonus = Threshold * VectorBonusPercent / 100;

  // If there is only one call of the function, and it has internal linkage,
  // the cost of inlining it drops dramatically. It may seem odd to update
  // Cost in updateThreshold, but the bonus depends on the logic in this method.
  if (isSoleCallToLocalFunction(Call, F)) {
    Cost -= LastCallToStaticBonus;
    StaticBonusApplied = LastCallToStaticBonus;
  }
}

bool CallAnalyzer::visitCmpInst(CmpInst &I) {
  Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
  // First try to handle simplified comparisons.
  if (simplifyInstruction(I))
    return true;

  // Try to handle comparison that can be simplified using ValueTracking.
  if (simplifyCmpInstForRecCall(I))
    return true;

  if (I.getOpcode() == Instruction::FCmp)
    return false;

  // Otherwise look for a comparison between constant offset pointers with
  // a common base.
  Value *LHSBase, *RHSBase;
  APInt LHSOffset, RHSOffset;
  std::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS);
  if (LHSBase) {
    std::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS);
    if (RHSBase && LHSBase == RHSBase) {
      // We have common bases, fold the icmp to a constant based on the
      // offsets.
      SimplifiedValues[&I] = ConstantInt::getBool(
          I.getType(),
          ICmpInst::compare(LHSOffset, RHSOffset, I.getPredicate()));
      ++NumConstantPtrCmps;
      return true;
    }
  }

  auto isImplicitNullCheckCmp = [](const CmpInst &I) {
    for (auto *User : I.users())
      if (auto *Instr = dyn_cast<Instruction>(User))
        if (!Instr->getMetadata(LLVMContext::MD_make_implicit))
          return false;
    return true;
  };

  // If the comparison is an equality comparison with null, we can simplify it
  // if we know the value (argument) can't be null
  if (I.isEquality() && isa<ConstantPointerNull>(I.getOperand(1))) {
    if (isKnownNonNullInCallee(I.getOperand(0))) {
      bool IsNotEqual = I.getPredicate() == CmpInst::ICMP_NE;
      SimplifiedValues[&I] = IsNotEqual ? ConstantInt::getTrue(I.getType())
                                        : ConstantInt::getFalse(I.getType());
      return true;
    }
    // Implicit null checks act as unconditional branches and their comparisons
    // should be treated as simplified and free of cost.
    if (isImplicitNullCheckCmp(I))
      return true;
  }
  return handleSROA(I.getOperand(0), isa<ConstantPointerNull>(I.getOperand(1)));
}

bool CallAnalyzer::visitSub(BinaryOperator &I) {
  // Try to handle a special case: we can fold computing the difference of two
  // constant-related pointers.
  Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
  Value *LHSBase, *RHSBase;
  APInt LHSOffset, RHSOffset;
  std::tie(LHSBase, LHSOffset) = ConstantOffsetPtrs.lookup(LHS);
  if (LHSBase) {
    std::tie(RHSBase, RHSOffset) = ConstantOffsetPtrs.lookup(RHS);
    if (RHSBase && LHSBase == RHSBase) {
      // We have common bases, fold the subtract to a constant based on the
      // offsets.
      Constant *CLHS = ConstantInt::get(LHS->getContext(), LHSOffset);
      Constant *CRHS = ConstantInt::get(RHS->getContext(), RHSOffset);
      if (Constant *C = ConstantExpr::getSub(CLHS, CRHS)) {
        SimplifiedValues[&I] = C;
        ++NumConstantPtrDiffs;
        return true;
      }
    }
  }

  // Otherwise, fall back to the generic logic for simplifying and handling
  // instructions.
  return Base::visitSub(I);
}

bool CallAnalyzer::visitBinaryOperator(BinaryOperator &I) {
  Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
  Constant *CLHS = getDirectOrSimplifiedValue<Constant>(LHS);
  Constant *CRHS = getDirectOrSimplifiedValue<Constant>(RHS);

  Value *SimpleV = nullptr;
  if (auto FI = dyn_cast<FPMathOperator>(&I))
    SimpleV = simplifyBinOp(I.getOpcode(), CLHS ? CLHS : LHS, CRHS ? CRHS : RHS,
                            FI->getFastMathFlags(), DL);
  else
    SimpleV =
        simplifyBinOp(I.getOpcode(), CLHS ? CLHS : LHS, CRHS ? CRHS : RHS, DL);

  if (Constant *C = dyn_cast_or_null<Constant>(SimpleV))
    SimplifiedValues[&I] = C;

  if (SimpleV)
    return true;

  // Disable any SROA on arguments to arbitrary, unsimplified binary operators.
  disableSROA(LHS);
  disableSROA(RHS);

  // If the instruction is floating point, and the target says this operation
  // is expensive, this may eventually become a library call. Treat the cost
  // as such. Unless it's fneg which can be implemented with an xor.
  using namespace llvm::PatternMatch;
  if (I.getType()->isFloatingPointTy() &&
      TTI.getFPOpCost(I.getType()) == TargetTransformInfo::TCC_Expensive &&
      !match(&I, m_FNeg(m_Value())))
    onCallPenalty();

  return false;
}

bool CallAnalyzer::visitFNeg(UnaryOperator &I) {
  Value *Op = I.getOperand(0);
  Constant *COp = getDirectOrSimplifiedValue<Constant>(Op);

  Value *SimpleV = simplifyFNegInst(
      COp ? COp : Op, cast<FPMathOperator>(I).getFastMathFlags(), DL);

  if (Constant *C = dyn_cast_or_null<Constant>(SimpleV))
    SimplifiedValues[&I] = C;

  if (SimpleV)
    return true;

  // Disable any SROA on arguments to arbitrary, unsimplified fneg.
  disableSROA(Op);

  return false;
}

bool CallAnalyzer::visitLoad(LoadInst &I) {
  if (handleSROA(I.getPointerOperand(), I.isSimple()))
    return true;

  // If the data is already loaded from this address and hasn't been clobbered
  // by any stores or calls, this load is likely to be redundant and can be
  // eliminated.
  if (EnableLoadElimination &&
      !LoadAddrSet.insert(I.getPointerOperand()).second && I.isUnordered()) {
    onLoadEliminationOpportunity();
    return true;
  }

  onMemAccess();
  return false;
}

bool CallAnalyzer::visitStore(StoreInst &I) {
  if (handleSROA(I.getPointerOperand(), I.isSimple()))
    return true;

  // The store can potentially clobber loads and prevent repeated loads from
  // being eliminated.
  // FIXME:
  // 1. We can probably keep an initial set of eliminatable loads substracted
  // from the cost even when we finally see a store. We just need to disable
  // *further* accumulation of elimination savings.
  // 2. We should probably at some point thread MemorySSA for the callee into
  // this and then use that to actually compute *really* precise savings.
  disableLoadElimination();

  onMemAccess();
  return false;
}

bool CallAnalyzer::visitExtractValue(ExtractValueInst &I) {
  Value *Op = I.getAggregateOperand();

  // Special handling, because we want to simplify extractvalue with a
  // potential insertvalue from the caller.
  if (Value *SimpleOp = getSimplifiedValueUnchecked(Op)) {
    SimplifyQuery SQ(DL);
    Value *SimpleV = simplifyExtractValueInst(SimpleOp, I.getIndices(), SQ);
    if (SimpleV) {
      SimplifiedValues[&I] = SimpleV;
      return true;
    }
  }

  // SROA can't look through these, but they may be free.
  return Base::visitExtractValue(I);
}

bool CallAnalyzer::visitInsertValue(InsertValueInst &I) {
  // Constant folding for insert value is trivial.
  if (simplifyInstruction(I))
    return true;

  // SROA can't look through these, but they may be free.
  return Base::visitInsertValue(I);
}

/// Try to simplify a call site.
///
/// Takes a concrete function and callsite and tries to actually simplify it by
/// analyzing the arguments and call itself with instsimplify. Returns true if
/// it has simplified the callsite to some other entity (a constant), making it
/// free.
bool CallAnalyzer::simplifyCallSite(Function *F, CallBase &Call) {
  // FIXME: Using the instsimplify logic directly for this is inefficient
  // because we have to continually rebuild the argument list even when no
  // simplifications can be performed. Until that is fixed with remapping
  // inside of instsimplify, directly constant fold calls here.
  if (!canConstantFoldCallTo(&Call, F))
    return false;

  // Try to re-map the arguments to constants.
  SmallVector<Constant *, 4> ConstantArgs;
  ConstantArgs.reserve(Call.arg_size());
  for (Value *I : Call.args()) {
    Constant *C = getDirectOrSimplifiedValue<Constant>(I);
    if (!C)
      return false; // This argument doesn't map to a constant.

    ConstantArgs.push_back(C);
  }
  if (Constant *C = ConstantFoldCall(&Call, F, ConstantArgs)) {
    SimplifiedValues[&Call] = C;
    return true;
  }

  return false;
}

bool CallAnalyzer::isLoweredToCall(Function *F, CallBase &Call) {
  const TargetLibraryInfo *TLI = GetTLI ? &GetTLI(*F) : nullptr;
  LibFunc LF;
  if (!TLI || !TLI->getLibFunc(*F, LF) || !TLI->has(LF))
    return TTI.isLoweredToCall(F);

  switch (LF) {
  case LibFunc_memcpy_chk:
  case LibFunc_memmove_chk:
  case LibFunc_mempcpy_chk:
  case LibFunc_memset_chk: {
    // Calls to  __memcpy_chk whose length is known to fit within the object
    // size will eventually be replaced by inline stores. Therefore, these
    // should not incur a call penalty. This is only really relevant on
    // platforms whose headers redirect memcpy to __memcpy_chk (e.g. Darwin), as
    // other platforms use memcpy intrinsics, which are already exempt from the
    // call penalty.
    auto *LenOp = getDirectOrSimplifiedValue<ConstantInt>(Call.getOperand(2));
    auto *ObjSizeOp =
        getDirectOrSimplifiedValue<ConstantInt>(Call.getOperand(3));
    if (LenOp && ObjSizeOp &&
        LenOp->getLimitedValue() <= ObjSizeOp->getLimitedValue()) {
      return false;
    }
    break;
  }
  default:
    break;
  }

  return TTI.isLoweredToCall(F);
}

bool CallAnalyzer::visitCallBase(CallBase &Call) {
  if (!onCallBaseVisitStart(Call))
    return true;

  if (Call.hasFnAttr(Attribute::ReturnsTwice) &&
      !F.hasFnAttribute(Attribute::ReturnsTwice)) {
    // This aborts the entire analysis.
    ExposesReturnsTwice = true;
    return false;
  }
  if (isa<CallInst>(Call) && cast<CallInst>(Call).cannotDuplicate())
    ContainsNoDuplicateCall = true;

  if (InlineAsm *InlineAsmOp = dyn_cast<InlineAsm>(Call.getCalledOperand()))
    onInlineAsm(*InlineAsmOp);

  Function *F = Call.getCalledFunction();
  bool IsIndirectCall = !F;
  if (IsIndirectCall) {
    // Check if this happens to be an indirect function call to a known function
    // in this inline context. If not, we've done all we can.
    Value *Callee = Call.getCalledOperand();
    F = getSimplifiedValue<Function>(Callee);
    if (!F || F->getFunctionType() != Call.getFunctionType()) {
      onCallArgumentSetup(Call);

      if (!Call.onlyReadsMemory())
        disableLoadElimination();
      return Base::visitCallBase(Call);
    }
  }

  assert(F && "Expected a call to a known function");

  // When we have a concrete function, first try to simplify it directly.
  if (simplifyCallSite(F, Call))
    return true;

  // Next check if it is an intrinsic we know about.
  // FIXME: Lift this into part of the InstVisitor.
  if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&Call)) {
    switch (II->getIntrinsicID()) {
    default:
      if (!Call.onlyReadsMemory() && !isAssumeLikeIntrinsic(II))
        disableLoadElimination();
      return Base::visitCallBase(Call);

    case Intrinsic::load_relative:
      onLoadRelativeIntrinsic();
      return false;

    case Intrinsic::memset:
    case Intrinsic::memcpy:
    case Intrinsic::memmove:
      disableLoadElimination();
      // SROA can usually chew through these intrinsics, but they aren't free.
      return false;
    case Intrinsic::icall_branch_funnel:
    case Intrinsic::localescape:
      HasUninlineableIntrinsic = true;
      return false;
    case Intrinsic::vastart:
      InitsVargArgs = true;
      return false;
    case Intrinsic::launder_invariant_group:
    case Intrinsic::strip_invariant_group:
      if (auto *SROAArg = getSROAArgForValueOrNull(II->getOperand(0)))
        SROAArgValues[II] = SROAArg;
      return true;
    case Intrinsic::is_constant:
      return simplifyIntrinsicCallIsConstant(Call);
    case Intrinsic::objectsize:
      return simplifyIntrinsicCallObjectSize(Call);
    }
  }

  if (F == Call.getFunction()) {
    // This flag will fully abort the analysis, so don't bother with anything
    // else.
    IsRecursiveCall = true;
    if (!AllowRecursiveCall)
      return false;
  }

  if (isLoweredToCall(F, Call)) {
    onLoweredCall(F, Call, IsIndirectCall);
  }

  if (!(Call.onlyReadsMemory() || (IsIndirectCall && F->onlyReadsMemory())))
    disableLoadElimination();
  return Base::visitCallBase(Call);
}

bool CallAnalyzer::visitReturnInst(ReturnInst &RI) {
  // At least one return instruction will be free after inlining.
  bool Free = !HasReturn;
  HasReturn = true;
  return Free;
}

bool CallAnalyzer::visitBranchInst(BranchInst &BI) {
  // We model unconditional branches as essentially free -- they really
  // shouldn't exist at all, but handling them makes the behavior of the
  // inliner more regular and predictable. Interestingly, conditional branches
  // which will fold away are also free.
  return BI.isUnconditional() ||
         getDirectOrSimplifiedValue<ConstantInt>(BI.getCondition()) ||
         BI.getMetadata(LLVMContext::MD_make_implicit);
}

bool CallAnalyzer::visitSelectInst(SelectInst &SI) {
  bool CheckSROA = SI.getType()->isPointerTy();
  Value *TrueVal = SI.getTrueValue();
  Value *FalseVal = SI.getFalseValue();

  Constant *TrueC = getDirectOrSimplifiedValue<Constant>(TrueVal);
  Constant *FalseC = getDirectOrSimplifiedValue<Constant>(FalseVal);
  Constant *CondC = getSimplifiedValue<Constant>(SI.getCondition());

  if (!CondC) {
    // Select C, X, X => X
    if (TrueC == FalseC && TrueC) {
      SimplifiedValues[&SI] = TrueC;
      return true;
    }

    if (!CheckSROA)
      return Base::visitSelectInst(SI);

    std::pair<Value *, APInt> TrueBaseAndOffset =
        ConstantOffsetPtrs.lookup(TrueVal);
    std::pair<Value *, APInt> FalseBaseAndOffset =
        ConstantOffsetPtrs.lookup(FalseVal);
    if (TrueBaseAndOffset == FalseBaseAndOffset && TrueBaseAndOffset.first) {
      ConstantOffsetPtrs[&SI] = TrueBaseAndOffset;

      if (auto *SROAArg = getSROAArgForValueOrNull(TrueVal))
        SROAArgValues[&SI] = SROAArg;
      return true;
    }

    return Base::visitSelectInst(SI);
  }

  // Select condition is a constant.
  Value *SelectedV = CondC->isAllOnesValue()  ? TrueVal
                     : (CondC->isNullValue()) ? FalseVal
                                              : nullptr;
  if (!SelectedV) {
    // Condition is a vector constant that is not all 1s or all 0s.  If all
    // operands are constants, ConstantFoldSelectInstruction() can handle the
    // cases such as select vectors.
    if (TrueC && FalseC) {
      if (auto *C = ConstantFoldSelectInstruction(CondC, TrueC, FalseC)) {
        SimplifiedValues[&SI] = C;
        return true;
      }
    }
    return Base::visitSelectInst(SI);
  }

  // Condition is either all 1s or all 0s. SI can be simplified.
  if (Constant *SelectedC = dyn_cast<Constant>(SelectedV)) {
    SimplifiedValues[&SI] = SelectedC;
    return true;
  }

  if (!CheckSROA)
    return true;

  std::pair<Value *, APInt> BaseAndOffset =
      ConstantOffsetPtrs.lookup(SelectedV);
  if (BaseAndOffset.first) {
    ConstantOffsetPtrs[&SI] = BaseAndOffset;

    if (auto *SROAArg = getSROAArgForValueOrNull(SelectedV))
      SROAArgValues[&SI] = SROAArg;
  }

  return true;
}

bool CallAnalyzer::visitSwitchInst(SwitchInst &SI) {
  // We model unconditional switches as free, see the comments on handling
  // branches.
  if (getDirectOrSimplifiedValue<ConstantInt>(SI.getCondition()))
    return true;

  // Assume the most general case where the switch is lowered into
  // either a jump table, bit test, or a balanced binary tree consisting of
  // case clusters without merging adjacent clusters with the same
  // destination. We do not consider the switches that are lowered with a mix
  // of jump table/bit test/binary search tree. The cost of the switch is
  // proportional to the size of the tree or the size of jump table range.
  //
  // NB: We convert large switches which are just used to initialize large phi
  // nodes to lookup tables instead in simplifycfg, so this shouldn't prevent
  // inlining those. It will prevent inlining in cases where the optimization
  // does not (yet) fire.

  unsigned JumpTableSize = 0;
  BlockFrequencyInfo *BFI = GetBFI ? &(GetBFI(F)) : nullptr;
  unsigned NumCaseCluster =
      TTI.getEstimatedNumberOfCaseClusters(SI, JumpTableSize, PSI, BFI);

  onFinalizeSwitch(JumpTableSize, NumCaseCluster, SI.defaultDestUnreachable());
  return false;
}

bool CallAnalyzer::visitIndirectBrInst(IndirectBrInst &IBI) {
  // We never want to inline functions that contain an indirectbr.  This is
  // incorrect because all the blockaddress's (in static global initializers
  // for example) would be referring to the original function, and this
  // indirect jump would jump from the inlined copy of the function into the
  // original function which is extremely undefined behavior.
  // FIXME: This logic isn't really right; we can safely inline functions with
  // indirectbr's as long as no other function or global references the
  // blockaddress of a block within the current function.
  HasIndirectBr = true;
  return false;
}

bool CallAnalyzer::visitResumeInst(ResumeInst &RI) {
  // FIXME: It's not clear that a single instruction is an accurate model for
  // the inline cost of a resume instruction.
  return false;
}

bool CallAnalyzer::visitCleanupReturnInst(CleanupReturnInst &CRI) {
  // FIXME: It's not clear that a single instruction is an accurate model for
  // the inline cost of a cleanupret instruction.
  return false;
}

bool CallAnalyzer::visitCatchReturnInst(CatchReturnInst &CRI) {
  // FIXME: It's not clear that a single instruction is an accurate model for
  // the inline cost of a catchret instruction.
  return false;
}

bool CallAnalyzer::visitUnreachableInst(UnreachableInst &I) {
  // FIXME: It might be reasonably to discount the cost of instructions leading
  // to unreachable as they have the lowest possible impact on both runtime and
  // code size.
  return true; // No actual code is needed for unreachable.
}

bool CallAnalyzer::visitInstruction(Instruction &I) {
  // Some instructions are free. All of the free intrinsics can also be
  // handled by SROA, etc.
  if (TTI.getInstructionCost(&I, TargetTransformInfo::TCK_SizeAndLatency) ==
      TargetTransformInfo::TCC_Free)
    return true;

  // We found something we don't understand or can't handle. Mark any SROA-able
  // values in the operand list as no longer viable.
  for (const Use &Op : I.operands())
    disableSROA(Op);

  return false;
}

/// Analyze a basic block for its contribution to the inline cost.
///
/// This method walks the analyzer over every instruction in the given basic
/// block and accounts for their cost during inlining at this callsite. It
/// aborts early if the threshold has been exceeded or an impossible to inline
/// construct has been detected. It returns false if inlining is no longer
/// viable, and true if inlining remains viable.
InlineResult
CallAnalyzer::analyzeBlock(BasicBlock *BB,
                           const SmallPtrSetImpl<const Value *> &EphValues) {
  for (Instruction &I : *BB) {
    // FIXME: Currently, the number of instructions in a function regardless of
    // our ability to simplify them during inline to constants or dead code,
    // are actually used by the vector bonus heuristic. As long as that's true,
    // we have to special case debug intrinsics here to prevent differences in
    // inlining due to debug symbols. Eventually, the number of unsimplified
    // instructions shouldn't factor into the cost computation, but until then,
    // hack around it here.
    // Similarly, skip pseudo-probes.
    if (I.isDebugOrPseudoInst())
      continue;

    // Skip ephemeral values.
    if (EphValues.count(&I))
      continue;

    ++NumInstructions;
    if (isa<ExtractElementInst>(I) || I.getType()->isVectorTy())
      ++NumVectorInstructions;

    // If the instruction simplified to a constant, there is no cost to this
    // instruction. Visit the instructions using our InstVisitor to account for
    // all of the per-instruction logic. The visit tree returns true if we
    // consumed the instruction in any way, and false if the instruction's base
    // cost should count against inlining.
    onInstructionAnalysisStart(&I);

    if (Base::visit(&I))
      ++NumInstructionsSimplified;
    else
      onMissedSimplification();

    onInstructionAnalysisFinish(&I);
    using namespace ore;
    // If the visit this instruction detected an uninlinable pattern, abort.
    InlineResult IR = InlineResult::success();
    if (IsRecursiveCall && !AllowRecursiveCall)
      IR = InlineResult::failure("recursive");
    else if (ExposesReturnsTwice)
      IR = InlineResult::failure("exposes returns twice");
    else if (HasDynamicAlloca)
      IR = InlineResult::failure("dynamic alloca");
    else if (HasIndirectBr)
      IR = InlineResult::failure("indirect branch");
    else if (HasUninlineableIntrinsic)
      IR = InlineResult::failure("uninlinable intrinsic");
    else if (InitsVargArgs)
      IR = InlineResult::failure("varargs");
    if (!IR.isSuccess()) {
      if (ORE)
        ORE->emit([&]() {
          return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
                                          &CandidateCall)
                 << NV("Callee", &F) << " has uninlinable pattern ("
                 << NV("InlineResult", IR.getFailureReason())
                 << ") and cost is not fully computed";
        });
      return IR;
    }

    // If the caller is a recursive function then we don't want to inline
    // functions which allocate a lot of stack space because it would increase
    // the caller stack usage dramatically.
    if (IsCallerRecursive && AllocatedSize > RecurStackSizeThreshold) {
      auto IR =
          InlineResult::failure("recursive and allocates too much stack space");
      if (ORE)
        ORE->emit([&]() {
          return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline",
                                          &CandidateCall)
                 << NV("Callee", &F) << " is "
                 << NV("InlineResult", IR.getFailureReason())
                 << ". Cost is not fully computed";
        });
      return IR;
    }

    if (shouldStop())
      return InlineResult::failure(
          "Call site analysis is not favorable to inlining.");
  }

  return InlineResult::success();
}

/// Compute the base pointer and cumulative constant offsets for V.
///
/// This strips all constant offsets off of V, leaving it the base pointer, and
/// accumulates the total constant offset applied in the returned constant. It
/// returns 0 if V is not a pointer, and returns the constant '0' if there are
/// no constant offsets applied.
ConstantInt *CallAnalyzer::stripAndComputeInBoundsConstantOffsets(Value *&V) {
  if (!V->getType()->isPointerTy())
    return nullptr;

  unsigned AS = V->getType()->getPointerAddressSpace();
  unsigned IntPtrWidth = DL.getIndexSizeInBits(AS);
  APInt Offset = APInt::getZero(IntPtrWidth);

  // Even though we don't look through PHI nodes, we could be called on an
  // instruction in an unreachable block, which may be on a cycle.
  SmallPtrSet<Value *, 4> Visited;
  Visited.insert(V);
  do {
    if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
      if (!GEP->isInBounds() || !accumulateGEPOffset(*GEP, Offset))
        return nullptr;
      V = GEP->getPointerOperand();
    } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
      if (GA->isInterposable())
        break;
      V = GA->getAliasee();
    } else {
      break;
    }
    assert(V->getType()->isPointerTy() && "Unexpected operand type!");
  } while (Visited.insert(V).second);

  Type *IdxPtrTy = DL.getIndexType(V->getType());
  return cast<ConstantInt>(ConstantInt::get(IdxPtrTy, Offset));
}

/// Find dead blocks due to deleted CFG edges during inlining.
///
/// If we know the successor of the current block, \p CurrBB, has to be \p
/// NextBB, the other successors of \p CurrBB are dead if these successors have
/// no live incoming CFG edges.  If one block is found to be dead, we can
/// continue growing the dead block list by checking the successors of the dead
/// blocks to see if all their incoming edges are dead or not.
void CallAnalyzer::findDeadBlocks(BasicBlock *CurrBB, BasicBlock *NextBB) {
  auto IsEdgeDead = [&](BasicBlock *Pred, BasicBlock *Succ) {
    // A CFG edge is dead if the predecessor is dead or the predecessor has a
    // known successor which is not the one under exam.
    if (DeadBlocks.count(Pred))
      return true;
    BasicBlock *KnownSucc = KnownSuccessors[Pred];
    return KnownSucc && KnownSucc != Succ;
  };

  auto IsNewlyDead = [&](BasicBlock *BB) {
    // If all the edges to a block are dead, the block is also dead.
    return (!DeadBlocks.count(BB) &&
            llvm::all_of(predecessors(BB),
                         [&](BasicBlock *P) { return IsEdgeDead(P, BB); }));
  };

  for (BasicBlock *Succ : successors(CurrBB)) {
    if (Succ == NextBB || !IsNewlyDead(Succ))
      continue;
    SmallVector<BasicBlock *, 4> NewDead;
    NewDead.push_back(Succ);
    while (!NewDead.empty()) {
      BasicBlock *Dead = NewDead.pop_back_val();
      if (DeadBlocks.insert(Dead).second)
        // Continue growing the dead block lists.
        for (BasicBlock *S : successors(Dead))
          if (IsNewlyDead(S))
            NewDead.push_back(S);
    }
  }
}

/// Analyze a call site for potential inlining.
///
/// Returns true if inlining this call is viable, and false if it is not
/// viable. It computes the cost and adjusts the threshold based on numerous
/// factors and heuristics. If this method returns false but the computed cost
/// is below the computed threshold, then inlining was forcibly disabled by
/// some artifact of the routine.
InlineResult CallAnalyzer::analyze() {
  ++NumCallsAnalyzed;

  auto Result = onAnalysisStart();
  if (!Result.isSuccess())
    return Result;

  if (F.empty())
    return InlineResult::success();

  Function *Caller = CandidateCall.getFunction();
  // Check if the caller function is recursive itself.
  for (User *U : Caller->users()) {
    CallBase *Call = dyn_cast<CallBase>(U);
    if (Call && Call->getFunction() == Caller) {
      IsCallerRecursive = true;
      break;
    }
  }

  // Populate our simplified values by mapping from function arguments to call
  // arguments with known important simplifications.
  auto CAI = CandidateCall.arg_begin();
  for (Argument &FAI : F.args()) {
    assert(CAI != CandidateCall.arg_end());
    SimplifiedValues[&FAI] = *CAI;
    if (isa<Constant>(*CAI))
      ++NumConstantArgs;

    Value *PtrArg = *CAI;
    if (ConstantInt *C = stripAndComputeInBoundsConstantOffsets(PtrArg)) {
      ConstantOffsetPtrs[&FAI] = std::make_pair(PtrArg, C->getValue());

      // We can SROA any pointer arguments derived from alloca instructions.
      if (auto *SROAArg = dyn_cast<AllocaInst>(PtrArg)) {
        SROAArgValues[&FAI] = SROAArg;
        onInitializeSROAArg(SROAArg);
        EnabledSROAAllocas.insert(SROAArg);
      }
    }
    ++CAI;
  }
  NumConstantOffsetPtrArgs = ConstantOffsetPtrs.size();
  NumAllocaArgs = SROAArgValues.size();

  // Collecting the ephemeral values of `F` can be expensive, so use the
  // ephemeral values cache if available.
  SmallPtrSet<const Value *, 32> EphValuesStorage;
  const SmallPtrSetImpl<const Value *> *EphValues = &EphValuesStorage;
  if (GetEphValuesCache)
    EphValues = &GetEphValuesCache(F).ephValues();
  else
    CodeMetrics::collectEphemeralValues(&F, &GetAssumptionCache(F),
                                        EphValuesStorage);

  // The worklist of live basic blocks in the callee *after* inlining. We avoid
  // adding basic blocks of the callee which can be proven to be dead for this
  // particular call site in order to get more accurate cost estimates. This
  // requires a somewhat heavyweight iteration pattern: we need to walk the
  // basic blocks in a breadth-first order as we insert live successors. To
  // accomplish this, prioritizing for small iterations because we exit after
  // crossing our threshold, we use a small-size optimized SetVector.
  typedef SmallSetVector<BasicBlock *, 16> BBSetVector;
  BBSetVector BBWorklist;
  BBWorklist.insert(&F.getEntryBlock());

  // Note that we *must not* cache the size, this loop grows the worklist.
  for (unsigned Idx = 0; Idx != BBWorklist.size(); ++Idx) {
    if (shouldStop())
      break;

    BasicBlock *BB = BBWorklist[Idx];
    if (BB->empty())
      continue;

    onBlockStart(BB);

    // Disallow inlining a blockaddress with uses other than strictly callbr.
    // A blockaddress only has defined behavior for an indirect branch in the
    // same function, and we do not currently support inlining indirect
    // branches.  But, the inliner may not see an indirect branch that ends up
    // being dead code at a particular call site. If the blockaddress escapes
    // the function, e.g., via a global variable, inlining may lead to an
    // invalid cross-function reference.
    // FIXME: pr/39560: continue relaxing this overt restriction.
    if (BB->hasAddressTaken())
      for (User *U : BlockAddress::get(&*BB)->users())
        if (!isa<CallBrInst>(*U))
          return InlineResult::failure("blockaddress used outside of callbr");

    // Analyze the cost of this block. If we blow through the threshold, this
    // returns false, and we can bail on out.
    InlineResult IR = analyzeBlock(BB, *EphValues);
    if (!IR.isSuccess())
      return IR;

    Instruction *TI = BB->getTerminator();

    // Add in the live successors by first checking whether we have terminator
    // that may be simplified based on the values simplified by this call.
    if (BranchInst *BI = dyn_cast<BranchInst>(TI)) {
      if (BI->isConditional()) {
        Value *Cond = BI->getCondition();
        if (ConstantInt *SimpleCond = getSimplifiedValue<ConstantInt>(Cond)) {
          BasicBlock *NextBB = BI->getSuccessor(SimpleCond->isZero() ? 1 : 0);
          BBWorklist.insert(NextBB);
          KnownSuccessors[BB] = NextBB;
          findDeadBlocks(BB, NextBB);
          continue;
        }
      }
    } else if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
      Value *Cond = SI->getCondition();
      if (ConstantInt *SimpleCond = getSimplifiedValue<ConstantInt>(Cond)) {
        BasicBlock *NextBB = SI->findCaseValue(SimpleCond)->getCaseSuccessor();
        BBWorklist.insert(NextBB);
        KnownSuccessors[BB] = NextBB;
        findDeadBlocks(BB, NextBB);
        continue;
      }
    }

    // If we're unable to select a particular successor, just count all of
    // them.
    BBWorklist.insert_range(successors(BB));

    onBlockAnalyzed(BB);
  }

  // If this is a noduplicate call, we can still inline as long as
  // inlining this would cause the removal of the caller (so the instruction
  // is not actually duplicated, just moved).
  if (!isSoleCallToLocalFunction(CandidateCall, F) && ContainsNoDuplicateCall)
    return InlineResult::failure("noduplicate");

  // If the callee's stack size exceeds the user-specified threshold,
  // do not let it be inlined.
  // The command line option overrides a limit set in the function attributes.
  size_t FinalStackSizeThreshold = StackSizeThreshold;
  if (!StackSizeThreshold.getNumOccurrences())
    if (std::optional<int> AttrMaxStackSize = getStringFnAttrAsInt(
            Caller, InlineConstants::MaxInlineStackSizeAttributeName))
      FinalStackSizeThreshold = *AttrMaxStackSize;
  if (AllocatedSize > FinalStackSizeThreshold)
    return InlineResult::failure("stacksize");

  return finalizeAnalysis();
}

void InlineCostCallAnalyzer::print(raw_ostream &OS) {
#define DEBUG_PRINT_STAT(x) OS << "      " #x ": " << x << "\n"
  if (PrintInstructionComments)
    F.print(OS, &Writer);
  DEBUG_PRINT_STAT(NumConstantArgs);
  DEBUG_PRINT_STAT(NumConstantOffsetPtrArgs);
  DEBUG_PRINT_STAT(NumAllocaArgs);
  DEBUG_PRINT_STAT(NumConstantPtrCmps);
  DEBUG_PRINT_STAT(NumConstantPtrDiffs);
  DEBUG_PRINT_STAT(NumInstructionsSimplified);
  DEBUG_PRINT_STAT(NumInstructions);
  DEBUG_PRINT_STAT(NumInlineAsmInstructions);
  DEBUG_PRINT_STAT(SROACostSavings);
  DEBUG_PRINT_STAT(SROACostSavingsLost);
  DEBUG_PRINT_STAT(LoadEliminationCost);
  DEBUG_PRINT_STAT(ContainsNoDuplicateCall);
  DEBUG_PRINT_STAT(Cost);
  DEBUG_PRINT_STAT(Threshold);
#undef DEBUG_PRINT_STAT
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Dump stats about this call's analysis.
LLVM_DUMP_METHOD void InlineCostCallAnalyzer::dump() { print(dbgs()); }
#endif

/// Test that there are no attribute conflicts between Caller and Callee
///        that prevent inlining.
static bool functionsHaveCompatibleAttributes(
    Function *Caller, Function *Callee, TargetTransformInfo &TTI,
    function_ref<const TargetLibraryInfo &(Function &)> &GetTLI) {
  // Note that CalleeTLI must be a copy not a reference. The legacy pass manager
  // caches the most recently created TLI in the TargetLibraryInfoWrapperPass
  // object, and always returns the same object (which is overwritten on each
  // GetTLI call). Therefore we copy the first result.
  auto CalleeTLI = GetTLI(*Callee);
  return (IgnoreTTIInlineCompatible ||
          TTI.areInlineCompatible(Caller, Callee)) &&
         GetTLI(*Caller).areInlineCompatible(CalleeTLI,
                                             InlineCallerSupersetNoBuiltin) &&
         AttributeFuncs::areInlineCompatible(*Caller, *Callee);
}

int llvm::getCallsiteCost(const TargetTransformInfo &TTI, const CallBase &Call,
                          const DataLayout &DL) {
  int64_t Cost = 0;
  for (unsigned I = 0, E = Call.arg_size(); I != E; ++I) {
    if (Call.isByValArgument(I)) {
      // We approximate the number of loads and stores needed by dividing the
      // size of the byval type by the target's pointer size.
      PointerType *PTy = cast<PointerType>(Call.getArgOperand(I)->getType());
      unsigned TypeSize = DL.getTypeSizeInBits(Call.getParamByValType(I));
      unsigned AS = PTy->getAddressSpace();
      unsigned PointerSize = DL.getPointerSizeInBits(AS);
      // Ceiling division.
      unsigned NumStores = (TypeSize + PointerSize - 1) / PointerSize;

      // If it generates more than 8 stores it is likely to be expanded as an
      // inline memcpy so we take that as an upper bound. Otherwise we assume
      // one load and one store per word copied.
      // FIXME: The maxStoresPerMemcpy setting from the target should be used
      // here instead of a magic number of 8, but it's not available via
      // DataLayout.
      NumStores = std::min(NumStores, 8U);

      Cost += 2 * NumStores * InstrCost;
    } else {
      // For non-byval arguments subtract off one instruction per call
      // argument.
      Cost += InstrCost;
    }
  }
  // The call instruction also disappears after inlining.
  Cost += InstrCost;
  Cost += TTI.getInlineCallPenalty(Call.getCaller(), Call, CallPenalty);

  return std::min<int64_t>(Cost, INT_MAX);
}

InlineCost llvm::getInlineCost(
    CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI,
    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
    function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
    ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
    function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache) {
  return getInlineCost(Call, Call.getCalledFunction(), Params, CalleeTTI,
                       GetAssumptionCache, GetTLI, GetBFI, PSI, ORE,
                       GetEphValuesCache);
}

std::optional<int> llvm::getInliningCostEstimate(
    CallBase &Call, TargetTransformInfo &CalleeTTI,
    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
    function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
    ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
  const InlineParams Params = {/* DefaultThreshold*/ 0,
                               /*HintThreshold*/ {},
                               /*ColdThreshold*/ {},
                               /*OptSizeThreshold*/ {},
                               /*OptMinSizeThreshold*/ {},
                               /*HotCallSiteThreshold*/ {},
                               /*LocallyHotCallSiteThreshold*/ {},
                               /*ColdCallSiteThreshold*/ {},
                               /*ComputeFullInlineCost*/ true,
                               /*EnableDeferral*/ true};

  InlineCostCallAnalyzer CA(*Call.getCalledFunction(), Call, Params, CalleeTTI,
                            GetAssumptionCache, GetBFI, GetTLI, PSI, ORE, true,
                            /*IgnoreThreshold*/ true);
  auto R = CA.analyze();
  if (!R.isSuccess())
    return std::nullopt;
  return CA.getCost();
}

std::optional<InlineCostFeatures> llvm::getInliningCostFeatures(
    CallBase &Call, TargetTransformInfo &CalleeTTI,
    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
    function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
    ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE) {
  InlineCostFeaturesAnalyzer CFA(CalleeTTI, GetAssumptionCache, GetBFI, GetTLI,
                                 PSI, ORE, *Call.getCalledFunction(), Call);
  auto R = CFA.analyze();
  if (!R.isSuccess())
    return std::nullopt;
  return CFA.features();
}

std::optional<InlineResult> llvm::getAttributeBasedInliningDecision(
    CallBase &Call, Function *Callee, TargetTransformInfo &CalleeTTI,
    function_ref<const TargetLibraryInfo &(Function &)> GetTLI) {

  // Cannot inline indirect calls.
  if (!Callee)
    return InlineResult::failure("indirect call");

  // When callee coroutine function is inlined into caller coroutine function
  // before coro-split pass,
  // coro-early pass can not handle this quiet well.
  // So we won't inline the coroutine function if it have not been unsplited
  if (Callee->isPresplitCoroutine())
    return InlineResult::failure("unsplited coroutine call");

  // Never inline calls with byval arguments that does not have the alloca
  // address space. Since byval arguments can be replaced with a copy to an
  // alloca, the inlined code would need to be adjusted to handle that the
  // argument is in the alloca address space (so it is a little bit complicated
  // to solve).
  unsigned AllocaAS = Callee->getDataLayout().getAllocaAddrSpace();
  for (unsigned I = 0, E = Call.arg_size(); I != E; ++I)
    if (Call.isByValArgument(I)) {
      PointerType *PTy = cast<PointerType>(Call.getArgOperand(I)->getType());
      if (PTy->getAddressSpace() != AllocaAS)
        return InlineResult::failure("byval arguments without alloca"
                                     " address space");
    }

  // Calls to functions with always-inline attributes should be inlined
  // whenever possible.
  if (Call.hasFnAttr(Attribute::AlwaysInline)) {
    if (Call.getAttributes().hasFnAttr(Attribute::NoInline))
      return InlineResult::failure("noinline call site attribute");

    auto IsViable = isInlineViable(*Callee);
    if (IsViable.isSuccess())
      return InlineResult::success();
    return InlineResult::failure(IsViable.getFailureReason());
  }

  // Never inline functions with conflicting attributes (unless callee has
  // always-inline attribute).
  Function *Caller = Call.getCaller();
  if (!functionsHaveCompatibleAttributes(Caller, Callee, CalleeTTI, GetTLI))
    return InlineResult::failure("conflicting attributes");

  // Don't inline this call if the caller has the optnone attribute.
  if (Caller->hasOptNone())
    return InlineResult::failure("optnone attribute");

  // Don't inline a function that treats null pointer as valid into a caller
  // that does not have this attribute.
  if (!Caller->nullPointerIsDefined() && Callee->nullPointerIsDefined())
    return InlineResult::failure("nullptr definitions incompatible");

  // Don't inline functions which can be interposed at link-time.
  if (Callee->isInterposable())
    return InlineResult::failure("interposable");

  // Don't inline functions marked noinline.
  if (Callee->hasFnAttribute(Attribute::NoInline))
    return InlineResult::failure("noinline function attribute");

  // Don't inline call sites marked noinline.
  if (Call.isNoInline())
    return InlineResult::failure("noinline call site attribute");

  // Don't inline functions that are loader replaceable.
  if (Callee->hasFnAttribute("loader-replaceable"))
    return InlineResult::failure("loader replaceable function attribute");

  return std::nullopt;
}

InlineCost llvm::getInlineCost(
    CallBase &Call, Function *Callee, const InlineParams &Params,
    TargetTransformInfo &CalleeTTI,
    function_ref<AssumptionCache &(Function &)> GetAssumptionCache,
    function_ref<const TargetLibraryInfo &(Function &)> GetTLI,
    function_ref<BlockFrequencyInfo &(Function &)> GetBFI,
    ProfileSummaryInfo *PSI, OptimizationRemarkEmitter *ORE,
    function_ref<EphemeralValuesCache &(Function &)> GetEphValuesCache) {

  auto UserDecision =
      llvm::getAttributeBasedInliningDecision(Call, Callee, CalleeTTI, GetTLI);

  if (UserDecision) {
    if (UserDecision->isSuccess())
      return llvm::InlineCost::getAlways("always inline attribute");
    return llvm::InlineCost::getNever(UserDecision->getFailureReason());
  }

  LLVM_DEBUG(llvm::dbgs() << "      Analyzing call of " << Callee->getName()
                          << "... (caller:" << Call.getCaller()->getName()
                          << ")\n");

  InlineCostCallAnalyzer CA(*Callee, Call, Params, CalleeTTI,
                            GetAssumptionCache, GetBFI, GetTLI, PSI, ORE,
                            /*BoostIndirect=*/true, /*IgnoreThreshold=*/false,
                            GetEphValuesCache);
  InlineResult ShouldInline = CA.analyze();

  LLVM_DEBUG(CA.dump());

  // Always make cost benefit based decision explicit.
  // We use always/never here since threshold is not meaningful,
  // as it's not what drives cost-benefit analysis.
  if (CA.wasDecidedByCostBenefit()) {
    if (ShouldInline.isSuccess())
      return InlineCost::getAlways("benefit over cost",
                                   CA.getCostBenefitPair());
    else
      return InlineCost::getNever("cost over benefit", CA.getCostBenefitPair());
  }

  if (CA.wasDecidedByCostThreshold())
    return InlineCost::get(CA.getCost(), CA.getThreshold(),
                           CA.getStaticBonusApplied());

  // No details on how the decision was made, simply return always or never.
  return ShouldInline.isSuccess()
             ? InlineCost::getAlways("empty function")
             : InlineCost::getNever(ShouldInline.getFailureReason());
}

InlineResult llvm::isInlineViable(Function &F) {
  bool ReturnsTwice = F.hasFnAttribute(Attribute::ReturnsTwice);
  for (BasicBlock &BB : F) {
    // Disallow inlining of functions which contain indirect branches.
    if (isa<IndirectBrInst>(BB.getTerminator()))
      return InlineResult::failure("contains indirect branches");

    // Disallow inlining of blockaddresses which are used by non-callbr
    // instructions.
    if (BB.hasAddressTaken())
      for (User *U : BlockAddress::get(&BB)->users())
        if (!isa<CallBrInst>(*U))
          return InlineResult::failure("blockaddress used outside of callbr");

    for (auto &II : BB) {
      CallBase *Call = dyn_cast<CallBase>(&II);
      if (!Call)
        continue;

      // Disallow recursive calls.
      Function *Callee = Call->getCalledFunction();
      if (&F == Callee)
        return InlineResult::failure("recursive call");

      // Disallow calls which expose returns-twice to a function not previously
      // attributed as such.
      if (!ReturnsTwice && isa<CallInst>(Call) &&
          cast<CallInst>(Call)->canReturnTwice())
        return InlineResult::failure("exposes returns-twice attribute");

      if (Callee)
        switch (Callee->getIntrinsicID()) {
        default:
          break;
        case llvm::Intrinsic::icall_branch_funnel:
          // Disallow inlining of @llvm.icall.branch.funnel because current
          // backend can't separate call targets from call arguments.
          return InlineResult::failure(
              "disallowed inlining of @llvm.icall.branch.funnel");
        case llvm::Intrinsic::localescape:
          // Disallow inlining functions that call @llvm.localescape. Doing this
          // correctly would require major changes to the inliner.
          return InlineResult::failure(
              "disallowed inlining of @llvm.localescape");
        case llvm::Intrinsic::vastart:
          // Disallow inlining of functions that initialize VarArgs with
          // va_start.
          return InlineResult::failure(
              "contains VarArgs initialized with va_start");
        }
    }
  }

  return InlineResult::success();
}

// APIs to create InlineParams based on command line flags and/or other
// parameters.

InlineParams llvm::getInlineParams(int Threshold) {
  InlineParams Params;

  // This field is the threshold to use for a callee by default. This is
  // derived from one or more of:
  //  * optimization or size-optimization levels,
  //  * a value passed to createFunctionInliningPass function, or
  //  * the -inline-threshold flag.
  //  If the -inline-threshold flag is explicitly specified, that is used
  //  irrespective of anything else.
  if (InlineThreshold.getNumOccurrences() > 0)
    Params.DefaultThreshold = InlineThreshold;
  else
    Params.DefaultThreshold = Threshold;

  // Set the HintThreshold knob from the -inlinehint-threshold.
  Params.HintThreshold = HintThreshold;

  // Set the HotCallSiteThreshold knob from the -hot-callsite-threshold.
  Params.HotCallSiteThreshold = HotCallSiteThreshold;

  // If the -locally-hot-callsite-threshold is explicitly specified, use it to
  // populate LocallyHotCallSiteThreshold. Later, we populate
  // Params.LocallyHotCallSiteThreshold from -locally-hot-callsite-threshold if
  // we know that optimization level is O3 (in the getInlineParams variant that
  // takes the opt and size levels).
  // FIXME: Remove this check (and make the assignment unconditional) after
  // addressing size regression issues at O2.
  if (LocallyHotCallSiteThreshold.getNumOccurrences() > 0)
    Params.LocallyHotCallSiteThreshold = LocallyHotCallSiteThreshold;

  // Set the ColdCallSiteThreshold knob from the
  // -inline-cold-callsite-threshold.
  Params.ColdCallSiteThreshold = ColdCallSiteThreshold;

  // Set the OptMinSizeThreshold and OptSizeThreshold params only if the
  // -inlinehint-threshold commandline option is not explicitly given. If that
  // option is present, then its value applies even for callees with size and
  // minsize attributes.
  // If the -inline-threshold is not specified, set the ColdThreshold from the
  // -inlinecold-threshold even if it is not explicitly passed. If
  // -inline-threshold is specified, then -inlinecold-threshold needs to be
  // explicitly specified to set the ColdThreshold knob
  if (InlineThreshold.getNumOccurrences() == 0) {
    Params.OptMinSizeThreshold = InlineConstants::OptMinSizeThreshold;
    Params.OptSizeThreshold = InlineConstants::OptSizeThreshold;
    Params.ColdThreshold = ColdThreshold;
  } else if (ColdThreshold.getNumOccurrences() > 0) {
    Params.ColdThreshold = ColdThreshold;
  }
  return Params;
}

InlineParams llvm::getInlineParams() {
  return getInlineParams(DefaultThreshold);
}

// Compute the default threshold for inlining based on the opt level and the
// size opt level.
static int computeThresholdFromOptLevels(unsigned OptLevel,
                                         unsigned SizeOptLevel) {
  if (OptLevel > 2)
    return InlineConstants::OptAggressiveThreshold;
  if (SizeOptLevel == 1) // -Os
    return InlineConstants::OptSizeThreshold;
  if (SizeOptLevel == 2) // -Oz
    return InlineConstants::OptMinSizeThreshold;
  return DefaultThreshold;
}

InlineParams llvm::getInlineParams(unsigned OptLevel, unsigned SizeOptLevel) {
  auto Params =
      getInlineParams(computeThresholdFromOptLevels(OptLevel, SizeOptLevel));
  // At O3, use the value of -locally-hot-callsite-threshold option to populate
  // Params.LocallyHotCallSiteThreshold. Below O3, this flag has effect only
  // when it is specified explicitly.
  if (OptLevel > 2)
    Params.LocallyHotCallSiteThreshold = LocallyHotCallSiteThreshold;
  return Params;
}

PreservedAnalyses
InlineCostAnnotationPrinterPass::run(Function &F,
                                     FunctionAnalysisManager &FAM) {
  PrintInstructionComments = true;
  std::function<AssumptionCache &(Function &)> GetAssumptionCache =
      [&](Function &F) -> AssumptionCache & {
    return FAM.getResult<AssumptionAnalysis>(F);
  };

  auto &MAMProxy = FAM.getResult<ModuleAnalysisManagerFunctionProxy>(F);
  ProfileSummaryInfo *PSI =
      MAMProxy.getCachedResult<ProfileSummaryAnalysis>(*F.getParent());
  const TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F);

  // FIXME: Redesign the usage of InlineParams to expand the scope of this pass.
  // In the current implementation, the type of InlineParams doesn't matter as
  // the pass serves only for verification of inliner's decisions.
  // We can add a flag which determines InlineParams for this run. Right now,
  // the default InlineParams are used.
  const InlineParams Params = llvm::getInlineParams();
  for (BasicBlock &BB : F) {
    for (Instruction &I : BB) {
      if (auto *CB = dyn_cast<CallBase>(&I)) {
        Function *CalledFunction = CB->getCalledFunction();
        if (!CalledFunction || CalledFunction->isDeclaration())
          continue;
        OptimizationRemarkEmitter ORE(CalledFunction);
        InlineCostCallAnalyzer ICCA(*CalledFunction, *CB, Params, TTI,
                                    GetAssumptionCache, nullptr, nullptr, PSI,
                                    &ORE);
        ICCA.analyze();
        OS << "      Analyzing call of " << CalledFunction->getName()
           << "... (caller:" << CB->getCaller()->getName() << ")\n";
        ICCA.print(OS);
        OS << "\n";
      }
    }
  }
  return PreservedAnalyses::all();
}
