//===- CloneFunction.cpp - Clone a function into another function ---------===//
//
// 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 the CloneFunctionInto interface, which is used as the
// low-level function cloner.  This is used by the CloneFunction and function
// inliner to do the dirty work of copying the body of a function around.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/InstructionSimplify.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/AttributeMask.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <cstdint>
#include <map>
#include <optional>
using namespace llvm;

#define DEBUG_TYPE "clone-function"

STATISTIC(RemappedAtomMax, "Highest global NextAtomGroup (after mapping)");

void llvm::mapAtomInstance(const DebugLoc &DL, ValueToValueMapTy &VMap) {
  uint64_t CurGroup = DL->getAtomGroup();
  if (!CurGroup)
    return;

  // Try inserting a new entry. If there's already a mapping for this atom
  // then there's nothing to do.
  auto [It, Inserted] = VMap.AtomMap.insert({{DL.getInlinedAt(), CurGroup}, 0});
  if (!Inserted)
    return;

  // Map entry to a new atom group.
  uint64_t NewGroup = DL->getContext().incNextDILocationAtomGroup();
  assert(NewGroup > CurGroup && "Next should always be greater than current");
  It->second = NewGroup;

  RemappedAtomMax = std::max<uint64_t>(NewGroup, RemappedAtomMax);
}

static void collectDebugInfoFromInstructions(const Function &F,
                                             DebugInfoFinder &DIFinder) {
  const Module *M = F.getParent();
  if (!M)
    return;
  // Inspect instructions to process e.g. DILexicalBlocks of inlined functions
  for (const Instruction &I : instructions(F))
    DIFinder.processInstruction(*M, I);
}

// Create a predicate that matches the metadata that should be identity mapped
// during function cloning.
static MetadataPredicate
createIdentityMDPredicate(const Function &F, CloneFunctionChangeType Changes) {
  if (Changes >= CloneFunctionChangeType::DifferentModule)
    return [](const Metadata *MD) { return false; };

  DISubprogram *SPClonedWithinModule = F.getSubprogram();

  // Don't clone inlined subprograms.
  auto ShouldKeep = [SPClonedWithinModule](const DISubprogram *SP) -> bool {
    return SP != SPClonedWithinModule;
  };

  return [=](const Metadata *MD) {
    // Avoid cloning types, compile units, and (other) subprograms.
    if (isa<DICompileUnit>(MD) || isa<DIType>(MD))
      return true;

    if (auto *SP = dyn_cast<DISubprogram>(MD))
      return ShouldKeep(SP);

    // If a subprogram isn't going to be cloned skip its lexical blocks as well.
    if (auto *LScope = dyn_cast<DILocalScope>(MD))
      return ShouldKeep(LScope->getSubprogram());

    // Avoid cloning local variables of subprograms that won't be cloned.
    if (auto *DV = dyn_cast<DILocalVariable>(MD))
      if (auto *S = dyn_cast_or_null<DILocalScope>(DV->getScope()))
        return ShouldKeep(S->getSubprogram());

    return false;
  };
}

/// See comments in Cloning.h.
BasicBlock *llvm::CloneBasicBlock(const BasicBlock *BB, ValueToValueMapTy &VMap,
                                  const Twine &NameSuffix, Function *F,
                                  ClonedCodeInfo *CodeInfo, bool MapAtoms) {
  BasicBlock *NewBB = BasicBlock::Create(BB->getContext(), "", F);
  if (BB->hasName())
    NewBB->setName(BB->getName() + NameSuffix);

  bool hasCalls = false, hasDynamicAllocas = false, hasMemProfMetadata = false;

  // Loop over all instructions, and copy them over.
  for (const Instruction &I : *BB) {
    Instruction *NewInst = I.clone();
    if (I.hasName())
      NewInst->setName(I.getName() + NameSuffix);

    NewInst->insertBefore(*NewBB, NewBB->end());
    NewInst->cloneDebugInfoFrom(&I);

    VMap[&I] = NewInst; // Add instruction map to value.

    if (MapAtoms) {
      if (const DebugLoc &DL = NewInst->getDebugLoc())
        mapAtomInstance(DL.get(), VMap);
    }

    if (isa<CallInst>(I) && !I.isDebugOrPseudoInst()) {
      hasCalls = true;
      hasMemProfMetadata |= I.hasMetadata(LLVMContext::MD_memprof);
      hasMemProfMetadata |= I.hasMetadata(LLVMContext::MD_callsite);
    }
    if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
      if (!AI->isStaticAlloca()) {
        hasDynamicAllocas = true;
      }
    }
  }

  if (CodeInfo) {
    CodeInfo->ContainsCalls |= hasCalls;
    CodeInfo->ContainsMemProfMetadata |= hasMemProfMetadata;
    CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
  }
  return NewBB;
}

void llvm::CloneFunctionAttributesInto(Function *NewFunc,
                                       const Function *OldFunc,
                                       ValueToValueMapTy &VMap,
                                       bool ModuleLevelChanges,
                                       ValueMapTypeRemapper *TypeMapper,
                                       ValueMaterializer *Materializer) {
  // Copy all attributes other than those stored in Function's AttributeList
  // which holds e.g. parameters and return value attributes.
  AttributeList NewAttrs = NewFunc->getAttributes();
  NewFunc->copyAttributesFrom(OldFunc);
  NewFunc->setAttributes(NewAttrs);

  const RemapFlags FuncGlobalRefFlags =
      ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges;

  // Fix up the personality function that got copied over.
  if (OldFunc->hasPersonalityFn())
    NewFunc->setPersonalityFn(MapValue(OldFunc->getPersonalityFn(), VMap,
                                       FuncGlobalRefFlags, TypeMapper,
                                       Materializer));

  if (OldFunc->hasPrefixData()) {
    NewFunc->setPrefixData(MapValue(OldFunc->getPrefixData(), VMap,
                                    FuncGlobalRefFlags, TypeMapper,
                                    Materializer));
  }

  if (OldFunc->hasPrologueData()) {
    NewFunc->setPrologueData(MapValue(OldFunc->getPrologueData(), VMap,
                                      FuncGlobalRefFlags, TypeMapper,
                                      Materializer));
  }

  SmallVector<AttributeSet, 4> NewArgAttrs(NewFunc->arg_size());
  AttributeList OldAttrs = OldFunc->getAttributes();

  // Clone any argument attributes that are present in the VMap.
  for (const Argument &OldArg : OldFunc->args()) {
    if (Argument *NewArg = dyn_cast<Argument>(VMap[&OldArg])) {
      // Remap the parameter indices.
      NewArgAttrs[NewArg->getArgNo()] =
          OldAttrs.getParamAttrs(OldArg.getArgNo());
    }
  }

  NewFunc->setAttributes(
      AttributeList::get(NewFunc->getContext(), OldAttrs.getFnAttrs(),
                         OldAttrs.getRetAttrs(), NewArgAttrs));
}

