//===- InlineFunction.cpp - Code to perform function inlining -------------===//
//
// 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 inlining of a function into a call site, resolving
// parameters and the return value as appropriate.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/AssumptionCache.h"
#include "llvm/Analysis/BlockFrequencyInfo.h"
#include "llvm/Analysis/CallGraph.h"
#include "llvm/Analysis/CaptureTracking.h"
#include "llvm/Analysis/CtxProfAnalysis.h"
#include "llvm/Analysis/IndirectCallVisitor.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/MemoryProfileInfo.h"
#include "llvm/Analysis/ObjCARCAnalysisUtils.h"
#include "llvm/Analysis/ObjCARCUtil.h"
#include "llvm/Analysis/ProfileSummaryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <deque>
#include <iterator>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#define DEBUG_TYPE "inline-function"

using namespace llvm;
using namespace llvm::memprof;

static cl::opt<bool>
EnableNoAliasConversion("enable-noalias-to-md-conversion", cl::init(true),
  cl::Hidden,
  cl::desc("Convert noalias attributes to metadata during inlining."));

static cl::opt<bool>
    UseNoAliasIntrinsic("use-noalias-intrinsic-during-inlining", cl::Hidden,
                        cl::init(true),
                        cl::desc("Use the llvm.experimental.noalias.scope.decl "
                                 "intrinsic during inlining."));

// Disabled by default, because the added alignment assumptions may increase
// compile-time and block optimizations. This option is not suitable for use
// with frontends that emit comprehensive parameter alignment annotations.
static cl::opt<bool>
PreserveAlignmentAssumptions("preserve-alignment-assumptions-during-inlining",
  cl::init(false), cl::Hidden,
  cl::desc("Convert align attributes to assumptions during inlining."));

static cl::opt<unsigned> InlinerAttributeWindow(
    "max-inst-checked-for-throw-during-inlining", cl::Hidden,
    cl::desc("the maximum number of instructions analyzed for may throw during "
             "attribute inference in inlined body"),
    cl::init(4));

namespace {

  /// A class for recording information about inlining a landing pad.
  class LandingPadInliningInfo {
    /// Destination of the invoke's unwind.
    BasicBlock *OuterResumeDest;

    /// Destination for the callee's resume.
    BasicBlock *InnerResumeDest = nullptr;

    /// LandingPadInst associated with the invoke.
    LandingPadInst *CallerLPad = nullptr;

    /// PHI for EH values from landingpad insts.
    PHINode *InnerEHValuesPHI = nullptr;

    SmallVector<Value*, 8> UnwindDestPHIValues;

  public:
    LandingPadInliningInfo(InvokeInst *II)
        : OuterResumeDest(II->getUnwindDest()) {
      // If there are PHI nodes in the unwind destination block, we need to keep
      // track of which values came into them from the invoke before removing
      // the edge from this block.
      BasicBlock *InvokeBB = II->getParent();
      BasicBlock::iterator I = OuterResumeDest->begin();
      for (; isa<PHINode>(I); ++I) {
        // Save the value to use for this edge.
        PHINode *PHI = cast<PHINode>(I);
        UnwindDestPHIValues.push_back(PHI->getIncomingValueForBlock(InvokeBB));
      }

      CallerLPad = cast<LandingPadInst>(I);
    }

    /// The outer unwind destination is the target of
    /// unwind edges introduced for calls within the inlined function.
    BasicBlock *getOuterResumeDest() const {
      return OuterResumeDest;
    }

    BasicBlock *getInnerResumeDest();

    LandingPadInst *getLandingPadInst() const { return CallerLPad; }

    /// Forward the 'resume' instruction to the caller's landing pad block.
    /// When the landing pad block has only one predecessor, this is
    /// a simple branch. When there is more than one predecessor, we need to
    /// split the landing pad block after the landingpad instruction and jump
    /// to there.
    void forwardResume(ResumeInst *RI,
                       SmallPtrSetImpl<LandingPadInst*> &InlinedLPads);

    /// Add incoming-PHI values to the unwind destination block for the given
    /// basic block, using the values for the original invoke's source block.
    void addIncomingPHIValuesFor(BasicBlock *BB) const {
      addIncomingPHIValuesForInto(BB, OuterResumeDest);
    }

    void addIncomingPHIValuesForInto(BasicBlock *src, BasicBlock *dest) const {
      BasicBlock::iterator I = dest->begin();
      for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
        PHINode *phi = cast<PHINode>(I);
        phi->addIncoming(UnwindDestPHIValues[i], src);
      }
    }
  };
} // end anonymous namespace

static IntrinsicInst *getConvergenceEntry(BasicBlock &BB) {
  BasicBlock::iterator It = BB.getFirstNonPHIIt();
  while (It != BB.end()) {
    if (auto *IntrinsicCall = dyn_cast<ConvergenceControlInst>(It)) {
      if (IntrinsicCall->isEntry()) {
        return IntrinsicCall;
      }
    }
    It = std::next(It);
  }
  return nullptr;
}

/// Get or create a target for the branch from ResumeInsts.
BasicBlock *LandingPadInliningInfo::getInnerResumeDest() {
  if (InnerResumeDest) return InnerResumeDest;

  // Split the landing pad.
  BasicBlock::iterator SplitPoint = ++CallerLPad->getIterator();
  InnerResumeDest =
    OuterResumeDest->splitBasicBlock(SplitPoint,
                                     OuterResumeDest->getName() + ".body");

  // The number of incoming edges we expect to the inner landing pad.
  const unsigned PHICapacity = 2;

  // Create corresponding new PHIs for all the PHIs in the outer landing pad.
  BasicBlock::iterator InsertPoint = InnerResumeDest->begin();
  BasicBlock::iterator I = OuterResumeDest->begin();
  for (unsigned i = 0, e = UnwindDestPHIValues.size(); i != e; ++i, ++I) {
    PHINode *OuterPHI = cast<PHINode>(I);
    PHINode *InnerPHI = PHINode::Create(OuterPHI->getType(), PHICapacity,
                                        OuterPHI->getName() + ".lpad-body");
    InnerPHI->insertBefore(InsertPoint);
    OuterPHI->replaceAllUsesWith(InnerPHI);
    InnerPHI->addIncoming(OuterPHI, OuterResumeDest);
  }

  // Create a PHI for the exception values.
  InnerEHValuesPHI =
      PHINode::Create(CallerLPad->getType(), PHICapacity, "eh.lpad-body");
  InnerEHValuesPHI->insertBefore(InsertPoint);
  CallerLPad->replaceAllUsesWith(InnerEHValuesPHI);
  InnerEHValuesPHI->addIncoming(CallerLPad, OuterResumeDest);

  // All done.
  return InnerResumeDest;
}

/// Forward the 'resume' instruction to the caller's landing pad block.
/// When the landing pad block has only one predecessor, this is a simple
/// branch. When there is more than one predecessor, we need to split the
/// landing pad block after the landingpad instruction and jump to there.
void LandingPadInliningInfo::forwardResume(
    ResumeInst *RI, SmallPtrSetImpl<LandingPadInst *> &InlinedLPads) {
  BasicBlock *Dest = getInnerResumeDest();
  BasicBlock *Src = RI->getParent();

  auto *BI = UncondBrInst::Create(Dest, Src);
  BI->setDebugLoc(RI->getDebugLoc());

  // Update the PHIs in the destination. They were inserted in an order which
  // makes this work.
  addIncomingPHIValuesForInto(Src, Dest);

  InnerEHValuesPHI->addIncoming(RI->getOperand(0), Src);
  RI->eraseFromParent();
}

/// Helper for getUnwindDestToken/getUnwindDestTokenHelper.
static Value *getParentPad(Value *EHPad) {
  if (auto *FPI = dyn_cast<FuncletPadInst>(EHPad))
    return FPI->getParentPad();
  return cast<CatchSwitchInst>(EHPad)->getParentPad();
}

using UnwindDestMemoTy = DenseMap<Instruction *, Value *>;

/// Helper for getUnwindDestToken that does the descendant-ward part of
/// the search.
static Value *getUnwindDestTokenHelper(Instruction *EHPad,
                                       UnwindDestMemoTy &MemoMap) {
  SmallVector<Instruction *, 8> Worklist(1, EHPad);

  while (!Worklist.empty()) {
    Instruction *CurrentPad = Worklist.pop_back_val();
    // We only put pads on the worklist that aren't in the MemoMap.  When
    // we find an unwind dest for a pad we may update its ancestors, but
    // the queue only ever contains uncles/great-uncles/etc. of CurrentPad,
    // so they should never get updated while queued on the worklist.
    assert(!MemoMap.count(CurrentPad));
    Value *UnwindDestToken = nullptr;
    if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(CurrentPad)) {
      if (CatchSwitch->hasUnwindDest()) {
        UnwindDestToken = &*CatchSwitch->getUnwindDest()->getFirstNonPHIIt();
      } else {
        // Catchswitch doesn't have a 'nounwind' variant, and one might be
        // annotated as "unwinds to caller" when really it's nounwind (see
        // e.g. SimplifyCFGOpt::SimplifyUnreachable), so we can't infer the
        // parent's unwind dest from this.  We can check its catchpads'
        // descendants, since they might include a cleanuppad with an
        // "unwinds to caller" cleanupret, which can be trusted.
        for (auto HI = CatchSwitch->handler_begin(),
                  HE = CatchSwitch->handler_end();
             HI != HE && !UnwindDestToken; ++HI) {
          BasicBlock *HandlerBlock = *HI;
          auto *CatchPad =
              cast<CatchPadInst>(&*HandlerBlock->getFirstNonPHIIt());
          for (User *Child : CatchPad->users()) {
            // Intentionally ignore invokes here -- since the catchswitch is
            // marked "unwind to caller", it would be a verifier error if it
            // contained an invoke which unwinds out of it, so any invoke we'd
            // encounter must unwind to some child of the catch.
            if (!isa<CleanupPadInst>(Child) && !isa<CatchSwitchInst>(Child))
              continue;

            Instruction *ChildPad = cast<Instruction>(Child);
            auto Memo = MemoMap.find(ChildPad);
            if (Memo == MemoMap.end()) {
              // Haven't figured out this child pad yet; queue it.
              Worklist.push_back(ChildPad);
              continue;
            }
            // We've already checked this child, but might have found that
            // it offers no proof either way.
            Value *ChildUnwindDestToken = Memo->second;
            if (!ChildUnwindDestToken)
              continue;
            // We already know the child's unwind dest, which can either
            // be ConstantTokenNone to indicate unwind to caller, or can
            // be another child of the catchpad.  Only the former indicates
            // the unwind dest of the catchswitch.
            if (isa<ConstantTokenNone>(ChildUnwindDestToken)) {
              UnwindDestToken = ChildUnwindDestToken;
              break;
            }
            assert(getParentPad(ChildUnwindDestToken) == CatchPad);
          }
        }
      }
    } else {
      auto *CleanupPad = cast<CleanupPadInst>(CurrentPad);
      for (User *U : CleanupPad->users()) {
        if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(U)) {
          if (BasicBlock *RetUnwindDest = CleanupRet->getUnwindDest())
            UnwindDestToken = &*RetUnwindDest->getFirstNonPHIIt();
          else
            UnwindDestToken = ConstantTokenNone::get(CleanupPad->getContext());
          break;
        }
        Value *ChildUnwindDestToken;
        if (auto *Invoke = dyn_cast<InvokeInst>(U)) {
          ChildUnwindDestToken = &*Invoke->getUnwindDest()->getFirstNonPHIIt();
        } else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
          Instruction *ChildPad = cast<Instruction>(U);
          auto Memo = MemoMap.find(ChildPad);
          if (Memo == MemoMap.end()) {
            // Haven't resolved this child yet; queue it and keep searching.
            Worklist.push_back(ChildPad);
            continue;
          }
          // We've checked this child, but still need to ignore it if it
          // had no proof either way.
          ChildUnwindDestToken = Memo->second;
          if (!ChildUnwindDestToken)
            continue;
        } else {
          // Not a relevant user of the cleanuppad
          continue;
        }
        // In a well-formed program, the child/invoke must either unwind to
        // an(other) child of the cleanup, or exit the cleanup.  In the
        // first case, continue searching.
        if (isa<Instruction>(ChildUnwindDestToken) &&
            getParentPad(ChildUnwindDestToken) == CleanupPad)
          continue;
        UnwindDestToken = ChildUnwindDestToken;
        break;
      }
    }
    // If we haven't found an unwind dest for CurrentPad, we may have queued its
    // children, so move on to the next in the worklist.
    if (!UnwindDestToken)
      continue;

    // Now we know that CurrentPad unwinds to UnwindDestToken.  It also exits
    // any ancestors of CurrentPad up to but not including UnwindDestToken's
    // parent pad.  Record this in the memo map, and check to see if the
    // original EHPad being queried is one of the ones exited.
    Value *UnwindParent;
    if (auto *UnwindPad = dyn_cast<Instruction>(UnwindDestToken))
      UnwindParent = getParentPad(UnwindPad);
    else
      UnwindParent = nullptr;
    bool ExitedOriginalPad = false;
    for (Instruction *ExitedPad = CurrentPad;
         ExitedPad && ExitedPad != UnwindParent;
         ExitedPad = dyn_cast<Instruction>(getParentPad(ExitedPad))) {
      // Skip over catchpads since they just follow their catchswitches.
      if (isa<CatchPadInst>(ExitedPad))
        continue;
      MemoMap[ExitedPad] = UnwindDestToken;
      ExitedOriginalPad |= (ExitedPad == EHPad);
    }

    if (ExitedOriginalPad)
      return UnwindDestToken;

    // Continue the search.
  }

  // No definitive information is contained within this funclet.
  return nullptr;
}

/// Given an EH pad, find where it unwinds.  If it unwinds to an EH pad,
/// return that pad instruction.  If it unwinds to caller, return
/// ConstantTokenNone.  If it does not have a definitive unwind destination,
/// return nullptr.
///
/// This routine gets invoked for calls in funclets in inlinees when inlining
/// an invoke.  Since many funclets don't have calls inside them, it's queried
/// on-demand rather than building a map of pads to unwind dests up front.
/// Determining a funclet's unwind dest may require recursively searching its
/// descendants, and also ancestors and cousins if the descendants don't provide
/// an answer.  Since most funclets will have their unwind dest immediately
/// available as the unwind dest of a catchswitch or cleanupret, this routine
/// searches top-down from the given pad and then up. To avoid worst-case
/// quadratic run-time given that approach, it uses a memo map to avoid
/// re-processing funclet trees.  The callers that rewrite the IR as they go
/// take advantage of this, for correctness, by checking/forcing rewritten
/// pads' entries to match the original callee view.
static Value *getUnwindDestToken(Instruction *EHPad,
                                 UnwindDestMemoTy &MemoMap) {
  // Catchpads unwind to the same place as their catchswitch;
  // redirct any queries on catchpads so the code below can
  // deal with just catchswitches and cleanuppads.
  if (auto *CPI = dyn_cast<CatchPadInst>(EHPad))
    EHPad = CPI->getCatchSwitch();

  // Check if we've already determined the unwind dest for this pad.
  auto Memo = MemoMap.find(EHPad);
  if (Memo != MemoMap.end())
    return Memo->second;

  // Search EHPad and, if necessary, its descendants.
  Value *UnwindDestToken = getUnwindDestTokenHelper(EHPad, MemoMap);
  assert((UnwindDestToken == nullptr) != (MemoMap.count(EHPad) != 0));
  if (UnwindDestToken)
    return UnwindDestToken;

  // No information is available for this EHPad from itself or any of its
  // descendants.  An unwind all the way out to a pad in the caller would
  // need also to agree with the unwind dest of the parent funclet, so
  // search up the chain to try to find a funclet with information.  Put
  // null entries in the memo map to avoid re-processing as we go up.
  MemoMap[EHPad] = nullptr;
#ifndef NDEBUG
  SmallPtrSet<Instruction *, 4> TempMemos;
  TempMemos.insert(EHPad);
#endif
  Instruction *LastUselessPad = EHPad;
  Value *AncestorToken;
  for (AncestorToken = getParentPad(EHPad);
       auto *AncestorPad = dyn_cast<Instruction>(AncestorToken);
       AncestorToken = getParentPad(AncestorToken)) {
    // Skip over catchpads since they just follow their catchswitches.
    if (isa<CatchPadInst>(AncestorPad))
      continue;
    // If the MemoMap had an entry mapping AncestorPad to nullptr, since we
    // haven't yet called getUnwindDestTokenHelper for AncestorPad in this
    // call to getUnwindDestToken, that would mean that AncestorPad had no
    // information in itself, its descendants, or its ancestors.  If that
    // were the case, then we should also have recorded the lack of information
    // for the descendant that we're coming from.  So assert that we don't
    // find a null entry in the MemoMap for AncestorPad.
    assert(!MemoMap.count(AncestorPad) || MemoMap[AncestorPad]);
    auto AncestorMemo = MemoMap.find(AncestorPad);
    if (AncestorMemo == MemoMap.end()) {
      UnwindDestToken = getUnwindDestTokenHelper(AncestorPad, MemoMap);
    } else {
      UnwindDestToken = AncestorMemo->second;
    }
    if (UnwindDestToken)
      break;
    LastUselessPad = AncestorPad;
    MemoMap[LastUselessPad] = nullptr;
#ifndef NDEBUG
    TempMemos.insert(LastUselessPad);
#endif
  }

  // We know that getUnwindDestTokenHelper was called on LastUselessPad and
  // returned nullptr (and likewise for EHPad and any of its ancestors up to
  // LastUselessPad), so LastUselessPad has no information from below.  Since
  // getUnwindDestTokenHelper must investigate all downward paths through
  // no-information nodes to prove that a node has no information like this,
  // and since any time it finds information it records it in the MemoMap for
  // not just the immediately-containing funclet but also any ancestors also
  // exited, it must be the case that, walking downward from LastUselessPad,
  // visiting just those nodes which have not been mapped to an unwind dest
  // by getUnwindDestTokenHelper (the nullptr TempMemos notwithstanding, since
  // they are just used to keep getUnwindDestTokenHelper from repeating work),
  // any node visited must have been exhaustively searched with no information
  // for it found.
  SmallVector<Instruction *, 8> Worklist(1, LastUselessPad);
  while (!Worklist.empty()) {
    Instruction *UselessPad = Worklist.pop_back_val();
    auto Memo = MemoMap.find(UselessPad);
    if (Memo != MemoMap.end() && Memo->second) {
      // Here the name 'UselessPad' is a bit of a misnomer, because we've found
      // that it is a funclet that does have information about unwinding to
      // a particular destination; its parent was a useless pad.
      // Since its parent has no information, the unwind edge must not escape
      // the parent, and must target a sibling of this pad.  This local unwind
      // gives us no information about EHPad.  Leave it and the subtree rooted
      // at it alone.
      assert(getParentPad(Memo->second) == getParentPad(UselessPad));
      continue;
    }
    // We know we don't have information for UselesPad.  If it has an entry in
    // the MemoMap (mapping it to nullptr), it must be one of the TempMemos
    // added on this invocation of getUnwindDestToken; if a previous invocation
    // recorded nullptr, it would have had to prove that the ancestors of
    // UselessPad, which include LastUselessPad, had no information, and that
    // in turn would have required proving that the descendants of
    // LastUselesPad, which include EHPad, have no information about
    // LastUselessPad, which would imply that EHPad was mapped to nullptr in
    // the MemoMap on that invocation, which isn't the case if we got here.
    assert(!MemoMap.count(UselessPad) || TempMemos.count(UselessPad));
    // Assert as we enumerate users that 'UselessPad' doesn't have any unwind
    // information that we'd be contradicting by making a map entry for it
    // (which is something that getUnwindDestTokenHelper must have proved for
    // us to get here).  Just assert on is direct users here; the checks in
    // this downward walk at its descendants will verify that they don't have
    // any unwind edges that exit 'UselessPad' either (i.e. they either have no
    // unwind edges or unwind to a sibling).
    MemoMap[UselessPad] = UnwindDestToken;
    if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(UselessPad)) {
      assert(CatchSwitch->getUnwindDest() == nullptr && "Expected useless pad");
      for (BasicBlock *HandlerBlock : CatchSwitch->handlers()) {
        auto *CatchPad = &*HandlerBlock->getFirstNonPHIIt();
        for (User *U : CatchPad->users()) {
          assert((!isa<InvokeInst>(U) ||
                  (getParentPad(&*cast<InvokeInst>(U)
                                      ->getUnwindDest()
                                      ->getFirstNonPHIIt()) == CatchPad)) &&
                 "Expected useless pad");
          if (isa<CatchSwitchInst>(U) || isa<CleanupPadInst>(U))
            Worklist.push_back(cast<Instruction>(U));
        }
      }
    } else {
      assert(isa<CleanupPadInst>(UselessPad));
      for (User *U : UselessPad->users()) {
        assert(!isa<CleanupReturnInst>(U) && "Expected useless pad");
        assert(
            (!isa<InvokeInst>(U) ||
             (getParentPad(
                  &*cast<InvokeInst>(U)->getUnwindDest()->getFirstNonPHIIt()) ==
              UselessPad)) &&
            "Expected useless pad");
        if (isa<CatchSwitchInst>(U) || isa<CleanupPadInst>(U))
          Worklist.push_back(cast<Instruction>(U));
      }
    }
  }

  return UnwindDestToken;
}