void llvm::CloneFunctionMetadataInto(Function &NewFunc, const Function &OldFunc,
                                     ValueToValueMapTy &VMap,
                                     RemapFlags RemapFlag,
                                     ValueMapTypeRemapper *TypeMapper,
                                     ValueMaterializer *Materializer,
                                     const MetadataPredicate *IdentityMD) {
  SmallVector<std::pair<unsigned, MDNode *>, 1> MDs;
  OldFunc.getAllMetadata(MDs);
  for (const auto &[Kind, MD] : MDs) {
    NewFunc.addMetadata(Kind, *MapMetadata(MD, VMap, RemapFlag, TypeMapper,
                                           Materializer, IdentityMD));
  }
}

void llvm::CloneFunctionBodyInto(Function &NewFunc, const Function &OldFunc,
                                 ValueToValueMapTy &VMap, RemapFlags RemapFlag,
                                 SmallVectorImpl<ReturnInst *> &Returns,
                                 const char *NameSuffix,
                                 ClonedCodeInfo *CodeInfo,
                                 ValueMapTypeRemapper *TypeMapper,
                                 ValueMaterializer *Materializer,
                                 const MetadataPredicate *IdentityMD) {
  if (OldFunc.isDeclaration())
    return;

  // Loop over all of the basic blocks in the function, cloning them as
  // appropriate.  Note that we save BE this way in order to handle cloning of
  // recursive functions into themselves.
  for (const BasicBlock &BB : OldFunc) {
    // Create a new basic block and copy instructions into it!
    BasicBlock *CBB =
        CloneBasicBlock(&BB, VMap, NameSuffix, &NewFunc, CodeInfo);

    // Add basic block mapping.
    VMap[&BB] = CBB;

    // It is only legal to clone a function if a block address within that
    // function is never referenced outside of the function.  Given that, we
    // want to map block addresses from the old function to block addresses in
    // the clone. (This is different from the generic ValueMapper
    // implementation, which generates an invalid blockaddress when
    // cloning a function.)
    if (BB.hasAddressTaken()) {
      Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(&OldFunc),
                                              const_cast<BasicBlock *>(&BB));
      VMap[OldBBAddr] = BlockAddress::get(&NewFunc, CBB);
    }

    // Note return instructions for the caller.
    if (ReturnInst *RI = dyn_cast<ReturnInst>(CBB->getTerminator()))
      Returns.push_back(RI);
  }

  // Loop over all of the instructions in the new function, fixing up operand
  // references as we go. This uses VMap to do all the hard work.
  for (Function::iterator
           BB = cast<BasicBlock>(VMap[&OldFunc.front()])->getIterator(),
           BE = NewFunc.end();
       BB != BE; ++BB)
    // Loop over all instructions, fixing each one as we find it, and any
    // attached debug-info records.
    for (Instruction &II : *BB) {
      RemapInstruction(&II, VMap, RemapFlag, TypeMapper, Materializer,
                       IdentityMD);
      RemapDbgRecordRange(II.getModule(), II.getDbgRecordRange(), VMap,
                          RemapFlag, TypeMapper, Materializer, IdentityMD);
    }
}

// Clone OldFunc into NewFunc, transforming the old arguments into references to
// VMap values.
void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
                             ValueToValueMapTy &VMap,
                             CloneFunctionChangeType Changes,
                             SmallVectorImpl<ReturnInst *> &Returns,
                             const char *NameSuffix, ClonedCodeInfo *CodeInfo,
                             ValueMapTypeRemapper *TypeMapper,
                             ValueMaterializer *Materializer) {
  assert(NameSuffix && "NameSuffix cannot be null!");

#ifndef NDEBUG
  for (const Argument &I : OldFunc->args())
    assert(VMap.count(&I) && "No mapping from source argument specified!");
#endif

  bool ModuleLevelChanges = Changes > CloneFunctionChangeType::LocalChangesOnly;

  CloneFunctionAttributesInto(NewFunc, OldFunc, VMap, ModuleLevelChanges,
                              TypeMapper, Materializer);

  // Everything else beyond this point deals with function instructions,
  // so if we are dealing with a function declaration, we're done.
  if (OldFunc->isDeclaration())
    return;

  if (Changes < CloneFunctionChangeType::DifferentModule) {
    assert((NewFunc->getParent() == nullptr ||
            NewFunc->getParent() == OldFunc->getParent()) &&
           "Expected NewFunc to have the same parent, or no parent");
  } else {
    assert((NewFunc->getParent() == nullptr ||
            NewFunc->getParent() != OldFunc->getParent()) &&
           "Expected NewFunc to have different parents, or no parent");

    if (Changes == CloneFunctionChangeType::DifferentModule) {
      assert(NewFunc->getParent() &&
             "Need parent of new function to maintain debug info invariants");
    }
  }

  MetadataPredicate IdentityMD = createIdentityMDPredicate(*OldFunc, Changes);

  // Cloning is always a Module level operation, since Metadata needs to be
  // cloned.
  const RemapFlags RemapFlag = RF_None;

  CloneFunctionMetadataInto(*NewFunc, *OldFunc, VMap, RemapFlag, TypeMapper,
                            Materializer, &IdentityMD);

  CloneFunctionBodyInto(*NewFunc, *OldFunc, VMap, RemapFlag, Returns,
                        NameSuffix, CodeInfo, TypeMapper, Materializer,
                        &IdentityMD);

  // Only update !llvm.dbg.cu for DifferentModule (not CloneModule). In the
  // same module, the compile unit will already be listed (or not). When
  // cloning a module, CloneModule() will handle creating the named metadata.
  if (Changes != CloneFunctionChangeType::DifferentModule)
    return;

  // Update !llvm.dbg.cu with compile units added to the new module if this
  // function is being cloned in isolation.
  //
  // FIXME: This is making global / module-level changes, which doesn't seem
  // like the right encapsulation  Consider dropping the requirement to update
  // !llvm.dbg.cu (either obsoleting the node, or restricting it to
  // non-discardable compile units) instead of discovering compile units by
  // visiting the metadata attached to global values, which would allow this
  // code to be deleted. Alternatively, perhaps give responsibility for this
  // update to CloneFunctionInto's callers.
  Module *NewModule = NewFunc->getParent();
  NamedMDNode *NMD = NewModule->getOrInsertNamedMetadata("llvm.dbg.cu");
  // Avoid multiple insertions of the same DICompileUnit to NMD.
  SmallPtrSet<const void *, 8> Visited(llvm::from_range, NMD->operands());

  // Collect and clone all the compile units referenced from the instructions in
  // the function (e.g. as instructions' scope).
  DebugInfoFinder DIFinder;
  collectDebugInfoFromInstructions(*OldFunc, DIFinder);
  for (DICompileUnit *Unit : DIFinder.compile_units()) {
    MDNode *MappedUnit =
        MapMetadata(Unit, VMap, RF_None, TypeMapper, Materializer);
    if (Visited.insert(MappedUnit).second)
      NMD->addOperand(MappedUnit);
  }
}

/// Return a copy of the specified function and add it to that function's
/// module.  Also, any references specified in the VMap are changed to refer to
/// their mapped value instead of the original one.  If any of the arguments to
/// the function are in the VMap, the arguments are deleted from the resultant
/// function.  The VMap is updated to include mappings from all of the
/// instructions and basicblocks in the function from their old to new values.
///
Function *llvm::CloneFunction(Function *F, ValueToValueMapTy &VMap,
                              ClonedCodeInfo *CodeInfo) {
  std::vector<Type *> ArgTypes;

  // The user might be deleting arguments to the function by specifying them in
  // the VMap.  If so, we need to not add the arguments to the arg ty vector
  //
  for (const Argument &I : F->args())
    if (VMap.count(&I) == 0) // Haven't mapped the argument to anything yet?
      ArgTypes.push_back(I.getType());

  // Create a new function type...
  FunctionType *FTy =
      FunctionType::get(F->getFunctionType()->getReturnType(), ArgTypes,
                        F->getFunctionType()->isVarArg());

  // Create the new function...
  Function *NewF = Function::Create(FTy, F->getLinkage(), F->getAddressSpace(),
                                    F->getName(), F->getParent());

  // Loop over the arguments, copying the names of the mapped arguments over...
  Function::arg_iterator DestI = NewF->arg_begin();
  for (const Argument &I : F->args())
    if (VMap.count(&I) == 0) {     // Is this argument preserved?
      DestI->setName(I.getName()); // Copy the name over...
      VMap[&I] = &*DestI++;        // Add mapping to VMap
    }

  SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
  CloneFunctionInto(NewF, F, VMap, CloneFunctionChangeType::LocalChangesOnly,
                    Returns, "", CodeInfo);

  return NewF;
}

namespace {
/// This is a private class used to implement CloneAndPruneFunctionInto.
struct PruningFunctionCloner {
  Function *NewFunc;
  const Function *OldFunc;
  ValueToValueMapTy &VMap;
  bool ModuleLevelChanges;
  const char *NameSuffix;
  ClonedCodeInfo *CodeInfo;
  bool HostFuncIsStrictFP;

  Instruction *cloneInstruction(BasicBlock::const_iterator II);

public:
  PruningFunctionCloner(Function *newFunc, const Function *oldFunc,
                        ValueToValueMapTy &valueMap, bool moduleLevelChanges,
                        const char *nameSuffix, ClonedCodeInfo *codeInfo)
      : NewFunc(newFunc), OldFunc(oldFunc), VMap(valueMap),
        ModuleLevelChanges(moduleLevelChanges), NameSuffix(nameSuffix),
        CodeInfo(codeInfo) {
    HostFuncIsStrictFP =
        newFunc->getAttributes().hasFnAttr(Attribute::StrictFP);
  }

  /// The specified block is found to be reachable, clone it and
  /// anything that it can reach.
  void CloneBlock(const BasicBlock *BB, BasicBlock::const_iterator StartingInst,
                  std::vector<const BasicBlock *> &ToClone);
};
} // namespace

Instruction *
PruningFunctionCloner::cloneInstruction(BasicBlock::const_iterator II) {
  const Instruction &OldInst = *II;
  Instruction *NewInst = nullptr;
  if (HostFuncIsStrictFP) {
    Intrinsic::ID CIID = getConstrainedIntrinsicID(OldInst);
    if (CIID != Intrinsic::not_intrinsic) {
      // Instead of cloning the instruction, a call to constrained intrinsic
      // should be created.
      // Assume the first arguments of constrained intrinsics are the same as
      // the operands of original instruction.

      // Determine overloaded types of the intrinsic.
      SmallVector<Type *, 2> TParams;
      SmallVector<Intrinsic::IITDescriptor, 8> Descriptor;
      getIntrinsicInfoTableEntries(CIID, Descriptor);
      for (unsigned I = 0, E = Descriptor.size(); I != E; ++I) {
        Intrinsic::IITDescriptor Operand = Descriptor[I];
        switch (Operand.Kind) {
        case Intrinsic::IITDescriptor::Argument:
          if (Operand.getArgumentKind() !=
              Intrinsic::IITDescriptor::AK_MatchType) {
            if (I == 0)
              TParams.push_back(OldInst.getType());
            else
              TParams.push_back(OldInst.getOperand(I - 1)->getType());
          }
          break;
        case Intrinsic::IITDescriptor::SameVecWidthArgument:
          ++I;
          break;
        default:
          break;
        }
      }

      // Create intrinsic call.
      LLVMContext &Ctx = NewFunc->getContext();
      Function *IFn = Intrinsic::getOrInsertDeclaration(NewFunc->getParent(),
                                                        CIID, TParams);
      SmallVector<Value *, 4> Args;
      unsigned NumOperands = OldInst.getNumOperands();
      if (isa<CallInst>(OldInst))
        --NumOperands;
      for (unsigned I = 0; I < NumOperands; ++I) {
        Value *Op = OldInst.getOperand(I);
        Args.push_back(Op);
      }
      if (const auto *CmpI = dyn_cast<FCmpInst>(&OldInst)) {
        FCmpInst::Predicate Pred = CmpI->getPredicate();
        StringRef PredName = FCmpInst::getPredicateName(Pred);
        Args.push_back(MetadataAsValue::get(Ctx, MDString::get(Ctx, PredName)));
      }

      // The last arguments of a constrained intrinsic are metadata that
      // represent rounding mode (absents in some intrinsics) and exception
      // behavior. The inlined function uses default settings.
      if (Intrinsic::hasConstrainedFPRoundingModeOperand(CIID))
        Args.push_back(
            MetadataAsValue::get(Ctx, MDString::get(Ctx, "round.tonearest")));
      Args.push_back(
          MetadataAsValue::get(Ctx, MDString::get(Ctx, "fpexcept.ignore")));

      NewInst = CallInst::Create(IFn, Args, OldInst.getName() + ".strict");
    }
  }
  if (!NewInst)
    NewInst = II->clone();
  return NewInst;
}