/// When we inline a basic block into an invoke,
/// we have to turn all of the calls that can throw into invokes.
/// This function analyze BB to see if there are any calls, and if so,
/// it rewrites them to be invokes that jump to InvokeDest and fills in the PHI
/// nodes in that block with the values specified in InvokeDestPHIValues.
static BasicBlock *HandleCallsInBlockInlinedThroughInvoke(
    BasicBlock *BB, BasicBlock *UnwindEdge,
    SmallSetVector<const Value *, 4> &OriginallyIndirectCalls,
    UnwindDestMemoTy *FuncletUnwindMap = nullptr) {
  for (Instruction &I : llvm::make_early_inc_range(*BB)) {
    // We only need to check for function calls: inlined invoke
    // instructions require no special handling.
    CallInst *CI = dyn_cast<CallInst>(&I);

    if (!CI || CI->doesNotThrow())
      continue;

    // We do not need to (and in fact, cannot) convert possibly throwing calls
    // to @llvm.experimental_deoptimize (resp. @llvm.experimental.guard) into
    // invokes.  The caller's "segment" of the deoptimization continuation
    // attached to the newly inlined @llvm.experimental_deoptimize
    // (resp. @llvm.experimental.guard) call should contain the exception
    // handling logic, if any.
    if (auto *F = CI->getCalledFunction())
      if (F->getIntrinsicID() == Intrinsic::experimental_deoptimize ||
          F->getIntrinsicID() == Intrinsic::experimental_guard)
        continue;

    if (auto FuncletBundle = CI->getOperandBundle(LLVMContext::OB_funclet)) {
      // This call is nested inside a funclet.  If that funclet has an unwind
      // destination within the inlinee, then unwinding out of this call would
      // be UB.  Rewriting this call to an invoke which targets the inlined
      // invoke's unwind dest would give the call's parent funclet multiple
      // unwind destinations, which is something that subsequent EH table
      // generation can't handle and that the veirifer rejects.  So when we
      // see such a call, leave it as a call.
      auto *FuncletPad = cast<Instruction>(FuncletBundle->Inputs[0]);
      Value *UnwindDestToken =
          getUnwindDestToken(FuncletPad, *FuncletUnwindMap);
      if (UnwindDestToken && !isa<ConstantTokenNone>(UnwindDestToken))
        continue;
#ifndef NDEBUG
      Instruction *MemoKey;
      if (auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPad))
        MemoKey = CatchPad->getCatchSwitch();
      else
        MemoKey = FuncletPad;
      assert(FuncletUnwindMap->count(MemoKey) &&
             (*FuncletUnwindMap)[MemoKey] == UnwindDestToken &&
             "must get memoized to avoid confusing later searches");
#endif // NDEBUG
    }

    bool WasIndirect = OriginallyIndirectCalls.remove(CI);
    changeToInvokeAndSplitBasicBlock(CI, UnwindEdge);
    if (WasIndirect)
      OriginallyIndirectCalls.insert(BB->getTerminator());
    return BB;
  }
  return nullptr;
}

/// If we inlined an invoke site, we need to convert calls
/// in the body of the inlined function into invokes.
///
/// II is the invoke instruction being inlined.  FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedLandingPad(InvokeInst *II, BasicBlock *FirstNewBlock,
                                    ClonedCodeInfo &InlinedCodeInfo) {
  BasicBlock *InvokeDest = II->getUnwindDest();

  Function *Caller = FirstNewBlock->getParent();

  // The inlined code is currently at the end of the function, scan from the
  // start of the inlined code to its end, checking for stuff we need to
  // rewrite.
  LandingPadInliningInfo Invoke(II);

  // Get all of the inlined landing pad instructions.
  SmallPtrSet<LandingPadInst*, 16> InlinedLPads;
  for (Function::iterator I = FirstNewBlock->getIterator(), E = Caller->end();
       I != E; ++I)
    if (InvokeInst *II = dyn_cast<InvokeInst>(I->getTerminator()))
      InlinedLPads.insert(II->getLandingPadInst());

  // Append the clauses from the outer landing pad instruction into the inlined
  // landing pad instructions.
  LandingPadInst *OuterLPad = Invoke.getLandingPadInst();
  for (LandingPadInst *InlinedLPad : InlinedLPads) {
    unsigned OuterNum = OuterLPad->getNumClauses();
    InlinedLPad->reserveClauses(OuterNum);
    for (unsigned OuterIdx = 0; OuterIdx != OuterNum; ++OuterIdx)
      InlinedLPad->addClause(OuterLPad->getClause(OuterIdx));
    if (OuterLPad->isCleanup())
      InlinedLPad->setCleanup(true);
  }

  for (Function::iterator BB = FirstNewBlock->getIterator(), E = Caller->end();
       BB != E; ++BB) {
    if (InlinedCodeInfo.ContainsCalls)
      if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
              &*BB, Invoke.getOuterResumeDest(),
              InlinedCodeInfo.OriginallyIndirectCalls))
        // Update any PHI nodes in the exceptional block to indicate that there
        // is now a new entry in them.
        Invoke.addIncomingPHIValuesFor(NewBB);

    // Forward any resumes that are remaining here.
    if (ResumeInst *RI = dyn_cast<ResumeInst>(BB->getTerminator()))
      Invoke.forwardResume(RI, InlinedLPads);
  }

  // Now that everything is happy, we have one final detail.  The PHI nodes in
  // the exception destination block still have entries due to the original
  // invoke instruction. Eliminate these entries (which might even delete the
  // PHI node) now.
  InvokeDest->removePredecessor(II->getParent());
}

/// If we inlined an invoke site, we need to convert calls
/// in the body of the inlined function into invokes.
///
/// II is the invoke instruction being inlined.  FirstNewBlock is the first
/// block of the inlined code (the last block is the end of the function),
/// and InlineCodeInfo is information about the code that got inlined.
static void HandleInlinedEHPad(InvokeInst *II, BasicBlock *FirstNewBlock,
                               ClonedCodeInfo &InlinedCodeInfo) {
  BasicBlock *UnwindDest = II->getUnwindDest();
  Function *Caller = FirstNewBlock->getParent();

  assert(UnwindDest->getFirstNonPHIIt()->isEHPad() && "unexpected BasicBlock!");

  // If there are PHI nodes in the unwind destination block, we need to keep
  // track of which values came into them from the invoke before removing the
  // edge from this block.
  SmallVector<Value *, 8> UnwindDestPHIValues;
  BasicBlock *InvokeBB = II->getParent();
  for (PHINode &PHI : UnwindDest->phis()) {
    // Save the value to use for this edge.
    UnwindDestPHIValues.push_back(PHI.getIncomingValueForBlock(InvokeBB));
  }

  // Add incoming-PHI values to the unwind destination block for the given basic
  // block, using the values for the original invoke's source block.
  auto UpdatePHINodes = [&](BasicBlock *Src) {
    BasicBlock::iterator I = UnwindDest->begin();
    for (Value *V : UnwindDestPHIValues) {
      PHINode *PHI = cast<PHINode>(I);
      PHI->addIncoming(V, Src);
      ++I;
    }
  };

  // This connects all the instructions which 'unwind to caller' to the invoke
  // destination.
  UnwindDestMemoTy FuncletUnwindMap;
  for (Function::iterator BB = FirstNewBlock->getIterator(), E = Caller->end();
       BB != E; ++BB) {
    if (auto *CRI = dyn_cast<CleanupReturnInst>(BB->getTerminator())) {
      if (CRI->unwindsToCaller()) {
        auto *CleanupPad = CRI->getCleanupPad();
        CleanupReturnInst::Create(CleanupPad, UnwindDest, CRI->getIterator());
        CRI->eraseFromParent();
        UpdatePHINodes(&*BB);
        // Finding a cleanupret with an unwind destination would confuse
        // subsequent calls to getUnwindDestToken, so map the cleanuppad
        // to short-circuit any such calls and recognize this as an "unwind
        // to caller" cleanup.
        assert(!FuncletUnwindMap.count(CleanupPad) ||
               isa<ConstantTokenNone>(FuncletUnwindMap[CleanupPad]));
        FuncletUnwindMap[CleanupPad] =
            ConstantTokenNone::get(Caller->getContext());
      }
    }

    BasicBlock::iterator I = BB->getFirstNonPHIIt();
    if (!I->isEHPad())
      continue;

    Instruction *Replacement = nullptr;
    if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
      if (CatchSwitch->unwindsToCaller()) {
        Value *UnwindDestToken;
        if (auto *ParentPad =
                dyn_cast<Instruction>(CatchSwitch->getParentPad())) {
          // This catchswitch is nested inside another funclet.  If that
          // funclet has an unwind destination within the inlinee, then
          // unwinding out of this catchswitch would be UB.  Rewriting this
          // catchswitch to unwind to the inlined invoke's unwind dest would
          // give the parent funclet multiple unwind destinations, which is
          // something that subsequent EH table generation can't handle and
          // that the veirifer rejects.  So when we see such a call, leave it
          // as "unwind to caller".
          UnwindDestToken = getUnwindDestToken(ParentPad, FuncletUnwindMap);
          if (UnwindDestToken && !isa<ConstantTokenNone>(UnwindDestToken))
            continue;
        } else {
          // This catchswitch has no parent to inherit constraints from, and
          // none of its descendants can have an unwind edge that exits it and
          // targets another funclet in the inlinee.  It may or may not have a
          // descendant that definitively has an unwind to caller.  In either
          // case, we'll have to assume that any unwinds out of it may need to
          // be routed to the caller, so treat it as though it has a definitive
          // unwind to caller.
          UnwindDestToken = ConstantTokenNone::get(Caller->getContext());
        }
        auto *NewCatchSwitch = CatchSwitchInst::Create(
            CatchSwitch->getParentPad(), UnwindDest,
            CatchSwitch->getNumHandlers(), CatchSwitch->getName(),
            CatchSwitch->getIterator());
        for (BasicBlock *PadBB : CatchSwitch->handlers())
          NewCatchSwitch->addHandler(PadBB);
        // Propagate info for the old catchswitch over to the new one in
        // the unwind map.  This also serves to short-circuit any subsequent
        // checks for the unwind dest of this catchswitch, which would get
        // confused if they found the outer handler in the callee.
        FuncletUnwindMap[NewCatchSwitch] = UnwindDestToken;
        Replacement = NewCatchSwitch;
      }
    } else if (!isa<FuncletPadInst>(I)) {
      llvm_unreachable("unexpected EHPad!");
    }

    if (Replacement) {
      Replacement->takeName(&*I);
      I->replaceAllUsesWith(Replacement);
      I->eraseFromParent();
      UpdatePHINodes(&*BB);
    }
  }

  if (InlinedCodeInfo.ContainsCalls)
    for (Function::iterator BB = FirstNewBlock->getIterator(),
                            E = Caller->end();
         BB != E; ++BB)
      if (BasicBlock *NewBB = HandleCallsInBlockInlinedThroughInvoke(
              &*BB, UnwindDest, InlinedCodeInfo.OriginallyIndirectCalls,
              &FuncletUnwindMap))
        // Update any PHI nodes in the exceptional block to indicate that there
        // is now a new entry in them.
        UpdatePHINodes(NewBB);

  // Now that everything is happy, we have one final detail.  The PHI nodes in
  // the exception destination block still have entries due to the original
  // invoke instruction. Eliminate these entries (which might even delete the
  // PHI node) now.
  UnwindDest->removePredecessor(InvokeBB);
}

static bool haveCommonPrefix(MDNode *MIBStackContext,
                             MDNode *CallsiteStackContext) {
  assert(MIBStackContext->getNumOperands() > 0 &&
         CallsiteStackContext->getNumOperands() > 0);
  // Because of the context trimming performed during matching, the callsite
  // context could have more stack ids than the MIB. We match up to the end of
  // the shortest stack context.
  for (auto MIBStackIter = MIBStackContext->op_begin(),
            CallsiteStackIter = CallsiteStackContext->op_begin();
       MIBStackIter != MIBStackContext->op_end() &&
       CallsiteStackIter != CallsiteStackContext->op_end();
       MIBStackIter++, CallsiteStackIter++) {
    auto *Val1 = mdconst::dyn_extract<ConstantInt>(*MIBStackIter);
    auto *Val2 = mdconst::dyn_extract<ConstantInt>(*CallsiteStackIter);
    assert(Val1 && Val2);
    if (Val1->getZExtValue() != Val2->getZExtValue())
      return false;
  }
  return true;
}

static void removeMemProfMetadata(CallBase *Call) {
  Call->setMetadata(LLVMContext::MD_memprof, nullptr);
}

static void removeCallsiteMetadata(CallBase *Call) {
  Call->setMetadata(LLVMContext::MD_callsite, nullptr);
}

static void updateMemprofMetadata(CallBase *CI,
                                  const std::vector<Metadata *> &MIBList,
                                  OptimizationRemarkEmitter *ORE) {
  assert(!MIBList.empty());
  // Remove existing memprof, which will either be replaced or may not be needed
  // if we are able to use a single allocation type function attribute.
  removeMemProfMetadata(CI);
  CallStackTrie CallStack(ORE);
  for (Metadata *MIB : MIBList)
    CallStack.addCallStack(cast<MDNode>(MIB));
  bool MemprofMDAttached = CallStack.buildAndAttachMIBMetadata(CI);
  assert(MemprofMDAttached == CI->hasMetadata(LLVMContext::MD_memprof));
  if (!MemprofMDAttached)
    // If we used a function attribute remove the callsite metadata as well.
    removeCallsiteMetadata(CI);
}

// Update the metadata on the inlined copy ClonedCall of a call OrigCall in the
// inlined callee body, based on the callsite metadata InlinedCallsiteMD from
// the call that was inlined.
static void propagateMemProfHelper(const CallBase *OrigCall,
                                   CallBase *ClonedCall,
                                   MDNode *InlinedCallsiteMD,
                                   OptimizationRemarkEmitter *ORE) {
  MDNode *OrigCallsiteMD = ClonedCall->getMetadata(LLVMContext::MD_callsite);
  MDNode *ClonedCallsiteMD = nullptr;
  // Check if the call originally had callsite metadata, and update it for the
  // new call in the inlined body.
  if (OrigCallsiteMD) {
    // The cloned call's context is now the concatenation of the original call's
    // callsite metadata and the callsite metadata on the call where it was
    // inlined.
    ClonedCallsiteMD = MDNode::concatenate(OrigCallsiteMD, InlinedCallsiteMD);
    ClonedCall->setMetadata(LLVMContext::MD_callsite, ClonedCallsiteMD);
  }

  // Update any memprof metadata on the cloned call.
  MDNode *OrigMemProfMD = ClonedCall->getMetadata(LLVMContext::MD_memprof);
  if (!OrigMemProfMD)
    return;
  // We currently expect that allocations with memprof metadata also have
  // callsite metadata for the allocation's part of the context.
  assert(OrigCallsiteMD);

  // New call's MIB list.
  std::vector<Metadata *> NewMIBList;

  // For each MIB metadata, check if its call stack context starts with the
  // new clone's callsite metadata. If so, that MIB goes onto the cloned call in
  // the inlined body. If not, it stays on the out-of-line original call.
  for (auto &MIBOp : OrigMemProfMD->operands()) {
    MDNode *MIB = dyn_cast<MDNode>(MIBOp);
    // Stack is first operand of MIB.
    MDNode *StackMD = getMIBStackNode(MIB);
    assert(StackMD);
    // See if the new cloned callsite context matches this profiled context.
    if (haveCommonPrefix(StackMD, ClonedCallsiteMD))
      // Add it to the cloned call's MIB list.
      NewMIBList.push_back(MIB);
  }
  if (NewMIBList.empty()) {
    removeMemProfMetadata(ClonedCall);
    removeCallsiteMetadata(ClonedCall);
    return;
  }
  if (NewMIBList.size() < OrigMemProfMD->getNumOperands())
    updateMemprofMetadata(ClonedCall, NewMIBList, ORE);
}

// Update memprof related metadata (!memprof and !callsite) based on the
// inlining of Callee into the callsite at CB. The updates include merging the
// inlined callee's callsite metadata with that of the inlined call,
// and moving the subset of any memprof contexts to the inlined callee
// allocations if they match the new inlined call stack.
static void
propagateMemProfMetadata(Function *Callee, CallBase &CB,
                         bool ContainsMemProfMetadata,
                         const ValueMap<const Value *, WeakTrackingVH> &VMap,
                         OptimizationRemarkEmitter *ORE) {
  MDNode *CallsiteMD = CB.getMetadata(LLVMContext::MD_callsite);
  // Only need to update if the inlined callsite had callsite metadata, or if
  // there was any memprof metadata inlined.
  if (!CallsiteMD && !ContainsMemProfMetadata)
    return;

  // Propagate metadata onto the cloned calls in the inlined callee.
  for (const auto &Entry : VMap) {
    // See if this is a call that has been inlined and remapped, and not
    // simplified away in the process.
    auto *OrigCall = dyn_cast_or_null<CallBase>(Entry.first);
    auto *ClonedCall = dyn_cast_or_null<CallBase>(Entry.second);
    if (!OrigCall || !ClonedCall)
      continue;
    // If the inlined callsite did not have any callsite metadata, then it isn't
    // involved in any profiled call contexts, and we can remove any memprof
    // metadata on the cloned call.
    if (!CallsiteMD) {
      removeMemProfMetadata(ClonedCall);
      removeCallsiteMetadata(ClonedCall);
      continue;
    }
    propagateMemProfHelper(OrigCall, ClonedCall, CallsiteMD, ORE);
  }
}