/// The specified block is found to be reachable, clone it and
/// anything that it can reach.
void PruningFunctionCloner::CloneBlock(
    const BasicBlock *BB, BasicBlock::const_iterator StartingInst,
    std::vector<const BasicBlock *> &ToClone) {
  WeakTrackingVH &BBEntry = VMap[BB];

  // Have we already cloned this block?
  if (BBEntry)
    return;

  // Nope, clone it now.
  BasicBlock *NewBB;
  Twine NewName(BB->hasName() ? Twine(BB->getName()) + NameSuffix : "");
  BBEntry = NewBB = BasicBlock::Create(BB->getContext(), NewName, NewFunc);

  // It is only legal to clone a function if a block address within that
  // function is never referenced outside of the function.  Given that, we
  // want to map block addresses from the old function to block addresses in
  // the clone. (This is different from the generic ValueMapper
  // implementation, which generates an invalid blockaddress when
  // cloning a function.)
  //
  // Note that we don't need to fix the mapping for unreachable blocks;
  // the default mapping there is safe.
  if (BB->hasAddressTaken()) {
    Constant *OldBBAddr = BlockAddress::get(const_cast<Function *>(OldFunc),
                                            const_cast<BasicBlock *>(BB));
    VMap[OldBBAddr] = BlockAddress::get(NewFunc, NewBB);
  }

  bool hasCalls = false, hasDynamicAllocas = false, hasStaticAllocas = false;
  bool hasMemProfMetadata = false;

  // Keep a cursor pointing at the last place we cloned debug-info records from.
  BasicBlock::const_iterator DbgCursor = StartingInst;
  auto CloneDbgRecordsToHere =
      [&DbgCursor](Instruction *NewInst, BasicBlock::const_iterator II) {
        // Clone debug-info records onto this instruction. Iterate through any
        // source-instructions we've cloned and then subsequently optimised
        // away, so that their debug-info doesn't go missing.
        for (; DbgCursor != II; ++DbgCursor)
          NewInst->cloneDebugInfoFrom(&*DbgCursor, std::nullopt, false);
        NewInst->cloneDebugInfoFrom(&*II);
        DbgCursor = std::next(II);
      };

  // Loop over all instructions, and copy them over, DCE'ing as we go.  This
  // loop doesn't include the terminator.
  for (BasicBlock::const_iterator II = StartingInst, IE = --BB->end(); II != IE;
       ++II) {

    // Don't clone fake_use as it may suppress many optimizations
    // due to inlining, especially SROA.
    if (auto *IntrInst = dyn_cast<IntrinsicInst>(II))
      if (IntrInst->getIntrinsicID() == Intrinsic::fake_use)
        continue;

    Instruction *NewInst = cloneInstruction(II);
    NewInst->insertInto(NewBB, NewBB->end());

    if (HostFuncIsStrictFP) {
      // All function calls in the inlined function must get 'strictfp'
      // attribute to prevent undesirable optimizations.
      if (auto *Call = dyn_cast<CallInst>(NewInst))
        Call->addFnAttr(Attribute::StrictFP);
    }

    // Eagerly remap operands to the newly cloned instruction, except for PHI
    // nodes for which we defer processing until we update the CFG.
    if (!isa<PHINode>(NewInst)) {
      RemapInstruction(NewInst, VMap,
                       ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges);

      // Eagerly constant fold the newly cloned instruction. If successful, add
      // a mapping to the new value. Non-constant operands may be incomplete at
      // this stage, thus instruction simplification is performed after
      // processing phi-nodes.
      if (Value *V = ConstantFoldInstruction(
              NewInst, BB->getDataLayout())) {
        if (isInstructionTriviallyDead(NewInst)) {
          VMap[&*II] = V;
          NewInst->eraseFromParent();
          continue;
        }
      }
    }

    if (II->hasName())
      NewInst->setName(II->getName() + NameSuffix);
    VMap[&*II] = NewInst; // Add instruction map to value.
    if (isa<CallInst>(II) && !II->isDebugOrPseudoInst()) {
      hasCalls = true;
      hasMemProfMetadata |= II->hasMetadata(LLVMContext::MD_memprof);
      hasMemProfMetadata |= II->hasMetadata(LLVMContext::MD_callsite);
    }

    CloneDbgRecordsToHere(NewInst, II);

    if (CodeInfo) {
      CodeInfo->OrigVMap[&*II] = NewInst;
      if (auto *CB = dyn_cast<CallBase>(&*II))
        if (CB->hasOperandBundles())
          CodeInfo->OperandBundleCallSites.push_back(NewInst);
    }

    if (const AllocaInst *AI = dyn_cast<AllocaInst>(II)) {
      if (isa<ConstantInt>(AI->getArraySize()))
        hasStaticAllocas = true;
      else
        hasDynamicAllocas = true;
    }
  }

  // Finally, clone over the terminator.
  const Instruction *OldTI = BB->getTerminator();
  bool TerminatorDone = false;
  if (const BranchInst *BI = dyn_cast<BranchInst>(OldTI)) {
    if (BI->isConditional()) {
      // If the condition was a known constant in the callee...
      ConstantInt *Cond = dyn_cast<ConstantInt>(BI->getCondition());
      // Or is a known constant in the caller...
      if (!Cond) {
        Value *V = VMap.lookup(BI->getCondition());
        Cond = dyn_cast_or_null<ConstantInt>(V);
      }

      // Constant fold to uncond branch!
      if (Cond) {
        BasicBlock *Dest = BI->getSuccessor(!Cond->getZExtValue());
        auto *NewBI = BranchInst::Create(Dest, NewBB);
        NewBI->setDebugLoc(BI->getDebugLoc());
        VMap[OldTI] = NewBI;
        ToClone.push_back(Dest);
        TerminatorDone = true;
      }
    }
  } else if (const SwitchInst *SI = dyn_cast<SwitchInst>(OldTI)) {
    // If switching on a value known constant in the caller.
    ConstantInt *Cond = dyn_cast<ConstantInt>(SI->getCondition());
    if (!Cond) { // Or known constant after constant prop in the callee...
      Value *V = VMap.lookup(SI->getCondition());
      Cond = dyn_cast_or_null<ConstantInt>(V);
    }
    if (Cond) { // Constant fold to uncond branch!
      SwitchInst::ConstCaseHandle Case = *SI->findCaseValue(Cond);
      BasicBlock *Dest = const_cast<BasicBlock *>(Case.getCaseSuccessor());
      auto *NewBI = BranchInst::Create(Dest, NewBB);
      NewBI->setDebugLoc(SI->getDebugLoc());
      VMap[OldTI] = NewBI;
      ToClone.push_back(Dest);
      TerminatorDone = true;
    }
  }

  if (!TerminatorDone) {
    Instruction *NewInst = OldTI->clone();
    if (OldTI->hasName())
      NewInst->setName(OldTI->getName() + NameSuffix);
    NewInst->insertInto(NewBB, NewBB->end());

    CloneDbgRecordsToHere(NewInst, OldTI->getIterator());

    VMap[OldTI] = NewInst; // Add instruction map to value.

    if (CodeInfo) {
      CodeInfo->OrigVMap[OldTI] = NewInst;
      if (auto *CB = dyn_cast<CallBase>(OldTI))
        if (CB->hasOperandBundles())
          CodeInfo->OperandBundleCallSites.push_back(NewInst);
    }

    // Recursively clone any reachable successor blocks.
    append_range(ToClone, successors(BB->getTerminator()));
  } else {
    // If we didn't create a new terminator, clone DbgVariableRecords from the
    // old terminator onto the new terminator.
    Instruction *NewInst = NewBB->getTerminator();
    assert(NewInst);

    CloneDbgRecordsToHere(NewInst, OldTI->getIterator());
  }

  if (CodeInfo) {
    CodeInfo->ContainsCalls |= hasCalls;
    CodeInfo->ContainsMemProfMetadata |= hasMemProfMetadata;
    CodeInfo->ContainsDynamicAllocas |= hasDynamicAllocas;
    CodeInfo->ContainsDynamicAllocas |=
        hasStaticAllocas && BB != &BB->getParent()->front();
  }
}