/// Collect all calls that produce RetVal, following only pointer-preserving
/// instructions (cast, phi, select).
static void collectPointerReturningCalls(Value *RetVal,
                                         SmallVectorImpl<CallBase *> &Out) {
  SmallVector<Value *, 8> Worklist{RetVal};
  SmallPtrSet<Value *, 8> Visited;
  while (!Worklist.empty()) {
    Value *V = Worklist.pop_back_val();
    if (!V->getType()->isPointerTy() || !Visited.insert(V).second)
      continue;
    if (auto *CB = dyn_cast<CallBase>(V))
      Out.push_back(CB);
    else if (isa<BitCastInst, AddrSpaceCastInst>(V))
      Worklist.push_back(cast<CastInst>(V)->getOperand(0));
    else if (auto *PN = dyn_cast<PHINode>(V))
      append_range(Worklist, PN->incoming_values());
    else if (auto *SI = dyn_cast<SelectInst>(V)) {
      Worklist.push_back(SI->getTrueValue());
      Worklist.push_back(SI->getFalseValue());
    }
  }
}

/// When inlining a call that carries !alloc_token metadata, propagate that
/// metadata onto calls exposed by inlining the wrapper body.  Propagation is
/// restricted to return-value producing calls, which avoids instrumenting
/// unrelated calls in the wrapper body.
static void
propagateAllocTokenMetadata(Function *CalledFunc, CallBase &CB,
                            const ValueMap<const Value *, WeakTrackingVH> &VMap,
                            ClonedCodeInfo &InlinedFunctionInfo) {
  MDNode *AllocTokenMD = CB.getMetadata(LLVMContext::MD_alloc_token);
  if (!AllocTokenMD)
    return;

  SmallVector<CallBase *, 2> AllocCalls;
  for (BasicBlock &BB : *CalledFunc)
    if (auto *RI = dyn_cast<ReturnInst>(BB.getTerminator()))
      if (Value *RV = RI->getReturnValue())
        collectPointerReturningCalls(RV, AllocCalls);

  for (CallBase *OrigCall : AllocCalls) {
    auto *ClonedCall = dyn_cast_or_null<CallBase>(VMap.lookup(OrigCall));
    if (!ClonedCall)
      continue;
    // Skip calls simplified during inlining; propagation may be incorrect.
    if (InlinedFunctionInfo.isSimplified(OrigCall, ClonedCall))
      continue;
    // Fill missing only: never overwrite a more specific token the wrapper
    // already set on an internal allocation. An unknown type (empty type name
    // with function name) is not more specific.
    if (MDNode *MD = ClonedCall->getMetadata(LLVMContext::MD_alloc_token)) {
      if (MD->getNumOperands() != 3 ||
          !cast<MDString>(MD->getOperand(0))->getString().empty())
        continue;
    }
    ClonedCall->setMetadata(LLVMContext::MD_alloc_token, AllocTokenMD);
  }
}

/// When inlining a call site that has !llvm.mem.parallel_loop_access,
/// !llvm.access.group, !alias.scope or !noalias metadata, that metadata should
/// be propagated to all memory-accessing cloned instructions.
static void PropagateCallSiteMetadata(CallBase &CB, Function::iterator FStart,
                                      Function::iterator FEnd) {
  MDNode *MemParallelLoopAccess =
      CB.getMetadata(LLVMContext::MD_mem_parallel_loop_access);
  MDNode *AccessGroup = CB.getMetadata(LLVMContext::MD_access_group);
  MDNode *AliasScope = CB.getMetadata(LLVMContext::MD_alias_scope);
  MDNode *NoAlias = CB.getMetadata(LLVMContext::MD_noalias);
  if (!MemParallelLoopAccess && !AccessGroup && !AliasScope && !NoAlias)
    return;

  for (BasicBlock &BB : make_range(FStart, FEnd)) {
    for (Instruction &I : BB) {
      // This metadata is only relevant for instructions that access memory.
      if (!I.mayReadOrWriteMemory())
        continue;

      if (MemParallelLoopAccess) {
        // TODO: This probably should not overwrite MemParalleLoopAccess.
        MemParallelLoopAccess = MDNode::concatenate(
            I.getMetadata(LLVMContext::MD_mem_parallel_loop_access),
            MemParallelLoopAccess);
        I.setMetadata(LLVMContext::MD_mem_parallel_loop_access,
                      MemParallelLoopAccess);
      }

      if (AccessGroup)
        I.setMetadata(LLVMContext::MD_access_group, uniteAccessGroups(
            I.getMetadata(LLVMContext::MD_access_group), AccessGroup));

      if (AliasScope)
        I.setMetadata(LLVMContext::MD_alias_scope, MDNode::concatenate(
            I.getMetadata(LLVMContext::MD_alias_scope), AliasScope));

      if (NoAlias)
        I.setMetadata(LLVMContext::MD_noalias, MDNode::concatenate(
            I.getMetadata(LLVMContext::MD_noalias), NoAlias));
    }
  }
}

/// Track inlining chain via inlined.from metadata for dontcall diagnostics.
static void PropagateInlinedFromMetadata(CallBase &CB, StringRef CalledFuncName,
                                         StringRef CallerFuncName,
                                         Function::iterator FStart,
                                         Function::iterator FEnd) {
  LLVMContext &Ctx = CB.getContext();
  uint64_t InlineSiteLoc = 0;
  if (auto *MD = CB.getMetadata("srcloc"))
    if (auto *CI = mdconst::dyn_extract<ConstantInt>(MD->getOperand(0)))
      InlineSiteLoc = CI->getZExtValue();

  auto *I64Ty = Type::getInt64Ty(Ctx);
  auto MakeMDInt = [&](uint64_t V) {
    return ConstantAsMetadata::get(ConstantInt::get(I64Ty, V));
  };

  for (BasicBlock &BB : make_range(FStart, FEnd)) {
    for (Instruction &I : BB) {
      auto *CI = dyn_cast<CallInst>(&I);
      if (!CI || !CI->getMetadata("srcloc"))
        continue;
      auto *Callee = CI->getCalledFunction();
      if (!Callee || (!Callee->hasFnAttribute("dontcall-error") &&
                      !Callee->hasFnAttribute("dontcall-warn")))
        continue;

      SmallVector<Metadata *, 8> Ops;
      if (MDNode *Existing = CI->getMetadata("inlined.from"))
        append_range(Ops, Existing->operands());
      else {
        Ops.push_back(MDString::get(Ctx, CalledFuncName));
        Ops.push_back(MakeMDInt(0));
      }
      Ops.push_back(MDString::get(Ctx, CallerFuncName));
      Ops.push_back(MakeMDInt(InlineSiteLoc));
      CI->setMetadata("inlined.from", MDNode::get(Ctx, Ops));
    }
  }
}

/// Bundle operands of the inlined function must be added to inlined call sites.
static void PropagateOperandBundles(Function::iterator InlinedBB,
                                    Instruction *CallSiteEHPad) {
  for (Instruction &II : llvm::make_early_inc_range(*InlinedBB)) {
    CallBase *I = dyn_cast<CallBase>(&II);
    if (!I)
      continue;
    // Skip call sites which already have a "funclet" bundle.
    if (I->getOperandBundle(LLVMContext::OB_funclet))
      continue;
    // Skip call sites which are nounwind intrinsics (as long as they don't
    // lower into regular function calls in the course of IR transformations).
    auto *CalledFn =
        dyn_cast<Function>(I->getCalledOperand()->stripPointerCasts());
    if (CalledFn && CalledFn->isIntrinsic() && I->doesNotThrow() &&
        !IntrinsicInst::mayLowerToFunctionCall(CalledFn->getIntrinsicID()))
      continue;

    SmallVector<OperandBundleDef, 1> OpBundles;
    I->getOperandBundlesAsDefs(OpBundles);
    OpBundles.emplace_back("funclet", CallSiteEHPad);

    Instruction *NewInst = CallBase::Create(I, OpBundles, I->getIterator());
    NewInst->takeName(I);
    I->replaceAllUsesWith(NewInst);
    I->eraseFromParent();
  }
}

namespace {
/// Utility for cloning !noalias and !alias.scope metadata. When a code region
/// using scoped alias metadata is inlined, the aliasing relationships may not
/// hold between the two version. It is necessary to create a deep clone of the
/// metadata, putting the two versions in separate scope domains.
class ScopedAliasMetadataDeepCloner {
  using MetadataMap = DenseMap<const MDNode *, TrackingMDNodeRef>;
  SetVector<const MDNode *> MD;
  MetadataMap MDMap;
  void addRecursiveMetadataUses();

public:
  ScopedAliasMetadataDeepCloner(const Function *F);

  /// Create a new clone of the scoped alias metadata, which will be used by
  /// subsequent remap() calls.
  void clone();

  /// Remap instructions in the given range from the original to the cloned
  /// metadata.
  void remap(Function::iterator FStart, Function::iterator FEnd);
};
} // namespace

ScopedAliasMetadataDeepCloner::ScopedAliasMetadataDeepCloner(
    const Function *F) {
  for (const BasicBlock &BB : *F) {
    for (const Instruction &I : BB) {
      if (const MDNode *M = I.getMetadata(LLVMContext::MD_alias_scope))
        MD.insert(M);
      if (const MDNode *M = I.getMetadata(LLVMContext::MD_noalias))
        MD.insert(M);

      // We also need to clone the metadata in noalias intrinsics.
      if (const auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
        MD.insert(Decl->getScopeList());
    }
  }
  addRecursiveMetadataUses();
}

void ScopedAliasMetadataDeepCloner::addRecursiveMetadataUses() {
  SmallVector<const Metadata *, 16> Queue(MD.begin(), MD.end());
  while (!Queue.empty()) {
    const MDNode *M = cast<MDNode>(Queue.pop_back_val());
    for (const Metadata *Op : M->operands())
      if (const MDNode *OpMD = dyn_cast<MDNode>(Op))
        if (MD.insert(OpMD))
          Queue.push_back(OpMD);
  }
}

void ScopedAliasMetadataDeepCloner::clone() {
  assert(MDMap.empty() && "clone() already called ?");

  SmallVector<TempMDTuple, 16> DummyNodes;
  for (const MDNode *I : MD) {
    DummyNodes.push_back(MDTuple::getTemporary(I->getContext(), {}));
    MDMap[I].reset(DummyNodes.back().get());
  }

  // Create new metadata nodes to replace the dummy nodes, replacing old
  // metadata references with either a dummy node or an already-created new
  // node.
  SmallVector<Metadata *, 4> NewOps;
  for (const MDNode *I : MD) {
    for (const Metadata *Op : I->operands()) {
      if (const MDNode *M = dyn_cast<MDNode>(Op))
        NewOps.push_back(MDMap[M]);
      else
        NewOps.push_back(const_cast<Metadata *>(Op));
    }

    MDNode *NewM = MDNode::get(I->getContext(), NewOps);
    MDTuple *TempM = cast<MDTuple>(MDMap[I]);
    assert(TempM->isTemporary() && "Expected temporary node");

    TempM->replaceAllUsesWith(NewM);
    NewOps.clear();
  }
}

void ScopedAliasMetadataDeepCloner::remap(Function::iterator FStart,
                                          Function::iterator FEnd) {
  if (MDMap.empty())
    return; // Nothing to do.

  for (BasicBlock &BB : make_range(FStart, FEnd)) {
    for (Instruction &I : BB) {
      // TODO: The null checks for the MDMap.lookup() results should no longer
      // be necessary.
      if (MDNode *M = I.getMetadata(LLVMContext::MD_alias_scope))
        if (MDNode *MNew = MDMap.lookup(M))
          I.setMetadata(LLVMContext::MD_alias_scope, MNew);

      if (MDNode *M = I.getMetadata(LLVMContext::MD_noalias))
        if (MDNode *MNew = MDMap.lookup(M))
          I.setMetadata(LLVMContext::MD_noalias, MNew);

      if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
        if (MDNode *MNew = MDMap.lookup(Decl->getScopeList()))
          Decl->setScopeList(MNew);
    }
  }
}

/// If the inlined function has noalias arguments,
/// then add new alias scopes for each noalias argument, tag the mapped noalias
/// parameters with noalias metadata specifying the new scope, and tag all
/// non-derived loads, stores and memory intrinsics with the new alias scopes.
static void AddAliasScopeMetadata(CallBase &CB, ValueToValueMapTy &VMap,
                                  const DataLayout &DL, AAResults *CalleeAAR,
                                  ClonedCodeInfo &InlinedFunctionInfo) {
  if (!EnableNoAliasConversion)
    return;

  const Function *CalledFunc = CB.getCalledFunction();
  SmallVector<const Argument *, 4> NoAliasArgs;

  for (const Argument &Arg : CalledFunc->args())
    if (CB.paramHasAttr(Arg.getArgNo(), Attribute::NoAlias) && !Arg.use_empty())
      NoAliasArgs.push_back(&Arg);

  if (NoAliasArgs.empty())
    return;

  // To do a good job, if a noalias variable is captured, we need to know if
  // the capture point dominates the particular use we're considering.
  DominatorTree DT;
  DT.recalculate(const_cast<Function&>(*CalledFunc));

  // noalias indicates that pointer values based on the argument do not alias
  // pointer values which are not based on it. So we add a new "scope" for each
  // noalias function argument. Accesses using pointers based on that argument
  // become part of that alias scope, accesses using pointers not based on that
  // argument are tagged as noalias with that scope.

  DenseMap<const Argument *, MDNode *> NewScopes;
  MDBuilder MDB(CalledFunc->getContext());

  // Create a new scope domain for this function. Its scopes are disjoint,
  // since accesses based on one noalias argument don't alias accesses based on
  // another one.
  MDNode *NewDomain = MDB.createAnonymousAliasScopeDomain(
      CalledFunc->getName(), /*DisjointScopes=*/true);
  for (unsigned i = 0, e = NoAliasArgs.size(); i != e; ++i) {
    const Argument *A = NoAliasArgs[i];

    std::string Name = std::string(CalledFunc->getName());
    if (A->hasName()) {
      Name += ": %";
      Name += A->getName();
    } else {
      Name += ": argument ";
      Name += utostr(i);
    }

    // Note: We always create a new anonymous root here. This is true regardless
    // of the linkage of the callee because the aliasing "scope" is not just a
    // property of the callee, but also all control dependencies in the caller.
    MDNode *NewScope = MDB.createAnonymousAliasScope(NewDomain, Name);
    NewScopes.insert(std::make_pair(A, NewScope));

    if (UseNoAliasIntrinsic) {
      // Introduce a llvm.experimental.noalias.scope.decl for the noalias
      // argument.
      MDNode *AScopeList = MDNode::get(CalledFunc->getContext(), NewScope);
      auto *NoAliasDecl =
          IRBuilder<>(&CB).CreateNoAliasScopeDeclaration(AScopeList);
      // Ignore the result for now. The result will be used when the
      // llvm.noalias intrinsic is introduced.
      (void)NoAliasDecl;
    }
  }

  // Iterate over all new instructions in the map; for all memory-access
  // instructions, add the alias scope metadata.
  for (ValueToValueMapTy::iterator VMI = VMap.begin(), VMIE = VMap.end();
       VMI != VMIE; ++VMI) {
    if (const Instruction *I = dyn_cast<Instruction>(VMI->first)) {
      if (!VMI->second)
        continue;

      Instruction *NI = dyn_cast<Instruction>(VMI->second);
      if (!NI || InlinedFunctionInfo.isSimplified(I, NI))
        continue;

      bool IsArgMemOnlyCall = false, IsFuncCall = false;
      SmallVector<const Value *, 2> PtrArgs;

      if (const LoadInst *LI = dyn_cast<LoadInst>(I))
        PtrArgs.push_back(LI->getPointerOperand());
      else if (const StoreInst *SI = dyn_cast<StoreInst>(I))
        PtrArgs.push_back(SI->getPointerOperand());
      else if (const VAArgInst *VAAI = dyn_cast<VAArgInst>(I))
        PtrArgs.push_back(VAAI->getPointerOperand());
      else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(I))
        PtrArgs.push_back(CXI->getPointerOperand());
      else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(I))
        PtrArgs.push_back(RMWI->getPointerOperand());
      else if (const auto *Call = dyn_cast<CallBase>(I)) {
        // If we know that the call does not access memory, then we'll still
        // know that about the inlined clone of this call site, and we don't
        // need to add metadata.
        if (Call->doesNotAccessMemory())
          continue;

        IsFuncCall = true;
        if (CalleeAAR) {
          MemoryEffects ME = CalleeAAR->getMemoryEffects(Call);

          // We'll retain this knowledge without additional metadata.
          if (ME.onlyAccessesInaccessibleMem())
            continue;

          if (ME.onlyAccessesArgPointees())
            IsArgMemOnlyCall = true;
        }

        for (Value *Arg : Call->args()) {
          // Only care about pointer arguments. If a noalias argument is
          // accessed through a non-pointer argument, it must be captured
          // first (e.g. via ptrtoint), and we protect against captures below.
          if (!Arg->getType()->isPointerTy())
            continue;

          PtrArgs.push_back(Arg);
        }
      }

      // If we found no pointers, then this instruction is not suitable for
      // pairing with an instruction to receive aliasing metadata.
      // However, if this is a call, this we might just alias with none of the
      // noalias arguments.
      if (PtrArgs.empty() && !IsFuncCall)
        continue;

      // It is possible that there is only one underlying object, but you
      // need to go through several PHIs to see it, and thus could be
      // repeated in the Objects list.
      SmallPtrSet<const Value *, 4> ObjSet;
      SmallVector<Metadata *, 4> Scopes, NoAliases;

      for (const Value *V : PtrArgs) {
        SmallVector<const Value *, 4> Objects;
        getUnderlyingObjects(V, Objects, /* LI = */ nullptr);

        ObjSet.insert_range(Objects);
      }

      // Figure out if we're derived from anything that is not a noalias
      // argument.
      bool RequiresNoCaptureBefore = false, UsesAliasingPtr = false,
           UsesUnknownObject = false;
      for (const Value *V : ObjSet) {
        // Is this value a constant that cannot be derived from any pointer
        // value (we need to exclude constant expressions, for example, that
        // are formed from arithmetic on global symbols).
        bool IsNonPtrConst = isa<ConstantInt>(V) || isa<ConstantFP>(V) ||
                             isa<ConstantPointerNull>(V) ||
                             isa<ConstantDataVector>(V) || isa<UndefValue>(V);
        if (IsNonPtrConst)
          continue;

        // If this is anything other than a noalias argument, then we cannot
        // completely describe the aliasing properties using alias.scope
        // metadata (and, thus, won't add any).
        if (const Argument *A = dyn_cast<Argument>(V)) {
          if (!CB.paramHasAttr(A->getArgNo(), Attribute::NoAlias))
            UsesAliasingPtr = true;
        } else {
          UsesAliasingPtr = true;
        }

        if (isEscapeSource(V)) {
          // An escape source can only alias with a noalias argument if it has
          // been captured beforehand.
          RequiresNoCaptureBefore = true;
        } else if (!isa<Argument>(V) && !isIdentifiedObject(V)) {
          // If this is neither an escape source, nor some identified object
          // (which cannot directly alias a noalias argument), nor some other
          // argument (which, by definition, also cannot alias a noalias
          // argument), conservatively do not make any assumptions.
          UsesUnknownObject = true;
        }
      }

      // Nothing we can do if the used underlying object cannot be reliably
      // determined.
      if (UsesUnknownObject)
        continue;

      // A function call can always get captured noalias pointers (via other
      // parameters, globals, etc.).
      if (IsFuncCall && !IsArgMemOnlyCall)
        RequiresNoCaptureBefore = true;

      // First, we want to figure out all of the sets to which we might belong.
      // We might belong to a set if the noalias argument is in the set of
      // underlying objects. If there is some non-noalias argument in our list
      // of underlying objects, then we cannot add a scope because the fact
      // that some access does not alias with any set of our noalias arguments
      // cannot itself guarantee that it does not alias with this access
      // (because there is some pointer of unknown origin involved and the
      // other access might also depend on this pointer). We also cannot add
      // scopes to arbitrary functions unless we know they don't access any
      // non-parameter pointer-values.
      bool CanAddScopes = !UsesAliasingPtr && (!IsFuncCall || IsArgMemOnlyCall);
      if (CanAddScopes) {
        for (const Argument *A : NoAliasArgs) {
          if (ObjSet.count(A))
            Scopes.push_back(NewScopes[A]);
        }
      }

      if (!Scopes.empty()) {
        NI->setMetadata(
            LLVMContext::MD_alias_scope,
            MDNode::concatenate(NI->getMetadata(LLVMContext::MD_alias_scope),
                                MDNode::get(CalledFunc->getContext(), Scopes)));
        // Being in these scopes already means being noalias with the rest.
        continue;
      }

      // Next, we want to figure out all of the sets with which we definitely
      // don't alias. Iterate over all noalias set, and add those for which:
      //   1. The noalias argument is not in the set of objects from which we
      //      definitely derive.
      //   2. The noalias argument has not yet been captured.
      // An arbitrary function that might load pointers could see captured
      // noalias arguments via other noalias arguments or globals, and so we
      // must always check for prior capture.
      for (const Argument *A : NoAliasArgs) {
        if (ObjSet.contains(A))
          continue; // May be based on a noalias argument.

        // It might be tempting to skip the PointerMayBeCapturedBefore check if
        // A->hasNoCaptureAttr() is true, but this is incorrect because
        // nocapture only guarantees that no copies outlive the function, not
        // that the value cannot be locally captured.
        if (!RequiresNoCaptureBefore ||
            !capturesAnything(PointerMayBeCapturedBefore(
                A, /*ReturnCaptures=*/false, I, &DT, /*IncludeI=*/false,
                CaptureComponents::Provenance)))
          NoAliases.push_back(NewScopes[A]);
      }

      if (!NoAliases.empty())
        NI->setMetadata(LLVMContext::MD_noalias,
                        MDNode::concatenate(
                            NI->getMetadata(LLVMContext::MD_noalias),
                            MDNode::get(CalledFunc->getContext(), NoAliases)));
    }
  }
}

static bool MayContainThrowingOrExitingCallAfterCB(CallBase *Begin,
                                                   ReturnInst *End) {

  assert(Begin->getParent() == End->getParent() &&
         "Expected to be in same basic block!");
  auto BeginIt = Begin->getIterator();
  assert(BeginIt != End->getIterator() && "Non-empty BB has empty iterator");
  return !llvm::isGuaranteedToTransferExecutionToSuccessor(
      ++BeginIt, End->getIterator(), InlinerAttributeWindow + 1);
}

// Add attributes from CB params and Fn attributes that can always be propagated
// to the corresponding argument / inner callbases.
static void AddParamAndFnBasicAttributes(const CallBase &CB,
                                         ValueToValueMapTy &VMap,
                                         ClonedCodeInfo &InlinedFunctionInfo) {
  auto *CalledFunction = CB.getCalledFunction();
  auto &Context = CalledFunction->getContext();

  // Collect valid attributes for all params.
  SmallVector<AttrBuilder> ValidObjParamAttrs, ValidExactParamAttrs;
  bool HasAttrToPropagate = false;

  // Attributes we can only propagate if the exact parameter is forwarded.
  // We can propagate both poison generating and UB generating attributes
  // without any extra checks. The only attribute that is tricky to propagate
  // is `noundef` (skipped for now) as that can create new UB where previous
  // behavior was just using a poison value.
  static const Attribute::AttrKind ExactAttrsToPropagate[] = {
      Attribute::Dereferenceable, Attribute::DereferenceableOrNull,
      Attribute::NonNull,         Attribute::NoFPClass,
      Attribute::Alignment,       Attribute::Range};

  for (unsigned I = 0, E = CB.arg_size(); I < E; ++I) {
    ValidObjParamAttrs.emplace_back(AttrBuilder{CB.getContext()});
    ValidExactParamAttrs.emplace_back(AttrBuilder{CB.getContext()});
    // Access attributes can be propagated to any param with the same underlying
    // object as the argument.
    if (CB.paramHasAttr(I, Attribute::ReadNone))
      ValidObjParamAttrs.back().addAttribute(Attribute::ReadNone);
    if (CB.paramHasAttr(I, Attribute::ReadOnly))
      ValidObjParamAttrs.back().addAttribute(Attribute::ReadOnly);

    for (Attribute::AttrKind AK : ExactAttrsToPropagate) {
      Attribute Attr = CB.getParamAttr(I, AK);
      if (Attr.isValid())
        ValidExactParamAttrs.back().addAttribute(Attr);
    }

    HasAttrToPropagate |= ValidObjParamAttrs.back().hasAttributes();
    HasAttrToPropagate |= ValidExactParamAttrs.back().hasAttributes();
  }

  // Won't be able to propagate anything.
  if (!HasAttrToPropagate)
    return;

  for (BasicBlock &BB : *CalledFunction) {
    for (Instruction &Ins : BB) {
      const auto *InnerCB = dyn_cast<CallBase>(&Ins);
      if (!InnerCB)
        continue;
      auto *NewInnerCB = dyn_cast_or_null<CallBase>(VMap.lookup(InnerCB));
      if (!NewInnerCB)
        continue;
      // The InnerCB might have be simplified during the inlining
      // process which can make propagation incorrect.
      if (InlinedFunctionInfo.isSimplified(InnerCB, NewInnerCB))
        continue;

      AttributeList AL = NewInnerCB->getAttributes();
      for (unsigned I = 0, E = InnerCB->arg_size(); I < E; ++I) {
        // It's unsound or requires special handling to propagate
        // attributes to byval arguments. Even if CalledFunction
        // doesn't e.g. write to the argument (readonly), the call to
        // NewInnerCB may write to its by-value copy.
        if (NewInnerCB->isByValArgument(I))
          continue;

        // Don't bother propagating attrs to constants.
        if (match(NewInnerCB->getArgOperand(I),
                  llvm::PatternMatch::m_ImmConstant()))
          continue;

        // Check if the underlying value for the parameter is an argument.
        const Argument *Arg = dyn_cast<Argument>(InnerCB->getArgOperand(I));
        unsigned ArgNo;
        if (Arg) {
          ArgNo = Arg->getArgNo();
          // For dereferenceable, dereferenceable_or_null, align, etc...
          // we don't want to propagate if the existing param has the same
          // attribute with "better" constraints. So  remove from the
          // new AL if the region of the existing param is larger than
          // what we can propagate.
          AttrBuilder NewAB{
              Context, AttributeSet::get(Context, ValidExactParamAttrs[ArgNo])};
          if (AL.getParamDereferenceableBytes(I) >
              NewAB.getDereferenceableBytes())
            NewAB.removeAttribute(Attribute::Dereferenceable);
          if (AL.getParamDereferenceableOrNullBytes(I) >
              NewAB.getDereferenceableOrNullBytes())
            NewAB.removeAttribute(Attribute::DereferenceableOrNull);
          if (AL.getParamAlignment(I).valueOrOne() >
              NewAB.getAlignment().valueOrOne())
            NewAB.removeAttribute(Attribute::Alignment);
          if (auto ExistingRange = AL.getParamRange(I)) {
            if (auto NewRange = NewAB.getRange()) {
              ConstantRange CombinedRange =
                  ExistingRange->intersectWith(*NewRange);
              NewAB.removeAttribute(Attribute::Range);
              NewAB.addRangeAttr(CombinedRange);
            }
          }

          if (FPClassTest ExistingNoFP = AL.getParamNoFPClass(I))
            NewAB.addNoFPClassAttr(ExistingNoFP | NewAB.getNoFPClass());

          AL = AL.addParamAttributes(Context, I, NewAB);
        } else if (NewInnerCB->getArgOperand(I)->getType()->isPointerTy()) {
          // Check if the underlying value for the parameter is an argument.
          const Value *UnderlyingV =
              getUnderlyingObject(InnerCB->getArgOperand(I));
          Arg = dyn_cast<Argument>(UnderlyingV);
          if (!Arg)
            continue;
          ArgNo = Arg->getArgNo();
        } else {
          continue;
        }

        // If so, propagate its access attributes.
        AL = AL.addParamAttributes(Context, I, ValidObjParamAttrs[ArgNo]);

        // We can have conflicting attributes from the inner callsite and
        // to-be-inlined callsite. In that case, choose the most
        // restrictive.

        // readonly + writeonly means we can never deref so make readnone.
        if (AL.hasParamAttr(I, Attribute::ReadOnly) &&
            AL.hasParamAttr(I, Attribute::WriteOnly))
          AL = AL.addParamAttribute(Context, I, Attribute::ReadNone);

        // If have readnone, need to clear readonly/writeonly
        if (AL.hasParamAttr(I, Attribute::ReadNone)) {
          AL = AL.removeParamAttribute(Context, I, Attribute::ReadOnly);
          AL = AL.removeParamAttribute(Context, I, Attribute::WriteOnly);
        }

        // Writable cannot exist in conjunction w/ readonly/readnone
        if (AL.hasParamAttr(I, Attribute::ReadOnly) ||
            AL.hasParamAttr(I, Attribute::ReadNone))
          AL = AL.removeParamAttribute(Context, I, Attribute::Writable);
      }
      NewInnerCB->setAttributes(AL);
    }
  }
}

// Only allow these white listed attributes to be propagated back to the
// callee. This is because other attributes may only be valid on the call
// itself, i.e. attributes such as signext and zeroext.

// Attributes that are always okay to propagate as if they are violated its
// immediate UB.
static AttrBuilder IdentifyValidUBGeneratingAttributes(CallBase &CB) {
  AttrBuilder Valid(CB.getContext());
  if (auto DerefBytes = CB.getRetDereferenceableBytes())
    Valid.addDereferenceableAttr(DerefBytes);
  if (auto DerefOrNullBytes = CB.getRetDereferenceableOrNullBytes())
    Valid.addDereferenceableOrNullAttr(DerefOrNullBytes);
  if (CB.hasRetAttr(Attribute::NoAlias))
    Valid.addAttribute(Attribute::NoAlias);
  if (CB.hasRetAttr(Attribute::NoUndef))
    Valid.addAttribute(Attribute::NoUndef);
  return Valid;
}

// Attributes that need additional checks as propagating them may change
// behavior or cause new UB.
static AttrBuilder IdentifyValidPoisonGeneratingAttributes(CallBase &CB) {
  AttrBuilder Valid(CB.getContext());
  if (CB.hasRetAttr(Attribute::NonNull))
    Valid.addAttribute(Attribute::NonNull);
  if (CB.hasRetAttr(Attribute::Alignment))
    Valid.addAlignmentAttr(CB.getRetAlign());
  if (std::optional<ConstantRange> Range = CB.getRange())
    Valid.addRangeAttr(*Range);
  if (CB.hasRetAttr(Attribute::NoFPClass))
    Valid.addNoFPClassAttr(CB.getRetNoFPClass());
  return Valid;
}

static void AddReturnAttributes(CallBase &CB, ValueToValueMapTy &VMap,
                                ClonedCodeInfo &InlinedFunctionInfo) {
  AttrBuilder CallSiteValidUB = IdentifyValidUBGeneratingAttributes(CB);
  AttrBuilder CallSiteValidPG = IdentifyValidPoisonGeneratingAttributes(CB);
  if (!CallSiteValidUB.hasAttributes() && !CallSiteValidPG.hasAttributes())
    return;
  auto *CalledFunction = CB.getCalledFunction();
  auto &Context = CalledFunction->getContext();

  for (auto &BB : *CalledFunction) {
    auto *RI = dyn_cast<ReturnInst>(BB.getTerminator());
    if (!RI || !isa<CallBase>(RI->getOperand(0)))
      continue;
    auto *RetVal = cast<CallBase>(RI->getOperand(0));
    // Check that the cloned RetVal exists and is a call, otherwise we cannot
    // add the attributes on the cloned RetVal. Simplification during inlining
    // could have transformed the cloned instruction.
    auto *NewRetVal = dyn_cast_or_null<CallBase>(VMap.lookup(RetVal));
    if (!NewRetVal)
      continue;

    // The RetVal might have be simplified during the inlining
    // process which can make propagation incorrect.
    if (InlinedFunctionInfo.isSimplified(RetVal, NewRetVal))
      continue;
    // Backward propagation of attributes to the returned value may be incorrect
    // if it is control flow dependent.
    // Consider:
    // @callee {
    //  %rv = call @foo()
    //  %rv2 = call @bar()
    //  if (%rv2 != null)
    //    return %rv2
    //  if (%rv == null)
    //    exit()
    //  return %rv
    // }
    // caller() {
    //   %val = call nonnull @callee()
    // }
    // Here we cannot add the nonnull attribute on either foo or bar. So, we
    // limit the check to both RetVal and RI are in the same basic block and
    // there are no throwing/exiting instructions between these instructions.
    if (RI->getParent() != RetVal->getParent() ||
        MayContainThrowingOrExitingCallAfterCB(RetVal, RI))
      continue;
    // Add to the existing attributes of NewRetVal, i.e. the cloned call
    // instruction.
    // NB! When we have the same attribute already existing on NewRetVal, but
    // with a differing value, the AttributeList's merge API honours the already
    // existing attribute value (i.e. attributes such as dereferenceable,
    // dereferenceable_or_null etc). See AttrBuilder::merge for more details.
    AttrBuilder ValidUB = IdentifyValidUBGeneratingAttributes(CB);
    AttrBuilder ValidPG = IdentifyValidPoisonGeneratingAttributes(CB);
    AttributeList AL = NewRetVal->getAttributes();
    if (ValidUB.getDereferenceableBytes() < AL.getRetDereferenceableBytes())
      ValidUB.removeAttribute(Attribute::Dereferenceable);
    if (ValidUB.getDereferenceableOrNullBytes() <
        AL.getRetDereferenceableOrNullBytes())
      ValidUB.removeAttribute(Attribute::DereferenceableOrNull);
    AttributeList NewAL = AL.addRetAttributes(Context, ValidUB);
    // Attributes that may generate poison returns are a bit tricky. If we
    // propagate them, other uses of the callsite might have their behavior
    // change or cause UB (if they have noundef) b.c of the new potential
    // poison.
    // Take the following three cases:
    //
    // 1)
    // define nonnull ptr @foo() {
    //   %p = call ptr @bar()
    //   call void @use(ptr %p) willreturn nounwind
    //   ret ptr %p
    // }
    //
    // 2)
    // define noundef nonnull ptr @foo() {
    //   %p = call ptr @bar()
    //   call void @use(ptr %p) willreturn nounwind
    //   ret ptr %p
    // }
    //
    // 3)
    // define nonnull ptr @foo() {
    //   %p = call noundef ptr @bar()
    //   ret ptr %p
    // }
    //
    // In case 1, we can't propagate nonnull because poison value in @use may
    // change behavior or trigger UB.
    // In case 2, we don't need to be concerned about propagating nonnull, as
    // any new poison at @use will trigger UB anyways.
    // In case 3, we can never propagate nonnull because it may create UB due to
    // the noundef on @bar.
    if (ValidPG.getAlignment().valueOrOne() < AL.getRetAlignment().valueOrOne())
      ValidPG.removeAttribute(Attribute::Alignment);
    if (ValidPG.hasAttributes()) {
      Attribute CBRange = ValidPG.getAttribute(Attribute::Range);
      if (CBRange.isValid()) {
        Attribute NewRange = AL.getRetAttr(Attribute::Range);
        if (NewRange.isValid()) {
          ValidPG.addRangeAttr(
              CBRange.getRange().intersectWith(NewRange.getRange()));
        }
      }

      Attribute CBNoFPClass = ValidPG.getAttribute(Attribute::NoFPClass);
      if (CBNoFPClass.isValid() && AL.hasRetAttr(Attribute::NoFPClass)) {
        ValidPG.addNoFPClassAttr(
            CBNoFPClass.getNoFPClass() |
            AL.getRetAttr(Attribute::NoFPClass).getNoFPClass());
      }

      // Three checks.
      // If the callsite has `noundef`, then a poison due to violating the
      // return attribute will create UB anyways so we can always propagate.
      // Otherwise, if the return value (callee to be inlined) has `noundef`, we
      // can't propagate as a new poison return will cause UB.
      // Finally, check if the return value has no uses whose behavior may
      // change/may cause UB if we potentially return poison. At the moment this
      // is implemented overly conservatively with a single-use check.
      // TODO: Update the single-use check to iterate through uses and only bail
      // if we have a potentially dangerous use.

      if (CB.hasRetAttr(Attribute::NoUndef) ||
          (RetVal->hasOneUse() && !RetVal->hasRetAttr(Attribute::NoUndef)))
        NewAL = NewAL.addRetAttributes(Context, ValidPG);
    }
    NewRetVal->setAttributes(NewAL);
  }
}

/// If the inlined function has non-byval align arguments, then
/// add @llvm.assume-based alignment assumptions to preserve this information.
static void AddAlignmentAssumptions(CallBase &CB, InlineFunctionInfo &IFI) {
  if (!PreserveAlignmentAssumptions || !IFI.GetAssumptionCache)
    return;

  AssumptionCache *AC = &IFI.GetAssumptionCache(*CB.getCaller());
  auto &DL = CB.getDataLayout();

  // To avoid inserting redundant assumptions, we should check for assumptions
  // already in the caller. To do this, we might need a DT of the caller.
  DominatorTree DT;
  bool DTCalculated = false;

  Function *CalledFunc = CB.getCalledFunction();
  for (Argument &Arg : CalledFunc->args()) {
    if (!Arg.getType()->isPointerTy() || Arg.hasPassPointeeByValueCopyAttr() ||
        Arg.use_empty())
      continue;
    MaybeAlign Alignment = Arg.getParamAlign();
    if (!Alignment)
      continue;

    if (!DTCalculated) {
      DT.recalculate(*CB.getCaller());
      DTCalculated = true;
    }
    // If we can already prove the asserted alignment in the context of the
    // caller, then don't bother inserting the assumption.
    Value *ArgVal = CB.getArgOperand(Arg.getArgNo());
    if (getKnownAlignment(ArgVal, DL, &CB, AC, &DT) >= *Alignment)
      continue;

    CallInst *NewAsmp = IRBuilder<>(&CB).CreateAlignmentAssumption(
        DL, ArgVal, Alignment->value());
    AC->registerAssumption(cast<AssumeInst>(NewAsmp));
  }
}