/// This works like CloneAndPruneFunctionInto, except that it does not clone the
/// entire function. Instead it starts at an instruction provided by the caller
/// and copies (and prunes) only the code reachable from that instruction.
void llvm::CloneAndPruneIntoFromInst(Function *NewFunc, const Function *OldFunc,
                                     const Instruction *StartingInst,
                                     ValueToValueMapTy &VMap,
                                     bool ModuleLevelChanges,
                                     SmallVectorImpl<ReturnInst *> &Returns,
                                     const char *NameSuffix,
                                     ClonedCodeInfo *CodeInfo) {
  assert(NameSuffix && "NameSuffix cannot be null!");

  ValueMapTypeRemapper *TypeMapper = nullptr;
  ValueMaterializer *Materializer = nullptr;

#ifndef NDEBUG
  // If the cloning starts at the beginning of the function, verify that
  // the function arguments are mapped.
  if (!StartingInst)
    for (const Argument &II : OldFunc->args())
      assert(VMap.count(&II) && "No mapping from source argument specified!");
#endif

  PruningFunctionCloner PFC(NewFunc, OldFunc, VMap, ModuleLevelChanges,
                            NameSuffix, CodeInfo);
  const BasicBlock *StartingBB;
  if (StartingInst)
    StartingBB = StartingInst->getParent();
  else {
    StartingBB = &OldFunc->getEntryBlock();
    StartingInst = &StartingBB->front();
  }

  // Clone the entry block, and anything recursively reachable from it.
  std::vector<const BasicBlock *> CloneWorklist;
  PFC.CloneBlock(StartingBB, StartingInst->getIterator(), CloneWorklist);
  while (!CloneWorklist.empty()) {
    const BasicBlock *BB = CloneWorklist.back();
    CloneWorklist.pop_back();
    PFC.CloneBlock(BB, BB->begin(), CloneWorklist);
  }

  // Loop over all of the basic blocks in the old function.  If the block was
  // reachable, we have cloned it and the old block is now in the value map:
  // insert it into the new function in the right order.  If not, ignore it.
  //
  // Defer PHI resolution until rest of function is resolved.
  SmallVector<const PHINode *, 16> PHIToResolve;
  for (const BasicBlock &BI : *OldFunc) {
    Value *V = VMap.lookup(&BI);
    BasicBlock *NewBB = cast_or_null<BasicBlock>(V);
    if (!NewBB)
      continue; // Dead block.

    // Move the new block to preserve the order in the original function.
    NewBB->moveBefore(NewFunc->end());

    // Handle PHI nodes specially, as we have to remove references to dead
    // blocks.
    for (const PHINode &PN : BI.phis()) {
      // PHI nodes may have been remapped to non-PHI nodes by the caller or
      // during the cloning process.
      if (isa<PHINode>(VMap[&PN]))
        PHIToResolve.push_back(&PN);
      else
        break;
    }

    // Finally, remap the terminator instructions, as those can't be remapped
    // until all BBs are mapped.
    RemapInstruction(NewBB->getTerminator(), VMap,
                     ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
                     TypeMapper, Materializer);
  }

  // Defer PHI resolution until rest of function is resolved, PHI resolution
  // requires the CFG to be up-to-date.
  for (unsigned phino = 0, e = PHIToResolve.size(); phino != e;) {
    const PHINode *OPN = PHIToResolve[phino];
    unsigned NumPreds = OPN->getNumIncomingValues();
    const BasicBlock *OldBB = OPN->getParent();
    BasicBlock *NewBB = cast<BasicBlock>(VMap[OldBB]);

    // Map operands for blocks that are live and remove operands for blocks
    // that are dead.
    for (; phino != PHIToResolve.size() &&
           PHIToResolve[phino]->getParent() == OldBB;
         ++phino) {
      OPN = PHIToResolve[phino];
      PHINode *PN = cast<PHINode>(VMap[OPN]);
      for (int64_t pred = NumPreds - 1; pred >= 0; --pred) {
        Value *V = VMap.lookup(PN->getIncomingBlock(pred));
        if (BasicBlock *MappedBlock = cast_or_null<BasicBlock>(V)) {
          Value *InVal =
              MapValue(PN->getIncomingValue(pred), VMap,
                       ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges);
          assert(InVal && "Unknown input value?");
          PN->setIncomingValue(pred, InVal);
          PN->setIncomingBlock(pred, MappedBlock);
          continue;
        }
        PN->removeIncomingValue(pred, false);
      }
    }

    // The loop above has removed PHI entries for those blocks that are dead
    // and has updated others.  However, if a block is live (i.e. copied over)
    // but its terminator has been changed to not go to this block, then our
    // phi nodes will have invalid entries.  Update the PHI nodes in this
    // case.
    PHINode *PN = cast<PHINode>(NewBB->begin());
    NumPreds = pred_size(NewBB);
    if (NumPreds != PN->getNumIncomingValues()) {
      assert(NumPreds < PN->getNumIncomingValues());
      // Count how many times each predecessor comes to this block.
      DenseMap<BasicBlock *, unsigned> PredCount;
      for (BasicBlock *Pred : predecessors(NewBB))
        ++PredCount[Pred];

      BasicBlock::iterator I = NewBB->begin();
      DenseMap<BasicBlock *, unsigned> SeenPredCount;
      SeenPredCount.reserve(PredCount.size());
      for (; (PN = dyn_cast<PHINode>(I)); ++I) {
        SeenPredCount.clear();
        PN->removeIncomingValueIf(
            [&](unsigned Idx) {
              BasicBlock *IncomingBlock = PN->getIncomingBlock(Idx);
              auto It = PredCount.find(IncomingBlock);
              if (It == PredCount.end())
                return true;
              unsigned &SeenCount = SeenPredCount[IncomingBlock];
              if (SeenCount < It->second) {
                SeenCount++;
                return false;
              }
              return true;
            },
            false);
      }
    }

    // If the loops above have made these phi nodes have 0 or 1 operand,
    // replace them with poison or the input value.  We must do this for
    // correctness, because 0-operand phis are not valid.
    PN = cast<PHINode>(NewBB->begin());
    if (PN->getNumIncomingValues() == 0) {
      BasicBlock::iterator I = NewBB->begin();
      BasicBlock::const_iterator OldI = OldBB->begin();
      while ((PN = dyn_cast<PHINode>(I++))) {
        Value *NV = PoisonValue::get(PN->getType());
        PN->replaceAllUsesWith(NV);
        assert(VMap[&*OldI] == PN && "VMap mismatch");
        VMap[&*OldI] = NV;
        PN->eraseFromParent();
        ++OldI;
      }
    }
  }

  // Drop all incompatible return attributes that cannot be applied to NewFunc
  // during cloning, so as to allow instruction simplification to reason on the
  // old state of the function. The original attributes are restored later.
  AttributeList Attrs = NewFunc->getAttributes();
  AttributeMask IncompatibleAttrs = AttributeFuncs::typeIncompatible(
      OldFunc->getReturnType(), Attrs.getRetAttrs());
  NewFunc->removeRetAttrs(IncompatibleAttrs);

  // As phi-nodes have been now remapped, allow incremental simplification of
  // newly-cloned instructions.
  const DataLayout &DL = NewFunc->getDataLayout();
  for (const BasicBlock &BB : *OldFunc) {
    for (const Instruction &I : BB) {
      auto *NewI = dyn_cast_or_null<Instruction>(VMap.lookup(&I));
      if (!NewI)
        continue;

      if (Value *V = simplifyInstruction(NewI, DL)) {
        NewI->replaceAllUsesWith(V);

        if (isInstructionTriviallyDead(NewI)) {
          NewI->eraseFromParent();
        } else {
          // Did not erase it? Restore the new instruction into VMap previously
          // dropped by `ValueIsRAUWd`.
          VMap[&I] = NewI;
        }
      }
    }
  }

  // Restore attributes.
  NewFunc->setAttributes(Attrs);

  // Remap debug records operands now that all values have been mapped.
  // Doing this now (late) preserves use-before-defs in debug records. If
  // we didn't do this, ValueAsMetadata(use-before-def) operands would be
  // replaced by empty metadata. This would signal later cleanup passes to
  // remove the debug records, potentially causing incorrect locations.
  Function::iterator Begin = cast<BasicBlock>(VMap[StartingBB])->getIterator();
  for (BasicBlock &BB : make_range(Begin, NewFunc->end())) {
    for (Instruction &I : BB) {
      RemapDbgRecordRange(I.getModule(), I.getDbgRecordRange(), VMap,
                          ModuleLevelChanges ? RF_None
                                             : RF_NoModuleLevelChanges,
                          TypeMapper, Materializer);
    }
  }

  // Simplify conditional branches and switches with a constant operand. We try
  // to prune these out when cloning, but if the simplification required
  // looking through PHI nodes, those are only available after forming the full
  // basic block. That may leave some here, and we still want to prune the dead
  // code as early as possible.
  for (BasicBlock &BB : make_range(Begin, NewFunc->end()))
    ConstantFoldTerminator(&BB);

  // Some blocks may have become unreachable as a result. Find and delete them.
  {
    SmallPtrSet<BasicBlock *, 16> ReachableBlocks;
    SmallVector<BasicBlock *, 16> Worklist;
    Worklist.push_back(&*Begin);
    while (!Worklist.empty()) {
      BasicBlock *BB = Worklist.pop_back_val();
      if (ReachableBlocks.insert(BB).second)
        append_range(Worklist, successors(BB));
    }

    SmallVector<BasicBlock *, 16> UnreachableBlocks;
    for (BasicBlock &BB : make_range(Begin, NewFunc->end()))
      if (!ReachableBlocks.contains(&BB))
        UnreachableBlocks.push_back(&BB);
    DeleteDeadBlocks(UnreachableBlocks);
  }

  // Now that the inlined function body has been fully constructed, go through
  // and zap unconditional fall-through branches. This happens all the time when
  // specializing code: code specialization turns conditional branches into
  // uncond branches, and this code folds them.
  Function::iterator I = Begin;
  while (I != NewFunc->end()) {
    BranchInst *BI = dyn_cast<BranchInst>(I->getTerminator());
    if (!BI || BI->isConditional()) {
      ++I;
      continue;
    }

    BasicBlock *Dest = BI->getSuccessor(0);
    if (!Dest->getSinglePredecessor() || Dest->hasAddressTaken()) {
      ++I;
      continue;
    }

    // We shouldn't be able to get single-entry PHI nodes here, as instsimplify
    // above should have zapped all of them..
    assert(!isa<PHINode>(Dest->begin()));

    // We know all single-entry PHI nodes in the inlined function have been
    // removed, so we just need to splice the blocks.
    BI->eraseFromParent();

    // Make all PHI nodes that referred to Dest now refer to I as their source.
    Dest->replaceAllUsesWith(&*I);

    // Move all the instructions in the succ to the pred.
    I->splice(I->end(), Dest);

    // Remove the dest block.
    Dest->eraseFromParent();

    // Do not increment I, iteratively merge all things this block branches to.
  }

  // Make a final pass over the basic blocks from the old function to gather
  // any return instructions which survived folding. We have to do this here
  // because we can iteratively remove and merge returns above.
  for (Function::iterator I = cast<BasicBlock>(VMap[StartingBB])->getIterator(),
                          E = NewFunc->end();
       I != E; ++I)
    if (ReturnInst *RI = dyn_cast<ReturnInst>(I->getTerminator()))
      Returns.push_back(RI);
}