static void HandleByValArgumentInit(Type *ByValType, Value *Dst, Value *Src,
                                    MaybeAlign SrcAlign, Module *M,
                                    BasicBlock *InsertBlock,
                                    InlineFunctionInfo &IFI,
                                    Function *CalledFunc) {
  IRBuilder<> Builder(InsertBlock->begin());

  Value *Size =
      Builder.getInt64(M->getDataLayout().getTypeStoreSize(ByValType));

  Align DstAlign = Dst->getPointerAlignment(M->getDataLayout());

  // Generate a memcpy with the correct alignments.
  CallInst *CI = Builder.CreateMemCpy(Dst, DstAlign, Src, SrcAlign, Size);

  // The verifier requires that all calls of debug-info-bearing functions
  // from debug-info-bearing functions have a debug location (for inlining
  // purposes). Assign a dummy location to satisfy the constraint.
  if (!CI->getDebugLoc() && InsertBlock->getParent()->getSubprogram())
    if (DISubprogram *SP = CalledFunc->getSubprogram())
      CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP));
}

/// When inlining a call site that has a byval argument,
/// we have to make the implicit memcpy explicit by adding it.
static Value *HandleByValArgument(Type *ByValType, Value *Arg,
                                  Instruction *TheCall,
                                  const Function *CalledFunc,
                                  InlineFunctionInfo &IFI,
                                  MaybeAlign ByValAlignment) {
  Function *Caller = TheCall->getFunction();
  const DataLayout &DL = Caller->getDataLayout();

  // If the called function is readonly, then it could not mutate the caller's
  // copy of the byval'd memory.  In this case, it is safe to elide the copy and
  // temporary.
  if (CalledFunc->onlyReadsMemory()) {
    // If the byval argument has a specified alignment that is greater than the
    // passed in pointer, then we either have to round up the input pointer or
    // give up on this transformation.
    if (ByValAlignment.valueOrOne() == 1)
      return Arg;

    AssumptionCache *AC =
        IFI.GetAssumptionCache ? &IFI.GetAssumptionCache(*Caller) : nullptr;

    // If the pointer is already known to be sufficiently aligned, or if we can
    // round it up to a larger alignment, then we don't need a temporary.
    if (getOrEnforceKnownAlignment(Arg, *ByValAlignment, DL, TheCall, AC) >=
        *ByValAlignment)
      return Arg;

    // Otherwise, we have to make a memcpy to get a safe alignment.  This is bad
    // for code quality, but rarely happens and is required for correctness.
  }

  // Create the alloca.  If we have DataLayout, use nice alignment.
  Align Alignment = DL.getPrefTypeAlign(ByValType);

  // If the byval had an alignment specified, we *must* use at least that
  // alignment, as it is required by the byval argument (and uses of the
  // pointer inside the callee).
  if (ByValAlignment)
    Alignment = std::max(Alignment, *ByValAlignment);

  AllocaInst *NewAlloca =
      new AllocaInst(ByValType, Arg->getType()->getPointerAddressSpace(),
                     nullptr, Alignment, Arg->getName());
  NewAlloca->setDebugLoc(DebugLoc::getCompilerGenerated());
  NewAlloca->insertBefore(Caller->begin()->begin());
  IFI.StaticAllocas.push_back(NewAlloca);

  // Uses of the argument in the function should use our new alloca
  // instead.
  return NewAlloca;
}

// Check whether this Value is used by a lifetime intrinsic.
static bool isUsedByLifetimeMarker(Value *V) {
  for (User *U : V->users())
    if (isa<LifetimeIntrinsic>(U))
      return true;
  return false;
}

// Check whether the given alloca already has
// lifetime.start or lifetime.end intrinsics.
static bool hasLifetimeMarkers(AllocaInst *AI) {
  Type *Ty = AI->getType();
  Type *Int8PtrTy =
      PointerType::get(Ty->getContext(), Ty->getPointerAddressSpace());
  if (Ty == Int8PtrTy)
    return isUsedByLifetimeMarker(AI);

  // Do a scan to find all the casts to i8*.
  for (User *U : AI->users()) {
    if (U->getType() != Int8PtrTy) continue;
    if (U->stripPointerCasts() != AI) continue;
    if (isUsedByLifetimeMarker(U))
      return true;
  }
  return false;
}

/// Return the result of AI->isStaticAlloca() if AI were moved to the entry
/// block. Allocas used in inalloca calls and allocas of dynamic array size
/// cannot be static.
static bool allocaWouldBeStaticInEntry(const AllocaInst *AI ) {
  return isa<Constant>(AI->getArraySize()) && !AI->isUsedWithInAlloca();
}

/// Returns a DebugLoc for a new DILocation which is a clone of \p OrigDL
/// inlined at \p InlinedAt. \p IANodes is an inlined-at cache.
static DebugLoc inlineDebugLoc(
    DebugLoc OrigDL, DILocation *InlinedAt, LLVMContext &Ctx,
    DenseMap<const MDNode *, MDNode *> &IANodes,
    SmallDenseMap<const DILocation *, DILocation *, 16> &InlineLocs) {
  if (DILocation *Cached = InlineLocs.lookup(OrigDL.get()))
    return DebugLoc(Cached);
  DILocation *IA =
      OrigDL->getInlinedAt()
          ? DebugLoc::appendInlinedAt(OrigDL, InlinedAt, Ctx, IANodes).get()
          : InlinedAt;
  DILocation *Result = DILocation::getDistinct(
      Ctx, OrigDL.getLine(), OrigDL.getCol(), OrigDL.getScope(), IA,
      OrigDL.isImplicitCode(), OrigDL->getAtomGroup(), OrigDL->getAtomRank());
  InlineLocs[OrigDL.get()] = Result;
  return DebugLoc(Result);
}

/// Update inlined instructions' line numbers to
/// to encode location where these instructions are inlined.
static void fixupLineNumbers(Function *Fn, Function::iterator FI,
                             Instruction *TheCall, bool CalleeHasDebugInfo) {
  if (!TheCall->getDebugLoc())
    return;

  // Don't propagate the source location atom from the call to inlined nodebug
  // instructions, and avoid putting it in the InlinedAt field of inlined
  // not-nodebug instructions. FIXME: Possibly worth transferring/generating
  // an atom for the returned value, otherwise we miss stepping on inlined
  // nodebug functions (which is different to existing behaviour).
  DebugLoc TheCallDL = TheCall->getDebugLoc()->getWithoutAtom();

  // A call receiving the outer callsite's fallback location has no usable
  // callsite probe of its own. Do not let it inherit the outer call's probe
  // discriminator, but preserve any packed DWARF base discriminator.
  DebugLoc TheCallDLForInlinedCall = TheCallDL;
  uint32_t Discriminator = TheCallDLForInlinedCall->getDiscriminator();
  if (DILocation::isPseudoProbeDiscriminator(Discriminator)) {
    std::optional<uint32_t> DwarfDiscriminator =
        PseudoProbeDwarfDiscriminator::extractDwarfBaseDiscriminator(
            Discriminator);
    TheCallDLForInlinedCall = TheCallDLForInlinedCall->cloneWithDiscriminator(
        DwarfDiscriminator.value_or(0));
  }

  auto &Ctx = Fn->getContext();
  DILocation *InlinedAtNode = TheCallDL;

  // Create a unique call site, not to be confused with any other call from the
  // same location.
  InlinedAtNode = DILocation::getDistinct(
      Ctx, InlinedAtNode->getLine(), InlinedAtNode->getColumn(),
      InlinedAtNode->getScope(), InlinedAtNode->getInlinedAt());

  // Cache the inlined-at nodes as they're built so they are reused, without
  // this every instruction's inlined-at chain would become distinct from each
  // other.
  DenseMap<const MDNode *, MDNode *> IANodes;
  SmallDenseMap<const DILocation *, DILocation *, 16> InlineLocs;

  // Check if we are not generating inline line tables and want to use
  // the call site location instead.
  bool NoInlineLineTables = Fn->hasFnAttribute("no-inline-line-tables");

  // Helper-util for updating the metadata attached to an instruction.
  auto UpdateInst = [&](Instruction &I) {
    // Loop metadata needs to be updated so that the start and end locs
    // reference inlined-at locations.
    auto updateLoopInfoLoc = [&Ctx, &InlinedAtNode, &IANodes,
                              &InlineLocs](Metadata *MD) -> Metadata * {
      if (auto *Loc = dyn_cast_or_null<DILocation>(MD))
        return inlineDebugLoc(Loc, InlinedAtNode, Ctx, IANodes, InlineLocs)
            .get();
      return MD;
    };
    updateLoopMetadataDebugLocations(I, updateLoopInfoLoc);

    if (!NoInlineLineTables)
      if (DebugLoc DL = I.getDebugLoc()) {
        DebugLoc IDL = inlineDebugLoc(DL, InlinedAtNode, I.getContext(),
                                      IANodes, InlineLocs);
        I.setDebugLoc(IDL);
        return;
      }

    if (CalleeHasDebugInfo && !NoInlineLineTables)
      return;

    // If the inlined instruction has no line number, or if inline info
    // is not being generated, make it look as if it originates from the call
    // location. This is important for ((__always_inline, __nodebug__))
    // functions which must use caller location for all instructions in their
    // function body.

    // Don't update static allocas, as they may get moved later.
    if (auto *AI = dyn_cast<AllocaInst>(&I))
      if (allocaWouldBeStaticInEntry(AI))
        return;

    // Do not force a debug loc for pseudo probes, since they do not need to
    // be debuggable, and also they are expected to have a zero/null dwarf
    // discriminator at this point which could be violated otherwise.
    if (isa<PseudoProbeInst>(I))
      return;

    I.setDebugLoc(isa<CallBase>(I) ? TheCallDLForInlinedCall : TheCallDL);
  };

  // Helper-util for updating debug-info records attached to instructions.
  auto UpdateDVR = [&](DbgRecord *DVR) {
    assert(DVR->getDebugLoc() && "Debug Value must have debug loc");
    if (NoInlineLineTables) {
      DVR->setDebugLoc(TheCallDL);
      return;
    }
    DebugLoc DL = DVR->getDebugLoc();
    DebugLoc IDL = inlineDebugLoc(DL, InlinedAtNode,
                                  DVR->getMarker()->getParent()->getContext(),
                                  IANodes, InlineLocs);
    DVR->setDebugLoc(IDL);
  };

  // Iterate over all instructions, updating metadata and debug-info records.
  for (; FI != Fn->end(); ++FI) {
    for (Instruction &I : *FI) {
      UpdateInst(I);
      for (DbgRecord &DVR : I.getDbgRecordRange()) {
        UpdateDVR(&DVR);
      }
    }

    // Remove debug info records if we're not keeping inline info.
    if (NoInlineLineTables) {
      BasicBlock::iterator BI = FI->begin();
      while (BI != FI->end()) {
        BI->dropDbgRecords();
        ++BI;
      }
    }
  }
}

#undef DEBUG_TYPE
#define DEBUG_TYPE "assignment-tracking"
/// Find Alloca and linked DbgAssignIntrinsic for locals escaped by \p CB.
static at::StorageToVarsMap collectEscapedLocals(const DataLayout &DL,
                                                 const CallBase &CB) {
  at::StorageToVarsMap EscapedLocals;
  SmallPtrSet<const Value *, 4> SeenBases;

  LLVM_DEBUG(
      errs() << "# Finding caller local variables escaped by callee\n");
  for (const Value *Arg : CB.args()) {
    LLVM_DEBUG(errs() << "INSPECT: " << *Arg << "\n");
    if (!Arg->getType()->isPointerTy()) {
      LLVM_DEBUG(errs() << " | SKIP: Not a pointer\n");
      continue;
    }

    const Instruction *I = dyn_cast<Instruction>(Arg);
    if (!I) {
      LLVM_DEBUG(errs() << " | SKIP: Not result of instruction\n");
      continue;
    }

    // Walk back to the base storage.
    assert(Arg->getType()->isPtrOrPtrVectorTy());
    APInt TmpOffset(DL.getIndexTypeSizeInBits(Arg->getType()), 0, false);
    const AllocaInst *Base = dyn_cast<AllocaInst>(
        Arg->stripAndAccumulateConstantOffsets(DL, TmpOffset, true));
    if (!Base) {
      LLVM_DEBUG(errs() << " | SKIP: Couldn't walk back to base storage\n");
      continue;
    }

    assert(Base);
    LLVM_DEBUG(errs() << " | BASE: " << *Base << "\n");
    // We only need to process each base address once - skip any duplicates.
    if (!SeenBases.insert(Base).second)
      continue;

    // Find all local variables associated with the backing storage.
    auto CollectAssignsForStorage = [&](DbgVariableRecord *DbgAssign) {
      // Skip variables from inlined functions - they are not local variables.
      if (DbgAssign->getDebugLoc().getInlinedAt())
        return;
      LLVM_DEBUG(errs() << " > DEF : " << *DbgAssign << "\n");
      EscapedLocals[Base].insert(at::VarRecord(DbgAssign));
    };
    for_each(at::getDVRAssignmentMarkers(Base), CollectAssignsForStorage);
  }
  return EscapedLocals;
}

static void trackInlinedStores(Function::iterator Start, Function::iterator End,
                               const CallBase &CB) {
  LLVM_DEBUG(errs() << "trackInlinedStores into "
                    << Start->getParent()->getName() << " from "
                    << CB.getCalledFunction()->getName() << "\n");
  const DataLayout &DL = CB.getDataLayout();
  at::trackAssignments(Start, End, collectEscapedLocals(DL, CB), DL);
}

/// Update inlined instructions' DIAssignID metadata. We need to do this
/// otherwise a function inlined more than once into the same function
/// will cause DIAssignID to be shared by many instructions.
static void fixupAssignments(Function::iterator Start, Function::iterator End) {
  DenseMap<DIAssignID *, DIAssignID *> Map;
  // Loop over all the inlined instructions. If we find a DIAssignID
  // attachment or use, replace it with a new version.
  for (auto BBI = Start; BBI != End; ++BBI) {
    for (Instruction &I : *BBI)
      at::remapAssignID(Map, I);
  }
}
#undef DEBUG_TYPE
#define DEBUG_TYPE "inline-function"

/// Update the block frequencies of the caller after a callee has been inlined.
///
/// Each block cloned into the caller has its block frequency scaled by the
/// ratio of CallSiteFreq/CalleeEntryFreq. This ensures that the cloned copy of
/// callee's entry block gets the same frequency as the callsite block and the
/// relative frequencies of all cloned blocks remain the same after cloning.
static void updateCallerBFI(BasicBlock *CallSiteBlock,
                            const ValueToValueMapTy &VMap,
                            BlockFrequencyInfo *CallerBFI,
                            BlockFrequencyInfo *CalleeBFI,
                            const BasicBlock &CalleeEntryBlock) {
  SmallPtrSet<BasicBlock *, 16> ClonedBBs;
  for (auto Entry : VMap) {
    if (!isa<BasicBlock>(Entry.first) || !Entry.second)
      continue;
    auto *OrigBB = cast<BasicBlock>(Entry.first);
    auto *ClonedBB = cast<BasicBlock>(Entry.second);
    BlockFrequency Freq = CalleeBFI->getBlockFreq(OrigBB);
    if (!ClonedBBs.insert(ClonedBB).second) {
      // Multiple blocks in the callee might get mapped to one cloned block in
      // the caller since we prune the callee as we clone it. When that happens,
      // we want to use the maximum among the original blocks' frequencies.
      BlockFrequency NewFreq = CallerBFI->getBlockFreq(ClonedBB);
      if (NewFreq > Freq)
        Freq = NewFreq;
    }
    CallerBFI->setBlockFreq(ClonedBB, Freq);
  }
  BasicBlock *EntryClone = cast<BasicBlock>(VMap.lookup(&CalleeEntryBlock));
  CallerBFI->setBlockFreqAndScale(
      EntryClone, CallerBFI->getBlockFreq(CallSiteBlock), ClonedBBs);
}

/// Update the branch metadata for cloned call instructions.
static void updateCallProfile(Function *Callee, const ValueToValueMapTy &VMap,
                              const uint64_t &CalleeEntryCount,
                              const CallBase &TheCall, ProfileSummaryInfo *PSI,
                              BlockFrequencyInfo *CallerBFI) {
  if (CalleeEntryCount < 1)
    return;
  auto CallSiteCount =
      PSI ? PSI->getProfileCount(TheCall, CallerBFI) : std::nullopt;
  int64_t CallCount = std::min(CallSiteCount.value_or(0), CalleeEntryCount);
  updateProfileCallee(Callee, -CallCount, &VMap);
}

void llvm::updateProfileCallee(
    Function *Callee, int64_t EntryDelta,
    const ValueMap<const Value *, WeakTrackingVH> *VMap) {
  auto CalleeCount = Callee->getEntryCount();
  if (!CalleeCount)
    return;

  // Since CallSiteCount is an estimate, it could exceed the original callee
  // count and has to be set to 0 so guard against underflow.
  const uint64_t NewEntryCount =
      (EntryDelta < 0 && static_cast<uint64_t>(-EntryDelta) > *CalleeCount)
          ? 0
          : *CalleeCount + EntryDelta;

  auto updateVTableProfWeight = [](CallBase *CB, const uint64_t NewEntryCount,
                                   const uint64_t PriorEntryCount) {
    Instruction *VPtr = PGOIndirectCallVisitor::tryGetVTableInstruction(CB);
    if (VPtr)
      scaleProfData(*VPtr, NewEntryCount, PriorEntryCount);
  };

  // During inlining ?
  if (VMap) {
    uint64_t CloneEntryCount = *CalleeCount - NewEntryCount;
    for (auto Entry : *VMap) {
      if (isa<CallInst>(Entry.first))
        if (auto *CI = dyn_cast_or_null<CallInst>(Entry.second)) {
          CI->updateProfWeight(CloneEntryCount, *CalleeCount);
          updateVTableProfWeight(CI, CloneEntryCount, *CalleeCount);
        }

      if (isa<InvokeInst>(Entry.first))
        if (auto *II = dyn_cast_or_null<InvokeInst>(Entry.second)) {
          II->updateProfWeight(CloneEntryCount, *CalleeCount);
          updateVTableProfWeight(II, CloneEntryCount, *CalleeCount);
        }
    }
  }

  if (EntryDelta) {
    Callee->setEntryCount(NewEntryCount);

    for (BasicBlock &BB : *Callee)
      // No need to update the callsite if it is pruned during inlining.
      if (!VMap || VMap->count(&BB))
        for (Instruction &I : BB) {
          if (CallInst *CI = dyn_cast<CallInst>(&I)) {
            CI->updateProfWeight(NewEntryCount, *CalleeCount);
            updateVTableProfWeight(CI, NewEntryCount, *CalleeCount);
          }
          if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
            II->updateProfWeight(NewEntryCount, *CalleeCount);
            updateVTableProfWeight(II, NewEntryCount, *CalleeCount);
          }
        }
  }
}

/// An operand bundle "clang.arc.attachedcall" on a call indicates the call
/// result is implicitly consumed by a call to retainRV or claimRV immediately
/// after the call. This function inlines the retainRV/claimRV calls.
///
/// There are three cases to consider:
///
/// 1. If there is a call to autoreleaseRV that takes a pointer to the returned
///    object in the callee return block, the autoreleaseRV call and the
///    retainRV/claimRV call in the caller cancel out. If the call in the caller
///    is a claimRV call, a call to objc_release is emitted.
///
/// 2. If there is a call in the callee return block that doesn't have operand
///    bundle "clang.arc.attachedcall", the operand bundle on the original call
///    is transferred to the call in the callee.
///
/// 3. Otherwise, a call to objc_retain is inserted if the call in the caller is
///    a retainRV call.
static void
inlineRetainOrClaimRVCalls(CallBase &CB, objcarc::ARCInstKind RVCallKind,
                           const SmallVectorImpl<ReturnInst *> &Returns) {
  assert(objcarc::isRetainOrClaimRV(RVCallKind) && "unexpected ARC function");
  bool IsRetainRV = RVCallKind == objcarc::ARCInstKind::RetainRV,
       IsUnsafeClaimRV = !IsRetainRV;

  for (auto *RI : Returns) {
    Value *RetOpnd = objcarc::GetRCIdentityRoot(RI->getOperand(0));
    bool InsertRetainCall = IsRetainRV;
    IRBuilder<> Builder(*RI->getModule());

    // Walk backwards through the basic block looking for either a matching
    // autoreleaseRV call or an unannotated call.
    auto InstRange = llvm::make_range(++(RI->getIterator().getReverse()),
                                      RI->getParent()->rend());
    for (Instruction &I : llvm::make_early_inc_range(InstRange)) {
      // Ignore casts.
      if (isa<CastInst>(I))
        continue;

      if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
        if (II->getIntrinsicID() != Intrinsic::objc_autoreleaseReturnValue ||
            !II->use_empty() ||
            objcarc::GetRCIdentityRoot(II->getOperand(0)) != RetOpnd)
          break;

        // If we've found a matching authoreleaseRV call:
        // - If claimRV is attached to the call, insert a call to objc_release
        //   and erase the autoreleaseRV call.
        // - If retainRV is attached to the call, just erase the autoreleaseRV
        //   call.
        if (IsUnsafeClaimRV) {
          Builder.SetInsertPoint(II);
          Builder.CreateIntrinsic(Intrinsic::objc_release, RetOpnd);
        }
        II->eraseFromParent();
        InsertRetainCall = false;
        break;
      }

      auto *CI = dyn_cast<CallInst>(&I);

      if (!CI)
        break;

      if (objcarc::GetRCIdentityRoot(CI) != RetOpnd ||
          objcarc::hasAttachedCallOpBundle(CI))
        break;

      // If we've found an unannotated call that defines RetOpnd, add a
      // "clang.arc.attachedcall" operand bundle.
      Value *BundleArgs[] = {*objcarc::getAttachedARCFunction(&CB)};
      OperandBundleDef OB("clang.arc.attachedcall", BundleArgs);
      auto *NewCall = CallBase::addOperandBundle(
          CI, LLVMContext::OB_clang_arc_attachedcall, OB, CI->getIterator());
      NewCall->copyMetadata(*CI);
      CI->replaceAllUsesWith(NewCall);
      CI->eraseFromParent();
      InsertRetainCall = false;
      break;
    }

    if (InsertRetainCall) {
      // The retainRV is attached to the call and we've failed to find a
      // matching autoreleaseRV or an annotated call in the callee. Emit a call
      // to objc_retain.
      Builder.SetInsertPoint(RI);
      Builder.CreateIntrinsic(Intrinsic::objc_retain, RetOpnd);
    }
  }
}

// In contextual profiling, when an inline succeeds, we want to remap the
// indices of the callee into the index space of the caller. We can't just leave
// them as-is because the same callee may appear in other places in this caller
// (other callsites), and its (callee's) counters and sub-contextual profile
// tree would be potentially different.
// Not all BBs of the callee may survive the opportunistic DCE InlineFunction
// does (same goes for callsites in the callee).
// We will return a pair of vectors, one for basic block IDs and one for
// callsites. For such a vector V, V[Idx] will be -1 if the callee
// instrumentation with index Idx did not survive inlining, and a new value
// otherwise.
// This function will update the caller's instrumentation intrinsics
// accordingly, mapping indices as described above. We also replace the "name"
// operand because we use it to distinguish between "own" instrumentation and
// "from callee" instrumentation when performing the traversal of the CFG of the
// caller. We traverse depth-first from the callsite's BB and up to the point we
// hit BBs owned by the caller.
// The return values will be then used to update the contextual
// profile. Note: we only update the "name" and "index" operands in the
// instrumentation intrinsics, we leave the hash and total nr of indices as-is,
// it's not worth updating those.
static std::pair<std::vector<int64_t>, std::vector<int64_t>>
remapIndices(Function &Caller, BasicBlock *StartBB,
             PGOContextualProfile &CtxProf, uint32_t CalleeCounters,
             uint32_t CalleeCallsites) {
  // We'll allocate a new ID to imported callsite counters and callsites. We're
  // using -1 to indicate a counter we delete. Most likely the entry ID, for
  // example, will be deleted - we don't want 2 IDs in the same BB, and the
  // entry would have been cloned in the callsite's old BB.
  std::vector<int64_t> CalleeCounterMap;
  std::vector<int64_t> CalleeCallsiteMap;
  CalleeCounterMap.resize(CalleeCounters, -1);
  CalleeCallsiteMap.resize(CalleeCallsites, -1);

  auto RewriteInstrIfNeeded = [&](InstrProfIncrementInst &Ins) -> bool {
    if (Ins.getNameValue() == &Caller)
      return false;
    const auto OldID = static_cast<uint32_t>(Ins.getIndex()->getZExtValue());
    if (CalleeCounterMap[OldID] == -1)
      CalleeCounterMap[OldID] = CtxProf.allocateNextCounterIndex(Caller);
    const auto NewID = static_cast<uint32_t>(CalleeCounterMap[OldID]);

    Ins.setNameValue(&Caller);
    Ins.setIndex(NewID);
    return true;
  };

  auto RewriteCallsiteInsIfNeeded = [&](InstrProfCallsite &Ins) -> bool {
    if (Ins.getNameValue() == &Caller)
      return false;
    const auto OldID = static_cast<uint32_t>(Ins.getIndex()->getZExtValue());
    if (CalleeCallsiteMap[OldID] == -1)
      CalleeCallsiteMap[OldID] = CtxProf.allocateNextCallsiteIndex(Caller);
    const auto NewID = static_cast<uint32_t>(CalleeCallsiteMap[OldID]);

    Ins.setNameValue(&Caller);
    Ins.setIndex(NewID);
    return true;
  };

  std::deque<BasicBlock *> Worklist;
  DenseSet<const BasicBlock *> Seen;
  // We will traverse the BBs starting from the callsite BB. The callsite BB
  // will have at least a BB ID - maybe its own, and in any case the one coming
  // from the cloned function's entry BB. The other BBs we'll start seeing from
  // there on may or may not have BB IDs. BBs with IDs belonging to our caller
  // are definitely not coming from the imported function and form a boundary
  // past which we don't need to traverse anymore. BBs may have no
  // instrumentation (because we originally inserted instrumentation as per
  // MST), in which case we'll traverse past them. An invariant we'll keep is
  // that a BB will have at most 1 BB ID. For example, in the callsite BB, we
  // will delete the callee BB's instrumentation. This doesn't result in
  // information loss: the entry BB of the callee will have the same count as
  // the callsite's BB. At the end of this traversal, all the callee's
  // instrumentation would be mapped into the caller's instrumentation index
  // space. Some of the callee's counters may be deleted (as mentioned, this
  // should result in no loss of information).
  Worklist.push_back(StartBB);
  while (!Worklist.empty()) {
    auto *BB = Worklist.front();
    Worklist.pop_front();
    bool Changed = false;
    auto *BBID = CtxProfAnalysis::getBBInstrumentation(*BB);
    if (BBID) {
      Changed |= RewriteInstrIfNeeded(*BBID);
      // this may be the entryblock from the inlined callee, coming into a BB
      // that didn't have instrumentation because of MST decisions. Let's make
      // sure it's placed accordingly. This is a noop elsewhere.
      BBID->moveBefore(BB->getFirstInsertionPt());
    }
    for (auto &I : llvm::make_early_inc_range(*BB)) {
      if (auto *Inc = dyn_cast<InstrProfIncrementInst>(&I)) {
        if (isa<InstrProfIncrementInstStep>(Inc)) {
          // Step instrumentation is used for select instructions. Inlining may
          // have propagated a constant resulting in the condition of the select
          // being resolved, case in which function cloning resolves the value
          // of the select, and elides the select instruction. If that is the
          // case, the step parameter of the instrumentation will reflect that.
          // We can delete the instrumentation in that case.
          if (isa<Constant>(Inc->getStep())) {
            assert(!Inc->getNextNode() || !isa<SelectInst>(Inc->getNextNode()));
            Inc->eraseFromParent();
          } else {
            assert(isa_and_nonnull<SelectInst>(Inc->getNextNode()));
            RewriteInstrIfNeeded(*Inc);
          }
        } else if (Inc != BBID) {
          // If we're here it means that the BB had more than 1 IDs, presumably
          // some coming from the callee. We "made up our mind" to keep the
          // first one (which may or may not have been originally the caller's).
          // All the others are superfluous and we delete them.
          Inc->eraseFromParent();
          Changed = true;
        }
      } else if (auto *CS = dyn_cast<InstrProfCallsite>(&I)) {
        Changed |= RewriteCallsiteInsIfNeeded(*CS);
      }
    }
    if (!BBID || Changed)
      for (auto *Succ : successors(BB))
        if (Seen.insert(Succ).second)
          Worklist.push_back(Succ);
  }

  assert(!llvm::is_contained(CalleeCounterMap, 0) &&
         "Counter index mapping should be either to -1 or to non-zero index, "
         "because the 0 "
         "index corresponds to the entry BB of the caller");
  assert(!llvm::is_contained(CalleeCallsiteMap, 0) &&
         "Callsite index mapping should be either to -1 or to non-zero index, "
         "because there should have been at least a callsite - the inlined one "
         "- which would have had a 0 index.");

  return {std::move(CalleeCounterMap), std::move(CalleeCallsiteMap)};
}

// Inline. If successful, update the contextual profile (if a valid one is
// given).
// The contextual profile data is organized in trees, as follows:
//  - each node corresponds to a function
//  - the root of each tree corresponds to an "entrypoint" - e.g.
//    RPC handler for server side
//  - the path from the root to a node is a particular call path
//  - the counters stored in a node are counter values observed in that
//    particular call path ("context")
//  - the edges between nodes are annotated with callsite IDs.
//
// Updating the contextual profile after an inlining means, at a high level,
// copying over the data of the callee, **intentionally without any value
// scaling**, and copying over the callees of the inlined callee.
llvm::InlineResult
llvm::InlineFunction(CallBase &CB, InlineFunctionInfo &IFI,
                     PGOContextualProfile &CtxProf, bool MergeAttributes,
                     AAResults *CalleeAAR, bool InsertLifetime,
                     bool TrackInlineHistory, Function *ForwardVarArgsTo,
                     OptimizationRemarkEmitter *ORE) {
  if (!CtxProf.isInSpecializedModule())
    return InlineFunction(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
                          TrackInlineHistory, ForwardVarArgsTo, ORE);

  auto &Caller = *CB.getCaller();
  auto &Callee = *CB.getCalledFunction();
  auto *StartBB = CB.getParent();

  // Get some preliminary data about the callsite before it might get inlined.
  // Inlining shouldn't delete the callee, but it's cleaner (and low-cost) to
  // get this data upfront and rely less on InlineFunction's behavior.
  const auto CalleeGUID = Callee.getGUID();
  auto *CallsiteIDIns = CtxProfAnalysis::getCallsiteInstrumentation(CB);
  const auto CallsiteID =
      static_cast<uint32_t>(CallsiteIDIns->getIndex()->getZExtValue());

  const auto NumCalleeCounters = CtxProf.getNumCounters(Callee);
  const auto NumCalleeCallsites = CtxProf.getNumCallsites(Callee);

  auto Ret = InlineFunction(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
                            TrackInlineHistory, ForwardVarArgsTo, ORE);
  if (!Ret.isSuccess())
    return Ret;

  // Inlining succeeded, we don't need the instrumentation of the inlined
  // callsite.
  CallsiteIDIns->eraseFromParent();

  // Assinging Maps and then capturing references into it in the lambda because
  // captured structured bindings are a C++20 extension. We do also need a
  // capture here, though.
  const auto IndicesMaps = remapIndices(Caller, StartBB, CtxProf,
                                        NumCalleeCounters, NumCalleeCallsites);
  const uint32_t NewCountersSize = CtxProf.getNumCounters(Caller);

  auto Updater = [&](PGOCtxProfContext &Ctx) {
    assert(Ctx.guid() == Caller.getGUID());
    const auto &[CalleeCounterMap, CalleeCallsiteMap] = IndicesMaps;
    assert(
        (Ctx.counters().size() +
             llvm::count_if(CalleeCounterMap, [](auto V) { return V != -1; }) ==
         NewCountersSize) &&
        "The caller's counters size should have grown by the number of new "
        "distinct counters inherited from the inlined callee.");
    Ctx.resizeCounters(NewCountersSize);
    // If the callsite wasn't exercised in this context, the value of the
    // counters coming from it is 0 - which it is right now, after resizing them
    // - and so we're done.
    auto CSIt = Ctx.callsites().find(CallsiteID);
    if (CSIt == Ctx.callsites().end())
      return;
    auto CalleeCtxIt = CSIt->second.find(CalleeGUID);
    // The callsite was exercised, but not with this callee (so presumably this
    // is an indirect callsite). Again, we're done here.
    if (CalleeCtxIt == CSIt->second.end())
      return;

    // Let's pull in the counter values and the subcontexts coming from the
    // inlined callee.
    auto &CalleeCtx = CalleeCtxIt->second;
    assert(CalleeCtx.guid() == CalleeGUID);

    for (auto I = 0U; I < CalleeCtx.counters().size(); ++I) {
      const int64_t NewIndex = CalleeCounterMap[I];
      if (NewIndex >= 0) {
        assert(NewIndex != 0 && "counter index mapping shouldn't happen to a 0 "
                                "index, that's the caller's entry BB");
        Ctx.counters()[NewIndex] = CalleeCtx.counters()[I];
      }
    }
    for (auto &[I, OtherSet] : CalleeCtx.callsites()) {
      const int64_t NewCSIdx = CalleeCallsiteMap[I];
      if (NewCSIdx >= 0) {
        assert(NewCSIdx != 0 &&
               "callsite index mapping shouldn't happen to a 0 index, the "
               "caller must've had at least one callsite (with such an index)");
        Ctx.ingestAllContexts(NewCSIdx, std::move(OtherSet));
      }
    }
    // We know the traversal is preorder, so it wouldn't have yet looked at the
    // sub-contexts of this context that it's currently visiting. Meaning, the
    // erase below invalidates no iterators.
    auto Deleted = Ctx.callsites().erase(CallsiteID);
    assert(Deleted);
    (void)Deleted;
  };
  CtxProf.update(Updater, Caller);
  return Ret;
}

llvm::InlineResult llvm::CanInlineCallSite(const CallBase &CB,
                                           InlineFunctionInfo &IFI) {
  assert(CB.getParent() && CB.getFunction() && "Instruction not in function!");

  // FIXME: we don't inline callbr yet.
  if (isa<CallBrInst>(CB))
    return InlineResult::failure("We don't inline callbr yet.");

  // If IFI has any state in it, zap it before we fill it in.
  IFI.reset();

  Function *CalledFunc = CB.getCalledFunction();
  if (!CalledFunc ||               // Can't inline external function or indirect
      CalledFunc->isDeclaration()) // call!
    return InlineResult::failure("external or indirect");

  // Don't inline if we've already inlined this callee through this call site
  // before to prevent infinite inlining through mutually recursive functions.
  if (MDNode *InlineHistory = CB.getMetadata(LLVMContext::MD_inline_history)) {
    for (const auto &Op : InlineHistory->operands()) {
      if (auto *MD = dyn_cast_or_null<ValueAsMetadata>(Op)) {
        if (MD->getValue() == CalledFunc) {
          return InlineResult::failure("inline history");
        }
      }
    }
  }

  // The inliner does not know how to inline through calls with operand bundles
  // in general ...
  if (CB.hasOperandBundles()) {
    for (int i = 0, e = CB.getNumOperandBundles(); i != e; ++i) {
      auto OBUse = CB.getOperandBundleAt(i);
      uint32_t Tag = OBUse.getTagID();
      // ... but it knows how to inline through "deopt" operand bundles ...
      if (Tag == LLVMContext::OB_deopt)
        continue;
      // ... and "funclet" operand bundles.
      if (Tag == LLVMContext::OB_funclet)
        continue;
      if (Tag == LLVMContext::OB_clang_arc_attachedcall)
        continue;
      if (Tag == LLVMContext::OB_kcfi)
        continue;
      if (Tag == LLVMContext::OB_convergencectrl) {
        IFI.ConvergenceControlToken = OBUse.Inputs[0].get();
        continue;
      }

      return InlineResult::failure("unsupported operand bundle");
    }
  }

  // FIXME: The check below is redundant and incomplete. According to spec, if a
  // convergent call is missing a token, then the caller is using uncontrolled
  // convergence. If the callee has an entry intrinsic, then the callee is using
  // controlled convergence, and the call cannot be inlined. A proper
  // implemenation of this check requires a whole new analysis that identifies
  // convergence in every function. For now, we skip that and just do this one
  // cursory check. The underlying assumption is that in a compiler flow that
  // fully implements convergence control tokens, there is no mixing of
  // controlled and uncontrolled convergent operations in the whole program.
  if (CB.isConvergent()) {
    if (!IFI.ConvergenceControlToken &&
        getConvergenceEntry(CalledFunc->getEntryBlock())) {
      return InlineResult::failure(
          "convergent call needs convergencectrl operand");
    }
  }

  const BasicBlock *OrigBB = CB.getParent();
  const Function *Caller = OrigBB->getParent();

  // GC poses two hazards to inlining, which only occur when the callee has GC:
  //  1. If the caller has no GC, then the callee's GC must be propagated to the
  //     caller.
  //  2. If the caller has a differing GC, it is invalid to inline.
  if (CalledFunc->hasGC()) {
    if (Caller->hasGC() && CalledFunc->getGC() != Caller->getGC())
      return InlineResult::failure("incompatible GC");
  }

  // Get the personality function from the callee if it contains a landing pad.
  Constant *CalledPersonality =
      CalledFunc->hasPersonalityFn()
          ? CalledFunc->getPersonalityFn()->stripPointerCasts()
          : nullptr;

  // Find the personality function used by the landing pads of the caller. If it
  // exists, then check to see that it matches the personality function used in
  // the callee.
  Constant *CallerPersonality =
      Caller->hasPersonalityFn()
          ? Caller->getPersonalityFn()->stripPointerCasts()
          : nullptr;
  if (CalledPersonality) {
    // If the personality functions match, then we can perform the
    // inlining. Otherwise, we can't inline.
    // TODO: This isn't 100% true. Some personality functions are proper
    //       supersets of others and can be used in place of the other.
    if (CallerPersonality && CalledPersonality != CallerPersonality)
      return InlineResult::failure("incompatible personality");
  }

  // We need to figure out which funclet the callsite was in so that we may
  // properly nest the callee.
  if (CallerPersonality) {
    EHPersonality Personality = classifyEHPersonality(CallerPersonality);
    if (isScopedEHPersonality(Personality)) {
      std::optional<OperandBundleUse> ParentFunclet =
          CB.getOperandBundle(LLVMContext::OB_funclet);
      if (ParentFunclet)
        IFI.CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());

      // OK, the inlining site is legal.  What about the target function?

      if (IFI.CallSiteEHPad) {
        if (Personality == EHPersonality::MSVC_CXX) {
          // The MSVC personality cannot tolerate catches getting inlined into
          // cleanup funclets.
          if (isa<CleanupPadInst>(IFI.CallSiteEHPad)) {
            // Ok, the call site is within a cleanuppad.  Let's check the callee
            // for catchpads.
            for (const BasicBlock &CalledBB : *CalledFunc) {
              if (isa<CatchSwitchInst>(CalledBB.getFirstNonPHIIt()))
                return InlineResult::failure("catch in cleanup funclet");
            }
          }
        } else if (isAsynchronousEHPersonality(Personality)) {
          // SEH is even less tolerant, there may not be any sort of exceptional
          // funclet in the callee.
          for (const BasicBlock &CalledBB : *CalledFunc) {
            if (CalledBB.isEHPad())
              return InlineResult::failure("SEH in cleanup funclet");
          }
        }
      }
    }
  }

  return InlineResult::success();
}