/// This works exactly like CloneFunctionInto,
/// except that it does some simple constant prop and DCE on the fly.  The
/// effect of this is to copy significantly less code in cases where (for
/// example) a function call with constant arguments is inlined, and those
/// constant arguments cause a significant amount of code in the callee to be
/// dead.  Since this doesn't produce an exact copy of the input, it can't be
/// used for things like CloneFunction or CloneModule.
void llvm::CloneAndPruneFunctionInto(
    Function *NewFunc, const Function *OldFunc, ValueToValueMapTy &VMap,
    bool ModuleLevelChanges, SmallVectorImpl<ReturnInst *> &Returns,
    const char *NameSuffix, ClonedCodeInfo *CodeInfo) {
  CloneAndPruneIntoFromInst(NewFunc, OldFunc, &OldFunc->front().front(), VMap,
                            ModuleLevelChanges, Returns, NameSuffix, CodeInfo);
}

/// Remaps instructions in \p Blocks using the mapping in \p VMap.
void llvm::remapInstructionsInBlocks(ArrayRef<BasicBlock *> Blocks,
                                     ValueToValueMapTy &VMap) {
  // Rewrite the code to refer to itself.
  for (BasicBlock *BB : Blocks) {
    for (Instruction &Inst : *BB) {
      RemapDbgRecordRange(Inst.getModule(), Inst.getDbgRecordRange(), VMap,
                          RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
      RemapInstruction(&Inst, VMap,
                       RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
    }
  }
}

/// Clones a loop \p OrigLoop.  Returns the loop and the blocks in \p
/// Blocks.
///
/// Updates LoopInfo and DominatorTree assuming the loop is dominated by block
/// \p LoopDomBB.  Insert the new blocks before block specified in \p Before.
Loop *llvm::cloneLoopWithPreheader(BasicBlock *Before, BasicBlock *LoopDomBB,
                                   Loop *OrigLoop, ValueToValueMapTy &VMap,
                                   const Twine &NameSuffix, LoopInfo *LI,
                                   DominatorTree *DT,
                                   SmallVectorImpl<BasicBlock *> &Blocks) {
  Function *F = OrigLoop->getHeader()->getParent();
  Loop *ParentLoop = OrigLoop->getParentLoop();
  DenseMap<Loop *, Loop *> LMap;

  Loop *NewLoop = LI->AllocateLoop();
  LMap[OrigLoop] = NewLoop;
  if (ParentLoop)
    ParentLoop->addChildLoop(NewLoop);
  else
    LI->addTopLevelLoop(NewLoop);

  BasicBlock *OrigPH = OrigLoop->getLoopPreheader();
  assert(OrigPH && "No preheader");
  BasicBlock *NewPH = CloneBasicBlock(OrigPH, VMap, NameSuffix, F);
  // To rename the loop PHIs.
  VMap[OrigPH] = NewPH;
  Blocks.push_back(NewPH);

  // Update LoopInfo.
  if (ParentLoop)
    ParentLoop->addBasicBlockToLoop(NewPH, *LI);

  // Update DominatorTree.
  DT->addNewBlock(NewPH, LoopDomBB);

  for (Loop *CurLoop : OrigLoop->getLoopsInPreorder()) {
    Loop *&NewLoop = LMap[CurLoop];
    if (!NewLoop) {
      NewLoop = LI->AllocateLoop();

      // Establish the parent/child relationship.
      Loop *OrigParent = CurLoop->getParentLoop();
      assert(OrigParent && "Could not find the original parent loop");
      Loop *NewParentLoop = LMap[OrigParent];
      assert(NewParentLoop && "Could not find the new parent loop");

      NewParentLoop->addChildLoop(NewLoop);
    }
  }

  for (BasicBlock *BB : OrigLoop->getBlocks()) {
    Loop *CurLoop = LI->getLoopFor(BB);
    Loop *&NewLoop = LMap[CurLoop];
    assert(NewLoop && "Expecting new loop to be allocated");

    BasicBlock *NewBB = CloneBasicBlock(BB, VMap, NameSuffix, F);
    VMap[BB] = NewBB;

    // Update LoopInfo.
    NewLoop->addBasicBlockToLoop(NewBB, *LI);

    // Add DominatorTree node. After seeing all blocks, update to correct
    // IDom.
    DT->addNewBlock(NewBB, NewPH);

    Blocks.push_back(NewBB);
  }

  for (BasicBlock *BB : OrigLoop->getBlocks()) {
    // Update loop headers.
    Loop *CurLoop = LI->getLoopFor(BB);
    if (BB == CurLoop->getHeader())
      LMap[CurLoop]->moveToHeader(cast<BasicBlock>(VMap[BB]));

    // Update DominatorTree.
    BasicBlock *IDomBB = DT->getNode(BB)->getIDom()->getBlock();
    DT->changeImmediateDominator(cast<BasicBlock>(VMap[BB]),
                                 cast<BasicBlock>(VMap[IDomBB]));
  }

  // Move them physically from the end of the block list.
  F->splice(Before->getIterator(), F, NewPH->getIterator());
  F->splice(Before->getIterator(), F, NewLoop->getHeader()->getIterator(),
            F->end());

  return NewLoop;
}

/// Duplicate non-Phi instructions from the beginning of block up to
/// StopAt instruction into a split block between BB and its predecessor.
BasicBlock *llvm::DuplicateInstructionsInSplitBetween(
    BasicBlock *BB, BasicBlock *PredBB, Instruction *StopAt,
    ValueToValueMapTy &ValueMapping, DomTreeUpdater &DTU) {

  assert(count(successors(PredBB), BB) == 1 &&
         "There must be a single edge between PredBB and BB!");
  // We are going to have to map operands from the original BB block to the new
  // copy of the block 'NewBB'.  If there are PHI nodes in BB, evaluate them to
  // account for entry from PredBB.
  BasicBlock::iterator BI = BB->begin();
  for (; PHINode *PN = dyn_cast<PHINode>(BI); ++BI)
    ValueMapping[PN] = PN->getIncomingValueForBlock(PredBB);

  BasicBlock *NewBB = SplitEdge(PredBB, BB);
  NewBB->setName(PredBB->getName() + ".split");
  Instruction *NewTerm = NewBB->getTerminator();

  // FIXME: SplitEdge does not yet take a DTU, so we include the split edge
  //        in the update set here.
  DTU.applyUpdates({{DominatorTree::Delete, PredBB, BB},
                    {DominatorTree::Insert, PredBB, NewBB},
                    {DominatorTree::Insert, NewBB, BB}});

  // Clone the non-phi instructions of BB into NewBB, keeping track of the
  // mapping and using it to remap operands in the cloned instructions.
  // Stop once we see the terminator too. This covers the case where BB's
  // terminator gets replaced and StopAt == BB's terminator.
  for (; StopAt != &*BI && BB->getTerminator() != &*BI; ++BI) {
    Instruction *New = BI->clone();
    New->setName(BI->getName());
    New->insertBefore(NewTerm->getIterator());
    New->cloneDebugInfoFrom(&*BI);
    ValueMapping[&*BI] = New;

    // Remap operands to patch up intra-block references.
    for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
      if (Instruction *Inst = dyn_cast<Instruction>(New->getOperand(i))) {
        auto I = ValueMapping.find(Inst);
        if (I != ValueMapping.end())
          New->setOperand(i, I->second);
      }

    // Remap debug variable operands.
    remapDebugVariable(ValueMapping, New);
  }

  return NewBB;
}

void llvm::cloneNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
                              DenseMap<MDNode *, MDNode *> &ClonedScopes,
                              StringRef Ext, LLVMContext &Context) {
  MDBuilder MDB(Context);

  for (MDNode *ScopeList : NoAliasDeclScopes) {
    for (const MDOperand &MDOp : ScopeList->operands()) {
      if (MDNode *MD = dyn_cast<MDNode>(MDOp)) {
        AliasScopeNode SNANode(MD);

        std::string Name;
        auto ScopeName = SNANode.getName();
        if (!ScopeName.empty())
          Name = (Twine(ScopeName) + ":" + Ext).str();
        else
          Name = std::string(Ext);

        MDNode *NewScope = MDB.createAnonymousAliasScope(
            const_cast<MDNode *>(SNANode.getDomain()), Name);
        ClonedScopes.insert(std::make_pair(MD, NewScope));
      }
    }
  }
}

void llvm::adaptNoAliasScopes(Instruction *I,
                              const DenseMap<MDNode *, MDNode *> &ClonedScopes,
                              LLVMContext &Context) {
  auto CloneScopeList = [&](const MDNode *ScopeList) -> MDNode * {
    bool NeedsReplacement = false;
    SmallVector<Metadata *, 8> NewScopeList;
    for (const MDOperand &MDOp : ScopeList->operands()) {
      if (MDNode *MD = dyn_cast<MDNode>(MDOp)) {
        if (auto *NewMD = ClonedScopes.lookup(MD)) {
          NewScopeList.push_back(NewMD);
          NeedsReplacement = true;
          continue;
        }
        NewScopeList.push_back(MD);
      }
    }
    if (NeedsReplacement)
      return MDNode::get(Context, NewScopeList);
    return nullptr;
  };

  if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(I))
    if (MDNode *NewScopeList = CloneScopeList(Decl->getScopeList()))
      Decl->setScopeList(NewScopeList);

  auto replaceWhenNeeded = [&](unsigned MD_ID) {
    if (const MDNode *CSNoAlias = I->getMetadata(MD_ID))
      if (MDNode *NewScopeList = CloneScopeList(CSNoAlias))
        I->setMetadata(MD_ID, NewScopeList);
  };
  replaceWhenNeeded(LLVMContext::MD_noalias);
  replaceWhenNeeded(LLVMContext::MD_alias_scope);
}