/// This function inlines the called function into the basic block of the
/// caller. This returns false if it is not possible to inline this call.
/// The program is still in a well defined state if this occurs though.
///
/// Note that this only does one level of inlining.  For example, if the
/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now
/// exists in the instruction stream.  Similarly this will inline a recursive
/// function by one level.
void llvm::InlineFunctionImpl(CallBase &CB, InlineFunctionInfo &IFI,
                              bool MergeAttributes, AAResults *CalleeAAR,
                              bool InsertLifetime, bool TrackInlineHistory,
                              Function *ForwardVarArgsTo,
                              OptimizationRemarkEmitter *ORE) {
  BasicBlock *OrigBB = CB.getParent();
  Function *Caller = OrigBB->getParent();
  Function *CalledFunc = CB.getCalledFunction();
  assert(CalledFunc && !CalledFunc->isDeclaration() &&
         "CanInlineCallSite should have verified direct call to definition");

  // Determine if we are dealing with a call in an EHPad which does not unwind
  // to caller.
  bool EHPadForCallUnwindsLocally = false;
  if (IFI.CallSiteEHPad && isa<CallInst>(CB)) {
    UnwindDestMemoTy FuncletUnwindMap;
    Value *CallSiteUnwindDestToken =
        getUnwindDestToken(IFI.CallSiteEHPad, FuncletUnwindMap);

    EHPadForCallUnwindsLocally =
        CallSiteUnwindDestToken &&
        !isa<ConstantTokenNone>(CallSiteUnwindDestToken);
  }

  // Get an iterator to the last basic block in the function, which will have
  // the new function inlined after it.
  Function::iterator LastBlock = --Caller->end();

  // Make sure to capture all of the return instructions from the cloned
  // function.
  SmallVector<ReturnInst*, 8> Returns;
  ClonedCodeInfo InlinedFunctionInfo;
  Function::iterator FirstNewBlock;

  // GC poses two hazards to inlining, which only occur when the callee has GC:
  //  1. If the caller has no GC, then the callee's GC must be propagated to the
  //     caller.
  //  2. If the caller has a differing GC, it is invalid to inline.
  if (CalledFunc->hasGC()) {
    if (!Caller->hasGC())
      Caller->setGC(CalledFunc->getGC());
    else {
      assert(CalledFunc->getGC() == Caller->getGC() &&
             "CanInlineCallSite should have verified compatible GCs");
    }
  }

  if (CalledFunc->hasPersonalityFn()) {
    Constant *CalledPersonality =
        CalledFunc->getPersonalityFn()->stripPointerCasts();
    if (!Caller->hasPersonalityFn()) {
      Caller->setPersonalityFn(CalledPersonality);
    } else
      assert(Caller->getPersonalityFn()->stripPointerCasts() ==
                 CalledPersonality &&
             "CanInlineCallSite should have verified compatible personality");
  }

  { // Scope to destroy VMap after cloning.
    ValueToValueMapTy VMap;
    struct ByValInit {
      Value *Dst;
      Value *Src;
      MaybeAlign SrcAlign;
      Type *Ty;
    };
    // Keep a list of tuples (dst, src, src_align) to emit byval
    // initializations. Src Alignment is only available though the callbase,
    // therefore has to be saved.
    SmallVector<ByValInit, 4> ByValInits;

    // When inlining a function that contains noalias scope metadata,
    // this metadata needs to be cloned so that the inlined blocks
    // have different "unique scopes" at every call site.
    // Track the metadata that must be cloned. Do this before other changes to
    // the function, so that we do not get in trouble when inlining caller ==
    // callee.
    ScopedAliasMetadataDeepCloner SAMetadataCloner(CB.getCalledFunction());

    auto &DL = Caller->getDataLayout();

    // Calculate the vector of arguments to pass into the function cloner, which
    // matches up the formal to the actual argument values.
    auto AI = CB.arg_begin();
    unsigned ArgNo = 0;
    for (Function::arg_iterator I = CalledFunc->arg_begin(),
         E = CalledFunc->arg_end(); I != E; ++I, ++AI, ++ArgNo) {
      Value *ActualArg = *AI;

      // When byval arguments actually inlined, we need to make the copy implied
      // by them explicit.  However, we don't do this if the callee is readonly
      // or readnone, because the copy would be unneeded: the callee doesn't
      // modify the struct.
      if (CB.isByValArgument(ArgNo)) {
        ActualArg = HandleByValArgument(CB.getParamByValType(ArgNo), ActualArg,
                                        &CB, CalledFunc, IFI,
                                        CalledFunc->getParamAlign(ArgNo));
        if (ActualArg != *AI)
          ByValInits.push_back({ActualArg, (Value *)*AI,
                                CB.getParamAlign(ArgNo),
                                CB.getParamByValType(ArgNo)});
      }

      VMap[&*I] = ActualArg;
    }

    // TODO: Remove this when users have been updated to the assume bundles.
    // Add alignment assumptions if necessary. We do this before the inlined
    // instructions are actually cloned into the caller so that we can easily
    // check what will be known at the start of the inlined code.
    AddAlignmentAssumptions(CB, IFI);

    AssumptionCache *AC =
        IFI.GetAssumptionCache ? &IFI.GetAssumptionCache(*Caller) : nullptr;

    /// Preserve all attributes on of the call and its parameters.
    salvageKnowledge(&CB, AC);

    // We want the inliner to prune the code as it copies.  We would LOVE to
    // have no dead or constant instructions leftover after inlining occurs
    // (which can happen, e.g., because an argument was constant), but we'll be
    // happy with whatever the cloner can do.
    CloneAndPruneFunctionInto(Caller, CalledFunc, VMap,
                              /*ModuleLevelChanges=*/false, Returns, ".i",
                              InlinedFunctionInfo);
    // Remember the first block that is newly cloned over.
    FirstNewBlock = LastBlock; ++FirstNewBlock;

    // Insert retainRV/clainRV runtime calls.
    objcarc::ARCInstKind RVCallKind = objcarc::getAttachedARCFunctionKind(&CB);
    if (RVCallKind != objcarc::ARCInstKind::None)
      inlineRetainOrClaimRVCalls(CB, RVCallKind, Returns);

    // Updated caller/callee profiles only when requested. For sample loader
    // inlining, the context-sensitive inlinee profile doesn't need to be
    // subtracted from callee profile, and the inlined clone also doesn't need
    // to be scaled based on call site count.
    if (IFI.UpdateProfile) {
      if (IFI.CallerBFI != nullptr && IFI.CalleeBFI != nullptr)
        // Update the BFI of blocks cloned into the caller.
        updateCallerBFI(OrigBB, VMap, IFI.CallerBFI, IFI.CalleeBFI,
                        CalledFunc->front());

      if (auto Profile = CalledFunc->getEntryCount())
        updateCallProfile(CalledFunc, VMap, *Profile, CB, IFI.PSI,
                          IFI.CallerBFI);
    }

    // Inject byval arguments initialization.
    for (ByValInit &Init : ByValInits)
      HandleByValArgumentInit(Init.Ty, Init.Dst, Init.Src, Init.SrcAlign,
                              Caller->getParent(), &*FirstNewBlock, IFI,
                              CalledFunc);

    std::optional<OperandBundleUse> ParentDeopt =
        CB.getOperandBundle(LLVMContext::OB_deopt);
    if (ParentDeopt) {
      SmallVector<OperandBundleDef, 2> OpDefs;

      for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
        CallBase *ICS = dyn_cast_or_null<CallBase>(VH);
        if (!ICS)
          continue; // instruction was DCE'd or RAUW'ed to undef

        OpDefs.clear();

        OpDefs.reserve(ICS->getNumOperandBundles());

        for (unsigned COBi = 0, COBe = ICS->getNumOperandBundles(); COBi < COBe;
             ++COBi) {
          auto ChildOB = ICS->getOperandBundleAt(COBi);
          if (ChildOB.getTagID() != LLVMContext::OB_deopt) {
            // If the inlined call has other operand bundles, let them be
            OpDefs.emplace_back(ChildOB);
            continue;
          }

          // It may be useful to separate this logic (of handling operand
          // bundles) out to a separate "policy" component if this gets crowded.
          // Prepend the parent's deoptimization continuation to the newly
          // inlined call's deoptimization continuation.
          std::vector<Value *> MergedDeoptArgs;
          MergedDeoptArgs.reserve(ParentDeopt->Inputs.size() +
                                  ChildOB.Inputs.size());

          llvm::append_range(MergedDeoptArgs, ParentDeopt->Inputs);
          llvm::append_range(MergedDeoptArgs, ChildOB.Inputs);

          OpDefs.emplace_back("deopt", std::move(MergedDeoptArgs));
        }

        Instruction *NewI = CallBase::Create(ICS, OpDefs, ICS->getIterator());

        // Note: the RAUW does the appropriate fixup in VMap, so we need to do
        // this even if the call returns void.
        ICS->replaceAllUsesWith(NewI);

        VH = nullptr;
        ICS->eraseFromParent();
      }
    }

    // For 'nodebug' functions, the associated DISubprogram is always null.
    // Conservatively avoid propagating the callsite debug location to
    // instructions inlined from a function whose DISubprogram is not null.
    fixupLineNumbers(Caller, FirstNewBlock, &CB,
                     CalledFunc->getSubprogram() != nullptr);

    if (isAssignmentTrackingEnabled(*Caller->getParent())) {
      // Interpret inlined stores to caller-local variables as assignments.
      trackInlinedStores(FirstNewBlock, Caller->end(), CB);

      // Update DIAssignID metadata attachments and uses so that they are
      // unique to this inlined instance.
      fixupAssignments(FirstNewBlock, Caller->end());
    }

    // Now clone the inlined noalias scope metadata.
    SAMetadataCloner.clone();
    SAMetadataCloner.remap(FirstNewBlock, Caller->end());

    // Add noalias metadata if necessary.
    AddAliasScopeMetadata(CB, VMap, DL, CalleeAAR, InlinedFunctionInfo);

    // Clone return attributes on the callsite into the calls within the inlined
    // function which feed into its return value.
    AddReturnAttributes(CB, VMap, InlinedFunctionInfo);

    // Clone attributes on the params of the callsite to calls within the
    // inlined function which use the same param.
    AddParamAndFnBasicAttributes(CB, VMap, InlinedFunctionInfo);

    propagateMemProfMetadata(
        CalledFunc, CB, InlinedFunctionInfo.ContainsMemProfMetadata, VMap, ORE);

    // Propagate metadata on the callsite if necessary.
    PropagateCallSiteMetadata(CB, FirstNewBlock, Caller->end());

    // Propagate an allocation wrapper's !alloc_token if necessary.
    propagateAllocTokenMetadata(CalledFunc, CB, VMap, InlinedFunctionInfo);

    // Propagate implicit ref metadata.
    if (CalledFunc->hasMetadata(LLVMContext::MD_implicit_ref)) {
      SmallVector<MDNode *> MDs;
      CalledFunc->getMetadata(LLVMContext::MD_implicit_ref, MDs);
      for (MDNode *MD : MDs) {
        Caller->addMetadata(LLVMContext::MD_implicit_ref, *MD);
      }
    }

    // Propagate inlined.from metadata for dontcall diagnostics.
    PropagateInlinedFromMetadata(CB, CalledFunc->getName(), Caller->getName(),
                                 FirstNewBlock, Caller->end());

    // Register any cloned assumptions.
    if (IFI.GetAssumptionCache)
      for (BasicBlock &NewBlock :
           make_range(FirstNewBlock->getIterator(), Caller->end()))
        for (Instruction &I : NewBlock)
          if (auto *II = dyn_cast<AssumeInst>(&I))
            IFI.GetAssumptionCache(*Caller).registerAssumption(II);
  }

  if (IFI.ConvergenceControlToken) {
    IntrinsicInst *IntrinsicCall = getConvergenceEntry(*FirstNewBlock);
    if (IntrinsicCall) {
      IntrinsicCall->replaceAllUsesWith(IFI.ConvergenceControlToken);
      IntrinsicCall->eraseFromParent();
    }
  }

  // If there are any alloca instructions in the block that used to be the entry
  // block for the callee, move them to the entry block of the caller.  First
  // calculate which instruction they should be inserted before.  We insert the
  // instructions at the end of the current alloca list.
  {
    BasicBlock::iterator InsertPoint = Caller->begin()->begin();
    for (BasicBlock::iterator I = FirstNewBlock->begin(),
         E = FirstNewBlock->end(); I != E; ) {
      AllocaInst *AI = dyn_cast<AllocaInst>(I++);
      if (!AI) continue;

      // If the alloca is now dead, remove it.  This often occurs due to code
      // specialization.
      if (AI->use_empty()) {
        AI->eraseFromParent();
        continue;
      }

      if (!allocaWouldBeStaticInEntry(AI))
        continue;

      // Keep track of the static allocas that we inline into the caller.
      IFI.StaticAllocas.push_back(AI);

      // Scan for the block of allocas that we can move over, and move them
      // all at once.
      while (isa<AllocaInst>(I) &&
             !cast<AllocaInst>(I)->use_empty() &&
             allocaWouldBeStaticInEntry(cast<AllocaInst>(I))) {
        IFI.StaticAllocas.push_back(cast<AllocaInst>(I));
        ++I;
      }

      // Transfer all of the allocas over in a block.  Using splice means
      // that the instructions aren't removed from the symbol table, then
      // reinserted.
      I.setTailBit(true);
      Caller->getEntryBlock().splice(InsertPoint, &*FirstNewBlock,
                                     AI->getIterator(), I);
    }
  }

  // If the call to the callee cannot throw, set the 'nounwind' flag on any
  // calls that we inline.
  bool MarkNoUnwind = CB.doesNotThrow();

  SmallVector<Value*,4> VarArgsToForward;
  SmallVector<AttributeSet, 4> VarArgsAttrs;
  for (unsigned i = CalledFunc->getFunctionType()->getNumParams();
       i < CB.arg_size(); i++) {
    VarArgsToForward.push_back(CB.getArgOperand(i));
    VarArgsAttrs.push_back(CB.getAttributes().getParamAttrs(i));
  }

  bool InlinedMustTailCalls = false, InlinedDeoptimizeCalls = false;
  if (InlinedFunctionInfo.ContainsCalls) {
    CallInst::TailCallKind CallSiteTailKind = CallInst::TCK_None;
    if (CallInst *CI = dyn_cast<CallInst>(&CB))
      CallSiteTailKind = CI->getTailCallKind();

    // For inlining purposes, the "notail" marker is the same as no marker.
    if (CallSiteTailKind == CallInst::TCK_NoTail)
      CallSiteTailKind = CallInst::TCK_None;

    for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E;
         ++BB) {
      for (Instruction &I : llvm::make_early_inc_range(*BB)) {
        CallInst *CI = dyn_cast<CallInst>(&I);
        if (!CI)
          continue;

        // Forward varargs from inlined call site to calls to the
        // ForwardVarArgsTo function, if requested, and to musttail calls.
        if (!VarArgsToForward.empty() &&
            ((ForwardVarArgsTo &&
              CI->getCalledFunction() == ForwardVarArgsTo) ||
             CI->isMustTailCall())) {
          // Collect attributes for non-vararg parameters.
          AttributeList Attrs = CI->getAttributes();
          SmallVector<AttributeSet, 8> ArgAttrs;
          if (!Attrs.isEmpty() || !VarArgsAttrs.empty()) {
            for (unsigned ArgNo = 0;
                 ArgNo < CI->getFunctionType()->getNumParams(); ++ArgNo)
              ArgAttrs.push_back(Attrs.getParamAttrs(ArgNo));
          }

          // Add VarArg attributes.
          ArgAttrs.append(VarArgsAttrs.begin(), VarArgsAttrs.end());
          Attrs = AttributeList::get(CI->getContext(), Attrs.getFnAttrs(),
                                     Attrs.getRetAttrs(), ArgAttrs);
          // Add VarArgs to existing parameters.
          SmallVector<Value *, 6> Params(CI->args());
          Params.append(VarArgsToForward.begin(), VarArgsToForward.end());
          CallInst *NewCI = CallInst::Create(
              CI->getFunctionType(), CI->getCalledOperand(), Params, "", CI->getIterator());
          NewCI->setDebugLoc(CI->getDebugLoc());
          NewCI->setAttributes(Attrs);
          NewCI->setCallingConv(CI->getCallingConv());
          CI->replaceAllUsesWith(NewCI);
          CI->eraseFromParent();
          CI = NewCI;
        }

        if (Function *F = CI->getCalledFunction())
          InlinedDeoptimizeCalls |=
              F->getIntrinsicID() == Intrinsic::experimental_deoptimize;

        // We need to reduce the strength of any inlined tail calls.  For
        // musttail, we have to avoid introducing potential unbounded stack
        // growth.  For example, if functions 'f' and 'g' are mutually recursive
        // with musttail, we can inline 'g' into 'f' so long as we preserve
        // musttail on the cloned call to 'f'.  If either the inlined call site
        // or the cloned call site is *not* musttail, the program already has
        // one frame of stack growth, so it's safe to remove musttail.  Here is
        // a table of example transformations:
        //
        //    f -> musttail g -> musttail f  ==>  f -> musttail f
        //    f -> musttail g ->     tail f  ==>  f ->     tail f
        //    f ->          g -> musttail f  ==>  f ->          f
        //    f ->          g ->     tail f  ==>  f ->          f
        //
        // Inlined notail calls should remain notail calls.
        CallInst::TailCallKind ChildTCK = CI->getTailCallKind();
        if (ChildTCK != CallInst::TCK_NoTail)
          ChildTCK = std::min(CallSiteTailKind, ChildTCK);
        CI->setTailCallKind(ChildTCK);
        InlinedMustTailCalls |= CI->isMustTailCall();

        // Call sites inlined through a 'nounwind' call site should be
        // 'nounwind' as well. However, avoid marking call sites explicitly
        // where possible. This helps expose more opportunities for CSE after
        // inlining, commonly when the callee is an intrinsic.
        if (MarkNoUnwind && !CI->doesNotThrow())
          CI->setDoesNotThrow();
      }
    }
  }

  // Leave lifetime markers for the static alloca's, scoping them to the
  // function we just inlined.
  // We need to insert lifetime intrinsics even at O0 to avoid invalid
  // access caused by multithreaded coroutines. The check
  // `Caller->isPresplitCoroutine()` would affect AlwaysInliner at O0 only.
  if ((InsertLifetime || Caller->isPresplitCoroutine()) &&
      !IFI.StaticAllocas.empty()) {
    IRBuilder<> builder(FirstNewBlock->begin());
    for (AllocaInst *AI : IFI.StaticAllocas) {
      // Don't mark swifterror allocas. They can't have bitcast uses.
      if (AI->isSwiftError())
        continue;

      // If the alloca is already scoped to something smaller than the whole
      // function then there's no need to add redundant, less accurate markers.
      if (hasLifetimeMarkers(AI))
        continue;

      std::optional<TypeSize> Size = AI->getAllocationSize(AI->getDataLayout());
      if (Size && Size->isZero())
        continue;

      builder.CreateLifetimeStart(AI);
      for (ReturnInst *RI : Returns) {
        // Don't insert llvm.lifetime.end calls between a musttail or deoptimize
        // call and a return.  The return kills all local allocas.
        if (InlinedMustTailCalls &&
            RI->getParent()->getTerminatingMustTailCall())
          continue;
        if (InlinedDeoptimizeCalls &&
            RI->getParent()->getTerminatingDeoptimizeCall())
          continue;
        IRBuilder<>(RI).CreateLifetimeEnd(AI);
      }
    }
  }

  // If the inlined code contained dynamic alloca instructions, wrap the inlined
  // code with llvm.stacksave/llvm.stackrestore intrinsics.
  if (InlinedFunctionInfo.ContainsDynamicAllocas) {
    // Insert the llvm.stacksave.
    CallInst *SavedPtr =
        IRBuilder<>(FirstNewBlock->begin()).CreateStackSave("savedstack");

    // Insert a call to llvm.stackrestore before any return instructions in the
    // inlined function.
    for (ReturnInst *RI : Returns) {
      // Don't insert llvm.stackrestore calls between a musttail or deoptimize
      // call and a return.  The return will restore the stack pointer.
      if (InlinedMustTailCalls && RI->getParent()->getTerminatingMustTailCall())
        continue;
      if (InlinedDeoptimizeCalls && RI->getParent()->getTerminatingDeoptimizeCall())
        continue;
      IRBuilder<>(RI).CreateStackRestore(SavedPtr);
    }
  }

  // If we are inlining for an invoke instruction, we must make sure to rewrite
  // any call instructions into invoke instructions.  This is sensitive to which
  // funclet pads were top-level in the inlinee, so must be done before
  // rewriting the "parent pad" links.
  if (auto *II = dyn_cast<InvokeInst>(&CB)) {
    BasicBlock *UnwindDest = II->getUnwindDest();
    BasicBlock::iterator FirstNonPHI = UnwindDest->getFirstNonPHIIt();
    if (isa<LandingPadInst>(FirstNonPHI)) {
      HandleInlinedLandingPad(II, &*FirstNewBlock, InlinedFunctionInfo);
    } else {
      HandleInlinedEHPad(II, &*FirstNewBlock, InlinedFunctionInfo);
    }
  }

  // Update the lexical scopes of the new funclets and callsites.
  // Anything that had 'none' as its parent is now nested inside the callsite's
  // EHPad.
  if (IFI.CallSiteEHPad) {
    for (Function::iterator BB = FirstNewBlock->getIterator(),
                            E = Caller->end();
         BB != E; ++BB) {
      // Add bundle operands to inlined call sites.
      PropagateOperandBundles(BB, IFI.CallSiteEHPad);

      // It is problematic if the inlinee has a cleanupret which unwinds to
      // caller and we inline it into a call site which doesn't unwind but into
      // an EH pad that does.  Such an edge must be dynamically unreachable.
      // As such, we replace the cleanupret with unreachable.
      if (auto *CleanupRet = dyn_cast<CleanupReturnInst>(BB->getTerminator()))
        if (CleanupRet->unwindsToCaller() && EHPadForCallUnwindsLocally)
          changeToUnreachable(CleanupRet);

      BasicBlock::iterator I = BB->getFirstNonPHIIt();
      if (!I->isEHPad())
        continue;

      if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(I)) {
        if (isa<ConstantTokenNone>(CatchSwitch->getParentPad()))
          CatchSwitch->setParentPad(IFI.CallSiteEHPad);
      } else {
        auto *FPI = cast<FuncletPadInst>(I);
        if (isa<ConstantTokenNone>(FPI->getParentPad()))
          FPI->setParentPad(IFI.CallSiteEHPad);
      }
    }
  }

  if (InlinedDeoptimizeCalls) {
    // We need to at least remove the deoptimizing returns from the Return set,
    // so that the control flow from those returns does not get merged into the
    // caller (but terminate it instead).  If the caller's return type does not
    // match the callee's return type, we also need to change the return type of
    // the intrinsic.
    if (Caller->getReturnType() == CB.getType()) {
      llvm::erase_if(Returns, [](ReturnInst *RI) {
        return RI->getParent()->getTerminatingDeoptimizeCall() != nullptr;
      });
    } else {
      SmallVector<ReturnInst *, 8> NormalReturns;
      Function *NewDeoptIntrinsic = Intrinsic::getOrInsertDeclaration(
          Caller->getParent(), Intrinsic::experimental_deoptimize,
          {Caller->getReturnType()});

      for (ReturnInst *RI : Returns) {
        CallInst *DeoptCall = RI->getParent()->getTerminatingDeoptimizeCall();
        if (!DeoptCall) {
          NormalReturns.push_back(RI);
          continue;
        }

        // The calling convention on the deoptimize call itself may be bogus,
        // since the code we're inlining may have undefined behavior (and may
        // never actually execute at runtime); but all
        // @llvm.experimental.deoptimize declarations have to have the same
        // calling convention in a well-formed module.
        auto CallingConv = DeoptCall->getCalledFunction()->getCallingConv();
        NewDeoptIntrinsic->setCallingConv(CallingConv);
        auto *CurBB = RI->getParent();
        RI->eraseFromParent();

        SmallVector<Value *, 4> CallArgs(DeoptCall->args());

        SmallVector<OperandBundleDef, 1> OpBundles;
        DeoptCall->getOperandBundlesAsDefs(OpBundles);
        auto DeoptAttributes = DeoptCall->getAttributes();
        DeoptCall->eraseFromParent();
        assert(!OpBundles.empty() &&
               "Expected at least the deopt operand bundle");

        IRBuilder<> Builder(CurBB);
        CallInst *NewDeoptCall =
            Builder.CreateCall(NewDeoptIntrinsic, CallArgs, OpBundles);
        NewDeoptCall->setCallingConv(CallingConv);
        NewDeoptCall->setAttributes(DeoptAttributes);
        if (NewDeoptCall->getType()->isVoidTy())
          Builder.CreateRetVoid();
        else
          Builder.CreateRet(NewDeoptCall);
        // Since the ret type is changed, remove the incompatible attributes.
        NewDeoptCall->removeRetAttrs(AttributeFuncs::typeIncompatible(
            NewDeoptCall->getType(), NewDeoptCall->getRetAttributes()));
      }

      // Leave behind the normal returns so we can merge control flow.
      std::swap(Returns, NormalReturns);
    }
  }

  // Handle any inlined musttail call sites.  In order for a new call site to be
  // musttail, the source of the clone and the inlined call site must have been
  // musttail.  Therefore it's safe to return without merging control into the
  // phi below.
  if (InlinedMustTailCalls) {
    // Handle the returns preceded by musttail calls separately.
    SmallVector<ReturnInst *, 8> NormalReturns;
    for (ReturnInst *RI : Returns) {
      CallInst *ReturnedMustTail =
          RI->getParent()->getTerminatingMustTailCall();
      if (!ReturnedMustTail)
        NormalReturns.push_back(RI);
    }

    // Leave behind the normal returns so we can merge control flow.
    std::swap(Returns, NormalReturns);
  }

  // Now that all of the transforms on the inlined code have taken place but
  // before we splice the inlined code into the CFG and lose track of which
  // blocks were actually inlined, collect the call sites. We only do this if
  // call graph updates weren't requested, as those provide value handle based
  // tracking of inlined call sites instead. Calls to intrinsics are not
  // collected because they are not inlineable.
  if (InlinedFunctionInfo.ContainsCalls) {
    // Otherwise just collect the raw call sites that were inlined.
    for (BasicBlock &NewBB :
         make_range(FirstNewBlock->getIterator(), Caller->end()))
      for (Instruction &I : NewBB)
        if (auto *CB = dyn_cast<CallBase>(&I))
          if (!(CB->getCalledFunction() &&
                CB->getCalledFunction()->isIntrinsic()))
            IFI.InlinedCallSites.push_back(CB);
  }

  for (CallBase *ICB : IFI.InlinedCallSites) {
    // We only track inline history if requested, or if the inlined call site
    // was originally an indirect call (it may have become a direct call
    // during inlining).
    if (TrackInlineHistory ||
        InlinedFunctionInfo.OriginallyIndirectCalls.contains(ICB)) {
      // !inline_history is {Callee, CB.inline_history, ICB.inline_history}.
      // Metadata nodes may be null if the referenced function was erased from
      // the module.
      SmallVector<Metadata *, 4> History;
      History.push_back(ValueAsMetadata::get(CalledFunc));
      if (MDNode *CBHistory = CB.getMetadata(LLVMContext::MD_inline_history)) {
        for (const auto &Op : CBHistory->operands()) {
          if (Op)
            History.push_back(Op.get());
        }
      }
      if (MDNode *CBHistory =
              ICB->getMetadata(LLVMContext::MD_inline_history)) {
        for (const auto &Op : CBHistory->operands()) {
          if (Op)
            History.push_back(Op.get());
        }
      }
      MDNode *NewHistory = MDNode::get(Caller->getContext(), History);
      ICB->setMetadata(LLVMContext::MD_inline_history, NewHistory);
    }
  }

  // If we cloned in _exactly one_ basic block, and if that block ends in a
  // return instruction, we splice the body of the inlined callee directly into
  // the calling basic block.
  if (Returns.size() == 1 && std::distance(FirstNewBlock, Caller->end()) == 1) {
    // Move all of the instructions right before the call.
    OrigBB->splice(CB.getIterator(), &*FirstNewBlock, FirstNewBlock->begin(),
                   FirstNewBlock->end());
    // Remove the cloned basic block.
    Caller->back().eraseFromParent();

    // If the call site was an invoke instruction, add a branch to the normal
    // destination.
    if (InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {
      UncondBrInst *NewBr =
          UncondBrInst::Create(II->getNormalDest(), CB.getIterator());
      NewBr->setDebugLoc(Returns[0]->getDebugLoc());
    }

    // If the return instruction returned a value, replace uses of the call with
    // uses of the returned value.
    if (!CB.use_empty()) {
      ReturnInst *R = Returns[0];
      if (&CB == R->getReturnValue())
        CB.replaceAllUsesWith(PoisonValue::get(CB.getType()));
      else
        CB.replaceAllUsesWith(R->getReturnValue());
    }
    // Since we are now done with the Call/Invoke, we can delete it.
    CB.eraseFromParent();

    // Since we are now done with the return instruction, delete it also.
    Returns[0]->eraseFromParent();

    if (MergeAttributes)
      AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);

    // We are now done with the inlining.
    return;
  }

  // Otherwise, we have the normal case, of more than one block to inline or
  // multiple return sites.

  // We want to clone the entire callee function into the hole between the
  // "starter" and "ender" blocks.  How we accomplish this depends on whether
  // this is an invoke instruction or a call instruction.
  BasicBlock *AfterCallBB;
  UncondBrInst *CreatedBranchToNormalDest = nullptr;
  if (InvokeInst *II = dyn_cast<InvokeInst>(&CB)) {

    // Add an unconditional branch to make this look like the CallInst case...
    CreatedBranchToNormalDest =
        UncondBrInst::Create(II->getNormalDest(), CB.getIterator());
    // We intend to replace this DebugLoc with another later.
    CreatedBranchToNormalDest->setDebugLoc(DebugLoc::getTemporary());

    // Split the basic block.  This guarantees that no PHI nodes will have to be
    // updated due to new incoming edges, and make the invoke case more
    // symmetric to the call case.
    AfterCallBB =
        OrigBB->splitBasicBlock(CreatedBranchToNormalDest->getIterator(),
                                CalledFunc->getName() + ".exit");

  } else { // It's a call
    // If this is a call instruction, we need to split the basic block that
    // the call lives in.
    //
    AfterCallBB = OrigBB->splitBasicBlock(CB.getIterator(),
                                          CalledFunc->getName() + ".exit");
  }

  if (IFI.CallerBFI) {
    // Copy original BB's block frequency to AfterCallBB
    IFI.CallerBFI->setBlockFreq(AfterCallBB,
                                IFI.CallerBFI->getBlockFreq(OrigBB));
  }

  // Change the branch that used to go to AfterCallBB to branch to the first
  // basic block of the inlined function.
  //
  UncondBrInst *Br = cast<UncondBrInst>(OrigBB->getTerminator());
  Br->setSuccessor(&*FirstNewBlock);

  // Now that the function is correct, make it a little bit nicer.  In
  // particular, move the basic blocks inserted from the end of the function
  // into the space made by splitting the source basic block.
  Caller->splice(AfterCallBB->getIterator(), Caller, FirstNewBlock,
                 Caller->end());

  // Handle all of the return instructions that we just cloned in, and eliminate
  // any users of the original call/invoke instruction.
  Type *RTy = CalledFunc->getReturnType();

  PHINode *PHI = nullptr;
  if (Returns.size() > 1) {
    // The PHI node should go at the front of the new basic block to merge all
    // possible incoming values.
    if (!CB.use_empty()) {
      PHI = PHINode::Create(RTy, Returns.size(), CB.getName());
      PHI->insertBefore(AfterCallBB->begin());
      // Anything that used the result of the function call should now use the
      // PHI node as their operand.
      CB.replaceAllUsesWith(PHI);
    }

    // Loop over all of the return instructions adding entries to the PHI node
    // as appropriate.
    if (PHI) {
      for (ReturnInst *RI : Returns) {
        assert(RI->getReturnValue()->getType() == PHI->getType() &&
               "Ret value not consistent in function!");
        PHI->addIncoming(RI->getReturnValue(), RI->getParent());
      }
    }

    // Add a branch to the merge points and remove return instructions.
    DebugLoc Loc;
    for (ReturnInst *RI : Returns) {
      UncondBrInst *BI = UncondBrInst::Create(AfterCallBB, RI->getIterator());
      Loc = RI->getDebugLoc();
      BI->setDebugLoc(Loc);
      RI->eraseFromParent();
    }
    // We need to set the debug location to *somewhere* inside the
    // inlined function. The line number may be nonsensical, but the
    // instruction will at least be associated with the right
    // function.
    if (CreatedBranchToNormalDest)
      CreatedBranchToNormalDest->setDebugLoc(Loc);
  } else if (!Returns.empty()) {
    // Otherwise, if there is exactly one return value, just replace anything
    // using the return value of the call with the computed value.
    if (!CB.use_empty()) {
      if (&CB == Returns[0]->getReturnValue())
        CB.replaceAllUsesWith(PoisonValue::get(CB.getType()));
      else
        CB.replaceAllUsesWith(Returns[0]->getReturnValue());
    }

    // Update PHI nodes that use the ReturnBB to use the AfterCallBB.
    BasicBlock *ReturnBB = Returns[0]->getParent();
    ReturnBB->replaceAllUsesWith(AfterCallBB);

    // Splice the code from the return block into the block that it will return
    // to, which contains the code that was after the call.
    AfterCallBB->splice(AfterCallBB->begin(), ReturnBB);

    if (CreatedBranchToNormalDest)
      CreatedBranchToNormalDest->setDebugLoc(Returns[0]->getDebugLoc());

    // Delete the return instruction now and empty ReturnBB now.
    Returns[0]->eraseFromParent();
    ReturnBB->eraseFromParent();
  } else if (!CB.use_empty()) {
    // In this case there are no returns to use, so there is no clear source
    // location for the "return".
    // FIXME: It may be correct to use the scope end line of the function here,
    // since this likely means we are falling out of the function.
    if (CreatedBranchToNormalDest)
      CreatedBranchToNormalDest->setDebugLoc(DebugLoc::getUnknown());
    // No returns, but something is using the return value of the call.  Just
    // nuke the result.
    CB.replaceAllUsesWith(PoisonValue::get(CB.getType()));
  }

  // Since we are now done with the Call/Invoke, we can delete it.
  CB.eraseFromParent();

  // If we inlined any musttail calls and the original return is now
  // unreachable, delete it.  It can only contain a ret.
  if (InlinedMustTailCalls && pred_empty(AfterCallBB))
    AfterCallBB->eraseFromParent();

  // We should always be able to fold the entry block of the function into the
  // single predecessor of the block...
  BasicBlock *CalleeEntry = Br->getSuccessor();

  // Splice the code entry block into calling block, right before the
  // unconditional branch.
  CalleeEntry->replaceAllUsesWith(OrigBB);  // Update PHI nodes
  OrigBB->splice(Br->getIterator(), CalleeEntry);

  // Remove the unconditional branch.
  Br->eraseFromParent();

  // Now we can remove the CalleeEntry block, which is now empty.
  CalleeEntry->eraseFromParent();

  // If we inserted a phi node, check to see if it has a single value (e.g. all
  // the entries are the same or undef).  If so, remove the PHI so it doesn't
  // block other optimizations.
  if (PHI) {
    AssumptionCache *AC =
        IFI.GetAssumptionCache ? &IFI.GetAssumptionCache(*Caller) : nullptr;
    auto &DL = Caller->getDataLayout();
    if (Value *V = simplifyInstruction(PHI, {DL, nullptr, nullptr, AC})) {
      PHI->replaceAllUsesWith(V);
      PHI->eraseFromParent();
    }
  }

  if (MergeAttributes)
    AttributeFuncs::mergeAttributesForInlining(*Caller, *CalledFunc);
}

llvm::InlineResult llvm::InlineFunction(
    CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes,
    AAResults *CalleeAAR, bool InsertLifetime, bool TrackInlineHistory,
    Function *ForwardVarArgsTo, OptimizationRemarkEmitter *ORE) {
  llvm::InlineResult Result = CanInlineCallSite(CB, IFI);
  if (Result.isSuccess()) {
    InlineFunctionImpl(CB, IFI, MergeAttributes, CalleeAAR, InsertLifetime,
                       TrackInlineHistory, ForwardVarArgsTo, ORE);
  }

  return Result;
}