void llvm::cloneAndAdaptNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
                                      ArrayRef<BasicBlock *> NewBlocks,
                                      LLVMContext &Context, StringRef Ext) {
  if (NoAliasDeclScopes.empty())
    return;

  DenseMap<MDNode *, MDNode *> ClonedScopes;
  LLVM_DEBUG(dbgs() << "cloneAndAdaptNoAliasScopes: cloning "
                    << NoAliasDeclScopes.size() << " node(s)\n");

  cloneNoAliasScopes(NoAliasDeclScopes, ClonedScopes, Ext, Context);
  // Identify instructions using metadata that needs adaptation
  for (BasicBlock *NewBlock : NewBlocks)
    for (Instruction &I : *NewBlock)
      adaptNoAliasScopes(&I, ClonedScopes, Context);
}

void llvm::cloneAndAdaptNoAliasScopes(ArrayRef<MDNode *> NoAliasDeclScopes,
                                      Instruction *IStart, Instruction *IEnd,
                                      LLVMContext &Context, StringRef Ext) {
  if (NoAliasDeclScopes.empty())
    return;

  DenseMap<MDNode *, MDNode *> ClonedScopes;
  LLVM_DEBUG(dbgs() << "cloneAndAdaptNoAliasScopes: cloning "
                    << NoAliasDeclScopes.size() << " node(s)\n");

  cloneNoAliasScopes(NoAliasDeclScopes, ClonedScopes, Ext, Context);
  // Identify instructions using metadata that needs adaptation
  assert(IStart->getParent() == IEnd->getParent() && "different basic block ?");
  auto ItStart = IStart->getIterator();
  auto ItEnd = IEnd->getIterator();
  ++ItEnd; // IEnd is included, increment ItEnd to get the end of the range
  for (auto &I : llvm::make_range(ItStart, ItEnd))
    adaptNoAliasScopes(&I, ClonedScopes, Context);
}

void llvm::identifyNoAliasScopesToClone(
    ArrayRef<BasicBlock *> BBs, SmallVectorImpl<MDNode *> &NoAliasDeclScopes) {
  for (BasicBlock *BB : BBs)
    for (Instruction &I : *BB)
      if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
        NoAliasDeclScopes.push_back(Decl->getScopeList());
}

void llvm::identifyNoAliasScopesToClone(
    BasicBlock::iterator Start, BasicBlock::iterator End,
    SmallVectorImpl<MDNode *> &NoAliasDeclScopes) {
  for (Instruction &I : make_range(Start, End))
    if (auto *Decl = dyn_cast<NoAliasScopeDeclInst>(&I))
      NoAliasDeclScopes.push_back(Decl->getScopeList());
}
