//===- Metadata.cpp - Implement Metadata classes --------------------------===//
//
// 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 Metadata classes.
//
//===----------------------------------------------------------------------===//

#include "llvm/IR/Metadata.h"
#include "LLVMContextImpl.h"
#include "MetadataImpl.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/ConstantRangeList.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/IR/DebugProgramInstruction.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalObject.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ProfDataUtils.h"
#include "llvm/IR/TrackingMDRef.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ModRef.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <type_traits>
#include <utility>
#include <vector>

using namespace llvm;

MetadataAsValue::MetadataAsValue(Type *Ty, Metadata *MD)
    : Value(Ty, MetadataAsValueVal), MD(MD) {
  track();
}

MetadataAsValue::~MetadataAsValue() {
  getType()->getContext().pImpl->MetadataAsValues.erase(MD);
  untrack();
}

/// Canonicalize metadata arguments to intrinsics.
///
/// To support bitcode upgrades (and assembly semantic sugar) for \a
/// MetadataAsValue, we need to canonicalize certain metadata.
///
///   - nullptr is replaced by an empty MDNode.
///   - An MDNode with a single null operand is replaced by an empty MDNode.
///   - An MDNode whose only operand is a \a ConstantAsMetadata gets skipped.
///
/// This maintains readability of bitcode from when metadata was a type of
/// value, and these bridges were unnecessary.
static Metadata *canonicalizeMetadataForValue(LLVMContext &Context,
                                              Metadata *MD) {
  if (!MD)
    // !{}
    return MDNode::get(Context, {});

  // Return early if this isn't a single-operand MDNode.
  auto *N = dyn_cast<MDNode>(MD);
  if (!N || N->getNumOperands() != 1)
    return MD;

  if (!N->getOperand(0))
    // !{}
    return MDNode::get(Context, {});

  if (auto *C = dyn_cast<ConstantAsMetadata>(N->getOperand(0)))
    // Look through the MDNode.
    return C;

  return MD;
}

MetadataAsValue *MetadataAsValue::get(LLVMContext &Context, Metadata *MD) {
  MD = canonicalizeMetadataForValue(Context, MD);
  auto *&Entry = Context.pImpl->MetadataAsValues[MD];
  if (!Entry)
    Entry = new MetadataAsValue(Type::getMetadataTy(Context), MD);
  return Entry;
}

MetadataAsValue *MetadataAsValue::getIfExists(LLVMContext &Context,
                                              Metadata *MD) {
  MD = canonicalizeMetadataForValue(Context, MD);
  auto &Store = Context.pImpl->MetadataAsValues;
  return Store.lookup(MD);
}

void MetadataAsValue::handleChangedMetadata(Metadata *MD) {
  LLVMContext &Context = getContext();
  MD = canonicalizeMetadataForValue(Context, MD);
  auto &Store = Context.pImpl->MetadataAsValues;

  // Stop tracking the old metadata.
  Store.erase(this->MD);
  untrack();
  this->MD = nullptr;

  // Start tracking MD, or RAUW if necessary.
  auto *&Entry = Store[MD];
  if (Entry) {
    replaceAllUsesWith(Entry);
    delete this;
    return;
  }

  this->MD = MD;
  track();
  Entry = this;
}

void MetadataAsValue::track() {
  if (MD)
    MetadataTracking::track(&MD, *MD, *this);
}

void MetadataAsValue::untrack() {
  if (MD)
    MetadataTracking::untrack(MD);
}

DbgVariableRecord *DebugValueUser::getUser() {
  return static_cast<DbgVariableRecord *>(this);
}
const DbgVariableRecord *DebugValueUser::getUser() const {
  return static_cast<const DbgVariableRecord *>(this);
}

void DebugValueUser::handleChangedValue(void *Old, Metadata *New) {
  // NOTE: We could inform the "owner" that a value has changed through
  // getOwner, if needed.
  auto OldMD = static_cast<Metadata **>(Old);
  ptrdiff_t Idx = std::distance(&*DebugValues.begin(), OldMD);
  // If replacing a ValueAsMetadata with a nullptr, replace it with a
  // PoisonValue instead.
  if (OldMD && isa<ValueAsMetadata>(*OldMD) && !New) {
    auto *OldVAM = cast<ValueAsMetadata>(*OldMD);
    New = ValueAsMetadata::get(PoisonValue::get(OldVAM->getValue()->getType()));
  }
  resetDebugValue(Idx, New);
}

void DebugValueUser::trackDebugValue(size_t Idx) {
  assert(Idx < 3 && "Invalid debug value index.");
  Metadata *&MD = DebugValues[Idx];
  if (MD)
    MetadataTracking::track(&MD, *MD, *this);
}

void DebugValueUser::trackDebugValues() {
  for (Metadata *&MD : DebugValues)
    if (MD)
      MetadataTracking::track(&MD, *MD, *this);
}

void DebugValueUser::untrackDebugValue(size_t Idx) {
  assert(Idx < 3 && "Invalid debug value index.");
  Metadata *&MD = DebugValues[Idx];
  if (MD)
    MetadataTracking::untrack(MD);
}

void DebugValueUser::untrackDebugValues() {
  for (Metadata *&MD : DebugValues)
    if (MD)
      MetadataTracking::untrack(MD);
}

void DebugValueUser::retrackDebugValues(DebugValueUser &X) {
  assert(DebugValueUser::operator==(X) && "Expected values to match");
  for (const auto &[MD, XMD] : zip(DebugValues, X.DebugValues))
    if (XMD)
      MetadataTracking::retrack(XMD, MD);
  X.DebugValues.fill(nullptr);
}

bool MetadataTracking::track(void *Ref, Metadata &MD, OwnerTy Owner) {
  assert(Ref && "Expected live reference");
  assert((Owner || *static_cast<Metadata **>(Ref) == &MD) &&
         "Reference without owner must be direct");
  if (auto *R = ReplaceableMetadataImpl::getOrCreate(MD)) {
    R->addRef(Ref, Owner);
    return true;
  }
  if (auto *PH = dyn_cast<DistinctMDOperandPlaceholder>(&MD)) {
    assert(!PH->Use && "Placeholders can only be used once");
    assert(!Owner && "Unexpected callback to owner");
    PH->Use = static_cast<Metadata **>(Ref);
    return true;
  }
  return false;
}

void MetadataTracking::untrack(void *Ref, Metadata &MD) {
  assert(Ref && "Expected live reference");
  if (auto *R = ReplaceableMetadataImpl::getIfExists(MD))
    R->dropRef(Ref);
  else if (auto *PH = dyn_cast<DistinctMDOperandPlaceholder>(&MD))
    PH->Use = nullptr;
}

bool MetadataTracking::retrack(void *Ref, Metadata &MD, void *New) {
  assert(Ref && "Expected live reference");
  assert(New && "Expected live reference");
  assert(Ref != New && "Expected change");
  if (auto *R = ReplaceableMetadataImpl::getIfExists(MD)) {
    R->moveRef(Ref, New, MD);
    return true;
  }
  assert(!isa<DistinctMDOperandPlaceholder>(MD) &&
         "Unexpected move of an MDOperand");
  assert(!isReplaceable(MD) &&
         "Expected un-replaceable metadata, since we didn't move a reference");
  return false;
}

bool MetadataTracking::isReplaceable(const Metadata &MD) {
  return ReplaceableMetadataImpl::isReplaceable(MD);
}

SmallVector<Metadata *> ReplaceableMetadataImpl::getAllArgListUsers() {
  SmallVector<std::pair<OwnerTy, uint64_t> *> MDUsersWithID;
  for (auto Pair : UseMap) {
    OwnerTy Owner = Pair.second.first;
    if (Owner.isNull())
      continue;
    if (!isa<Metadata *>(Owner))
      continue;
    Metadata *OwnerMD = cast<Metadata *>(Owner);
    if (OwnerMD->getMetadataID() == Metadata::DIArgListKind)
      MDUsersWithID.push_back(&UseMap[Pair.first]);
  }
  llvm::sort(MDUsersWithID, [](auto UserA, auto UserB) {
    return UserA->second < UserB->second;
  });
  SmallVector<Metadata *> MDUsers;
  for (auto *UserWithID : MDUsersWithID)
    MDUsers.push_back(cast<Metadata *>(UserWithID->first));
  return MDUsers;
}

SmallVector<DbgVariableRecord *>
ReplaceableMetadataImpl::getAllDbgVariableRecordUsers() {
  SmallVector<std::pair<OwnerTy, uint64_t> *> DVRUsersWithID;
  for (auto Pair : UseMap) {
    OwnerTy Owner = Pair.second.first;
    if (Owner.isNull())
      continue;
    if (!isa<DebugValueUser *>(Owner))
      continue;
    DVRUsersWithID.push_back(&UseMap[Pair.first]);
  }
  // Order DbgVariableRecord users in reverse-creation order. Normal dbg.value
  // users of MetadataAsValues are ordered by their UseList, i.e. reverse order
  // of when they were added: we need to replicate that here. The structure of
  // debug-info output depends on the ordering of intrinsics, thus we need
  // to keep them consistent for comparisons sake.
  llvm::sort(DVRUsersWithID, [](auto UserA, auto UserB) {
    return UserA->second > UserB->second;
  });
  SmallVector<DbgVariableRecord *> DVRUsers;
  for (auto UserWithID : DVRUsersWithID)
    DVRUsers.push_back(cast<DebugValueUser *>(UserWithID->first)->getUser());
  return DVRUsers;
}

void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) {
  bool WasInserted =
      UseMap.insert(std::make_pair(Ref, std::make_pair(Owner, NextIndex)))
          .second;
  (void)WasInserted;
  assert(WasInserted && "Expected to add a reference");

  ++NextIndex;
  assert(NextIndex != 0 && "Unexpected overflow");
}

void ReplaceableMetadataImpl::dropRef(void *Ref) {
  bool WasErased = UseMap.erase(Ref);
  (void)WasErased;
  assert(WasErased && "Expected to drop a reference");
}

void ReplaceableMetadataImpl::moveRef(void *Ref, void *New,
                                      const Metadata &MD) {
  auto I = UseMap.find(Ref);
  assert(I != UseMap.end() && "Expected to move a reference");
  auto OwnerAndIndex = I->second;
  UseMap.erase(I);
  bool WasInserted = UseMap.insert(std::make_pair(New, OwnerAndIndex)).second;
  (void)WasInserted;
  assert(WasInserted && "Expected to add a reference");

  // Check that the references are direct if there's no owner.
  (void)MD;
  assert((OwnerAndIndex.first || *static_cast<Metadata **>(Ref) == &MD) &&
         "Reference without owner must be direct");
  assert((OwnerAndIndex.first || *static_cast<Metadata **>(New) == &MD) &&
         "Reference without owner must be direct");
}

void ReplaceableMetadataImpl::SalvageDebugInfo(const Constant &C) {
  if (!C.isUsedByMetadata()) {
    return;
  }

  LLVMContext &Context = C.getType()->getContext();
  auto &Store = Context.pImpl->ValuesAsMetadata;
  auto I = Store.find(&C);
  ValueAsMetadata *MD = I->second;
  using UseTy =
      std::pair<void *, std::pair<MetadataTracking::OwnerTy, uint64_t>>;
  // Copy out uses and update value of Constant used by debug info metadata with
  // poison below
  SmallVector<UseTy, 8> Uses(MD->UseMap.begin(), MD->UseMap.end());

  for (const auto &Pair : Uses) {
    MetadataTracking::OwnerTy Owner = Pair.second.first;
    if (!Owner)
      continue;
    // Check for MetadataAsValue.
    if (isa<MetadataAsValue *>(Owner)) {
      cast<MetadataAsValue *>(Owner)->handleChangedMetadata(
          ValueAsMetadata::get(PoisonValue::get(C.getType())));
      continue;
    }
    if (!isa<Metadata *>(Owner))
      continue;
    auto *OwnerMD = dyn_cast_if_present<MDNode>(cast<Metadata *>(Owner));
    if (!OwnerMD)
      continue;
    if (isa<DINode>(OwnerMD)) {
      OwnerMD->handleChangedOperand(
          Pair.first, ValueAsMetadata::get(PoisonValue::get(C.getType())));
    }
  }
}

void ReplaceableMetadataImpl::replaceAllUsesWith(Metadata *MD) {
  if (UseMap.empty())
    return;

  // Copy out uses since UseMap will get touched below.
  using UseTy = std::pair<void *, std::pair<OwnerTy, uint64_t>>;
  SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
  llvm::sort(Uses, [](const UseTy &L, const UseTy &R) {
    return L.second.second < R.second.second;
  });
  for (const auto &Pair : Uses) {
    // Check that this Ref hasn't disappeared after RAUW (when updating a
    // previous Ref).
    if (!UseMap.count(Pair.first))
      continue;

    OwnerTy Owner = Pair.second.first;
    if (!Owner) {
      // Update unowned tracking references directly.
      Metadata *&Ref = *static_cast<Metadata **>(Pair.first);
      Ref = MD;
      if (MD)
        MetadataTracking::track(Ref);
      UseMap.erase(Pair.first);
      continue;
    }

    // Check for MetadataAsValue.
    if (isa<MetadataAsValue *>(Owner)) {
      cast<MetadataAsValue *>(Owner)->handleChangedMetadata(MD);
      continue;
    }

    if (auto *DVU = dyn_cast<DebugValueUser *>(Owner)) {
      DVU->handleChangedValue(Pair.first, MD);
      continue;
    }

    // There's a Metadata owner -- dispatch.
    Metadata *OwnerMD = cast<Metadata *>(Owner);
    switch (OwnerMD->getMetadataID()) {
#define HANDLE_METADATA_LEAF(CLASS)                                            \
  case Metadata::CLASS##Kind:                                                  \
    cast<CLASS>(OwnerMD)->handleChangedOperand(Pair.first, MD);                \
    continue;
#include "llvm/IR/Metadata.def"
    default:
      llvm_unreachable("Invalid metadata subclass");
    }
  }
  assert(UseMap.empty() && "Expected all uses to be replaced");
}

void ReplaceableMetadataImpl::resolveAllUses(bool ResolveUsers) {
  if (UseMap.empty())
    return;

  if (!ResolveUsers) {
    UseMap.clear();
    return;
  }

  // Copy out uses since UseMap could get touched below.
  using UseTy = std::pair<void *, std::pair<OwnerTy, uint64_t>>;
  SmallVector<UseTy, 8> Uses(UseMap.begin(), UseMap.end());
  llvm::sort(Uses, [](const UseTy &L, const UseTy &R) {
    return L.second.second < R.second.second;
  });
  UseMap.clear();
  for (const auto &Pair : Uses) {
    auto Owner = Pair.second.first;
    if (!Owner)
      continue;
    if (!isa<Metadata *>(Owner))
      continue;

    // Resolve MDNodes that point at this.
    auto *OwnerMD = dyn_cast_if_present<MDNode>(cast<Metadata *>(Owner));
    if (!OwnerMD)
      continue;
    if (OwnerMD->isResolved())
      continue;
    OwnerMD->decrementUnresolvedOperandCount();
  }
}

// Special handing of DIArgList is required in the RemoveDIs project, see
// commentry in DIArgList::handleChangedOperand for details. Hidden behind
// conditional compilation to avoid a compile time regression.
ReplaceableMetadataImpl *ReplaceableMetadataImpl::getOrCreate(Metadata &MD) {
  if (auto *N = dyn_cast<MDNode>(&MD)) {
    return !N->isResolved() || N->isAlwaysReplaceable()
               ? N->Context.getOrCreateReplaceableUses()
               : nullptr;
  }
  if (auto ArgList = dyn_cast<DIArgList>(&MD))
    return ArgList;
  return dyn_cast<ValueAsMetadata>(&MD);
}

ReplaceableMetadataImpl *ReplaceableMetadataImpl::getIfExists(Metadata &MD) {
  if (auto *N = dyn_cast<MDNode>(&MD)) {
    return !N->isResolved() || N->isAlwaysReplaceable()
               ? N->Context.getReplaceableUses()
               : nullptr;
  }
  if (auto ArgList = dyn_cast<DIArgList>(&MD))
    return ArgList;
  return dyn_cast<ValueAsMetadata>(&MD);
}

bool ReplaceableMetadataImpl::isReplaceable(const Metadata &MD) {
  if (auto *N = dyn_cast<MDNode>(&MD))
    return !N->isResolved() || N->isAlwaysReplaceable();
  return isa<ValueAsMetadata>(&MD) || isa<DIArgList>(&MD);
}

static DISubprogram *getLocalFunctionMetadata(Value *V) {
  assert(V && "Expected value");
  if (auto *A = dyn_cast<Argument>(V)) {
    if (auto *Fn = A->getParent())
      return Fn->getSubprogram();
    return nullptr;
  }

  if (BasicBlock *BB = cast<Instruction>(V)->getParent()) {
    if (auto *Fn = BB->getParent())
      return Fn->getSubprogram();
    return nullptr;
  }

  return nullptr;
}

ValueAsMetadata *ValueAsMetadata::get(Value *V) {
  assert(V && "Unexpected null Value");

  auto &Context = V->getContext();
  auto *&Entry = Context.pImpl->ValuesAsMetadata[V];
  if (!Entry) {
    assert((isa<Constant>(V) || isa<Argument>(V) || isa<Instruction>(V)) &&
           "Expected constant or function-local value");
    assert(!V->IsUsedByMD && "Expected this to be the only metadata use");
    V->IsUsedByMD = true;
    if (auto *C = dyn_cast<Constant>(V))
      Entry = new ConstantAsMetadata(C);
    else
      Entry = new LocalAsMetadata(V);
  }

  return Entry;
}

ValueAsMetadata *ValueAsMetadata::getIfExists(Value *V) {
  assert(V && "Unexpected null Value");
  return V->getContext().pImpl->ValuesAsMetadata.lookup(V);
}

void ValueAsMetadata::handleDeletion(Value *V) {
  assert(V && "Expected valid value");

  auto &Store = V->getType()->getContext().pImpl->ValuesAsMetadata;
  auto I = Store.find(V);
  if (I == Store.end())
    return;

  // Remove old entry from the map.
  ValueAsMetadata *MD = I->second;
  assert(MD && "Expected valid metadata");
  assert(MD->getValue() == V && "Expected valid mapping");
  Store.erase(I);

  // Delete the metadata.
  MD->replaceAllUsesWith(nullptr);
  delete MD;
}

void ValueAsMetadata::handleRAUW(Value *From, Value *To) {
  assert(From && "Expected valid value");
  assert(To && "Expected valid value");
  assert(From != To && "Expected changed value");
  assert(&From->getContext() == &To->getContext() && "Expected same context");

  LLVMContext &Context = From->getType()->getContext();
  auto &Store = Context.pImpl->ValuesAsMetadata;
  auto I = Store.find(From);
  if (I == Store.end()) {
    assert(!From->IsUsedByMD && "Expected From not to be used by metadata");
    return;
  }

  // Remove old entry from the map.
  assert(From->IsUsedByMD && "Expected From to be used by metadata");
  From->IsUsedByMD = false;
  ValueAsMetadata *MD = I->second;
  assert(MD && "Expected valid metadata");
  assert(MD->getValue() == From && "Expected valid mapping");
  Store.erase(I);

  if (isa<LocalAsMetadata>(MD)) {
    if (auto *C = dyn_cast<Constant>(To)) {
      // Local became a constant.
      MD->replaceAllUsesWith(ConstantAsMetadata::get(C));
      delete MD;
      return;
    }
    if (getLocalFunctionMetadata(From) && getLocalFunctionMetadata(To) &&
        getLocalFunctionMetadata(From) != getLocalFunctionMetadata(To)) {
      // DISubprogram changed.
      MD->replaceAllUsesWith(nullptr);
      delete MD;
      return;
    }
  } else if (!isa<Constant>(To)) {
    // Changed to function-local value.
    MD->replaceAllUsesWith(nullptr);
    delete MD;
    return;
  }

  auto *&Entry = Store[To];
  if (Entry) {
    // The target already exists.
    MD->replaceAllUsesWith(Entry);
    delete MD;
    return;
  }

  // Update MD in place (and update the map entry).
  assert(!To->IsUsedByMD && "Expected this to be the only metadata use");
  To->IsUsedByMD = true;
  MD->V = To;
  Entry = MD;
}

//===----------------------------------------------------------------------===//
// MDString implementation.
//

MDString *MDString::get(LLVMContext &Context, StringRef Str) {
  auto &Store = Context.pImpl->MDStringCache;
  auto I = Store.try_emplace(Str);
  auto &MapEntry = I.first->getValue();
  if (!I.second)
    return &MapEntry;
  MapEntry.Entry = &*I.first;
  return &MapEntry;
}

StringRef MDString::getString() const {
  assert(Entry && "Expected to find string map entry");
  return Entry->first();
}

//===----------------------------------------------------------------------===//
// MDNode implementation.
//

// Assert that the MDNode types will not be unaligned by the objects
// prepended to them.
#define HANDLE_MDNODE_LEAF(CLASS)                                              \
  static_assert(                                                               \
      alignof(uint64_t) >= alignof(CLASS),                                     \
      "Alignment is insufficient after objects prepended to " #CLASS);
#include "llvm/IR/Metadata.def"

void *MDNode::operator new(size_t Size, size_t NumOps, StorageType Storage) {
  // uint64_t is the most aligned type we need support (ensured by static_assert
  // above)
  size_t AllocSize =
      alignTo(Header::getAllocSize(Storage, NumOps), alignof(uint64_t));
  char *Mem = reinterpret_cast<char *>(::operator new(AllocSize + Size));
  Header *H = new (Mem + AllocSize - sizeof(Header)) Header(NumOps, Storage);
  return reinterpret_cast<void *>(H + 1);
}

void MDNode::operator delete(void *N) {
  Header *H = reinterpret_cast<Header *>(N) - 1;
  void *Mem = H->getAllocation();
  H->~Header();
  ::operator delete(Mem);
}

MDNode::MDNode(LLVMContext &Context, unsigned ID, StorageType Storage,
               ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2)
    : Metadata(ID, Storage), Context(Context) {
  unsigned Op = 0;
  for (Metadata *MD : Ops1)
    setOperand(Op++, MD);
  for (Metadata *MD : Ops2)
    setOperand(Op++, MD);

  if (!isUniqued())
    return;

  // Count the unresolved operands.  If there are any, RAUW support will be
  // added lazily on first reference.
  countUnresolvedOperands();
}

TempMDNode MDNode::clone() const {
  switch (getMetadataID()) {
  default:
    llvm_unreachable("Invalid MDNode subclass");
#define HANDLE_MDNODE_LEAF(CLASS)                                              \
  case CLASS##Kind:                                                            \
    return cast<CLASS>(this)->cloneImpl();
#include "llvm/IR/Metadata.def"
  }
}

MDNode::Header::Header(size_t NumOps, StorageType Storage) {
  IsLarge = isLarge(NumOps);
  IsResizable = isResizable(Storage);
  SmallSize = getSmallSize(NumOps, IsResizable, IsLarge);
  if (IsLarge) {
    SmallNumOps = 0;
    new (getLargePtr()) LargeStorageVector();
    getLarge().resize(NumOps);
    return;
  }
  SmallNumOps = NumOps;
  MDOperand *O = reinterpret_cast<MDOperand *>(this) - SmallSize;
  for (MDOperand *E = O + SmallSize; O != E;)
    (void)new (O++) MDOperand();
}

MDNode::Header::~Header() {
  if (IsLarge) {
    getLarge().~LargeStorageVector();
    return;
  }
  MDOperand *O = reinterpret_cast<MDOperand *>(this);
  for (MDOperand *E = O - SmallSize; O != E; --O)
    (O - 1)->~MDOperand();
}

void *MDNode::Header::getSmallPtr() {
  static_assert(alignof(MDOperand) <= alignof(Header),
                "MDOperand too strongly aligned");
  return reinterpret_cast<char *>(const_cast<Header *>(this)) -
         sizeof(MDOperand) * SmallSize;
}

void MDNode::Header::resize(size_t NumOps) {
  assert(IsResizable && "Node is not resizable");
  if (operands().size() == NumOps)
    return;

  if (IsLarge)
    getLarge().resize(NumOps);
  else if (NumOps <= SmallSize)
    resizeSmall(NumOps);
  else
    resizeSmallToLarge(NumOps);
}

void MDNode::Header::resizeSmall(size_t NumOps) {
  assert(!IsLarge && "Expected a small MDNode");
  assert(NumOps <= SmallSize && "NumOps too large for small resize");

  MutableArrayRef<MDOperand> ExistingOps = operands();
  assert(NumOps != ExistingOps.size() && "Expected a different size");

  int NumNew = (int)NumOps - (int)ExistingOps.size();
  MDOperand *O = ExistingOps.end();
  for (int I = 0, E = NumNew; I < E; ++I)
    (O++)->reset();
  for (int I = 0, E = NumNew; I > E; --I)
    (--O)->reset();
  SmallNumOps = NumOps;
  assert(O == operands().end() && "Operands not (un)initialized until the end");
}

void MDNode::Header::resizeSmallToLarge(size_t NumOps) {
  assert(!IsLarge && "Expected a small MDNode");
  assert(NumOps > SmallSize && "Expected NumOps to be larger than allocation");
  LargeStorageVector NewOps;
  NewOps.resize(NumOps);
  llvm::move(operands(), NewOps.begin());
  resizeSmall(0);
  new (getLargePtr()) LargeStorageVector(std::move(NewOps));
  IsLarge = true;
}

static bool isOperandUnresolved(Metadata *Op) {
  if (auto *N = dyn_cast_or_null<MDNode>(Op))
    return !N->isResolved();
  return false;
}

void MDNode::countUnresolvedOperands() {
  assert(getNumUnresolved() == 0 && "Expected unresolved ops to be uncounted");
  assert(isUniqued() && "Expected this to be uniqued");
  setNumUnresolved(count_if(operands(), isOperandUnresolved));
}

void MDNode::makeUniqued() {
  assert(isTemporary() && "Expected this to be temporary");
  assert(!isResolved() && "Expected this to be unresolved");

  // Enable uniquing callbacks.
  for (auto &Op : mutable_operands())
    Op.reset(Op.get(), this);

  // Make this 'uniqued'.
  Storage = Uniqued;
  countUnresolvedOperands();
  if (!getNumUnresolved()) {
    dropReplaceableUses();
    assert(isResolved() && "Expected this to be resolved");
  }

  assert(isUniqued() && "Expected this to be uniqued");
}

void MDNode::makeDistinct() {
  assert(isTemporary() && "Expected this to be temporary");
  assert(!isResolved() && "Expected this to be unresolved");

  // Drop RAUW support and store as a distinct node.
  dropReplaceableUses();
  storeDistinctInContext();

  assert(isDistinct() && "Expected this to be distinct");
  assert(isResolved() && "Expected this to be resolved");
}

void MDNode::resolve() {
  assert(isUniqued() && "Expected this to be uniqued");
  assert(!isResolved() && "Expected this to be unresolved");

  setNumUnresolved(0);
  dropReplaceableUses();

  assert(isResolved() && "Expected this to be resolved");
}

void MDNode::dropReplaceableUses() {
  assert(!getNumUnresolved() && "Unexpected unresolved operand");

  // Drop any RAUW support.
  if (Context.hasReplaceableUses())
    Context.takeReplaceableUses()->resolveAllUses();
}

void MDNode::resolveAfterOperandChange(Metadata *Old, Metadata *New) {
  assert(isUniqued() && "Expected this to be uniqued");
  assert(getNumUnresolved() != 0 && "Expected unresolved operands");

  // Check if an operand was resolved.
  if (!isOperandUnresolved(Old)) {
    if (isOperandUnresolved(New))
      // An operand was un-resolved!
      setNumUnresolved(getNumUnresolved() + 1);
  } else if (!isOperandUnresolved(New))
    decrementUnresolvedOperandCount();
}

void MDNode::decrementUnresolvedOperandCount() {
  assert(!isResolved() && "Expected this to be unresolved");
  if (isTemporary())
    return;

  assert(isUniqued() && "Expected this to be uniqued");
  setNumUnresolved(getNumUnresolved() - 1);
  if (getNumUnresolved())
    return;

  // Last unresolved operand has just been resolved.
  dropReplaceableUses();
  assert(isResolved() && "Expected this to become resolved");
}

void MDNode::resolveCycles() {
  if (isResolved())
    return;

  // Resolve this node immediately.
  resolve();

  // Resolve all operands.
  for (const auto &Op : operands()) {
    auto *N = dyn_cast_or_null<MDNode>(Op);
    if (!N)
      continue;

    assert(!N->isTemporary() &&
           "Expected all forward declarations to be resolved");
    if (!N->isResolved())
      N->resolveCycles();
  }
}

static bool hasSelfReference(MDNode *N) {
  return llvm::is_contained(N->operands(), N);
}

MDNode *MDNode::replaceWithPermanentImpl() {
  switch (getMetadataID()) {
  default:
    // If this type isn't uniquable, replace with a distinct node.
    return replaceWithDistinctImpl();

#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
  case CLASS##Kind:                                                            \
    break;
#include "llvm/IR/Metadata.def"
  }

  // Even if this type is uniquable, self-references have to be distinct.
  if (hasSelfReference(this))
    return replaceWithDistinctImpl();
  return replaceWithUniquedImpl();
}

MDNode *MDNode::replaceWithUniquedImpl() {
  // Try to uniquify in place.
  MDNode *UniquedNode = uniquify();

  if (UniquedNode == this) {
    makeUniqued();
    return this;
  }

  // Collision, so RAUW instead.
  replaceAllUsesWith(UniquedNode);
  deleteAsSubclass();
  return UniquedNode;
}

MDNode *MDNode::replaceWithDistinctImpl() {
  makeDistinct();
  return this;
}

void MDTuple::recalculateHash() {
  setHash(MDTupleInfo::KeyTy::calculateHash(this));
}

void MDNode::dropAllReferences() {
  for (unsigned I = 0, E = getNumOperands(); I != E; ++I)
    setOperand(I, nullptr);
  if (Context.hasReplaceableUses()) {
    Context.getReplaceableUses()->resolveAllUses(/* ResolveUsers */ false);
    (void)Context.takeReplaceableUses();
  }
}

void MDNode::handleChangedOperand(void *Ref, Metadata *New) {
  unsigned Op = static_cast<MDOperand *>(Ref) - op_begin();
  assert(Op < getNumOperands() && "Expected valid operand");

  if (!isUniqued()) {
    // This node is not uniqued.  Just set the operand and be done with it.
    setOperand(Op, New);
    return;
  }

  // This node is uniqued.
  eraseFromStore();

  Metadata *Old = getOperand(Op);
  setOperand(Op, New);

  // Drop uniquing for self-reference cycles and deleted constants.
  if (New == this || (!New && Old && isa<ConstantAsMetadata>(Old))) {
    if (!isResolved())
      resolve();
    storeDistinctInContext();
    return;
  }

  // Re-unique the node.
  auto *Uniqued = uniquify();
  if (Uniqued == this) {
    if (!isResolved())
      resolveAfterOperandChange(Old, New);
    return;
  }

  // Collision.
  if (!isResolved()) {
    // Still unresolved, so RAUW.
    //
    // First, clear out all operands to prevent any recursion (similar to
    // dropAllReferences(), but we still need the use-list).
    for (unsigned O = 0, E = getNumOperands(); O != E; ++O)
      setOperand(O, nullptr);
    if (Context.hasReplaceableUses())
      Context.getReplaceableUses()->replaceAllUsesWith(Uniqued);
    deleteAsSubclass();
    return;
  }

  // Store in non-uniqued form if RAUW isn't possible.
  storeDistinctInContext();
}

void MDNode::deleteAsSubclass() {
  switch (getMetadataID()) {
  default:
    llvm_unreachable("Invalid subclass of MDNode");
#define HANDLE_MDNODE_LEAF(CLASS)                                              \
  case CLASS##Kind:                                                            \
    delete cast<CLASS>(this);                                                  \
    break;
#include "llvm/IR/Metadata.def"
  }
}

template <class T, class InfoT>
static T *uniquifyImpl(T *N, DenseSet<T *, InfoT> &Store) {
  if (T *U = getUniqued(Store, N))
    return U;

  Store.insert(N);
  return N;
}

template <class NodeTy> struct MDNode::HasCachedHash {
  template <class U>
  static std::true_type check(SameType<void (U::*)(unsigned), &U::setHash> *);
  template <class U> static std::false_type check(...);

  static constexpr bool value = decltype(check<NodeTy>(nullptr))::value;
};

MDNode *MDNode::uniquify() {
  assert(!hasSelfReference(this) && "Cannot uniquify a self-referencing node");

  // Try to insert into uniquing store.
  switch (getMetadataID()) {
  default:
    llvm_unreachable("Invalid or non-uniquable subclass of MDNode");
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
  case CLASS##Kind: {                                                          \
    CLASS *SubclassThis = cast<CLASS>(this);                                   \
    dispatchRecalculateHash(SubclassThis);                                     \
    return uniquifyImpl(SubclassThis, getContext().pImpl->CLASS##s);           \
  }
#include "llvm/IR/Metadata.def"
  }
}

void MDNode::eraseFromStore() {
  switch (getMetadataID()) {
  default:
    llvm_unreachable("Invalid or non-uniquable subclass of MDNode");
#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS)                                    \
  case CLASS##Kind:                                                            \
    getContext().pImpl->CLASS##s.erase(cast<CLASS>(this));                     \
    break;
#include "llvm/IR/Metadata.def"
  }
}

MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef<Metadata *> MDs,
                          StorageType Storage, bool ShouldCreate) {
  unsigned Hash = 0;
  if (Storage == Uniqued) {
    MDTupleInfo::KeyTy Key(MDs);
    if (auto *N = getUniqued(Context.pImpl->MDTuples, Key))
      return N;
    if (!ShouldCreate)
      return nullptr;
    Hash = Key.getHash();
  } else {
    assert(ShouldCreate && "Expected non-uniqued nodes to always be created");
  }

  return storeImpl(new (MDs.size(), Storage)
                       MDTuple(Context, Storage, Hash, MDs),
                   Storage, Context.pImpl->MDTuples);
}

void MDNode::deleteTemporary(MDNode *N) {
  assert(N->isTemporary() && "Expected temporary node");
  N->replaceAllUsesWith(nullptr);
  N->deleteAsSubclass();
}

void MDNode::storeDistinctInContext() {
  assert(!Context.hasReplaceableUses() && "Unexpected replaceable uses");
  assert(!getNumUnresolved() && "Unexpected unresolved nodes");
  Storage = Distinct;
  assert(isResolved() && "Expected this to be resolved");

  // Reset the hash.
  switch (getMetadataID()) {
  default:
    llvm_unreachable("Invalid subclass of MDNode");
#define HANDLE_MDNODE_LEAF(CLASS)                                              \
  case CLASS##Kind: {                                                          \
    dispatchResetHash(cast<CLASS>(this));                                      \
    break;                                                                     \
  }
#include "llvm/IR/Metadata.def"
  }

  getContext().pImpl->DistinctMDNodes.push_back(this);
}

void MDNode::replaceOperandWith(unsigned I, Metadata *New) {
  if (getOperand(I) == New)
    return;

  if (!isUniqued()) {
    setOperand(I, New);
    return;
  }

  handleChangedOperand(mutable_begin() + I, New);
}

void MDNode::setOperand(unsigned I, Metadata *New) {
  assert(I < getNumOperands());
  mutable_begin()[I].reset(New, isUniqued() ? this : nullptr);
}

/// Get a node or a self-reference that looks like it.
///
/// Special handling for finding self-references, for use by \a
/// MDNode::concatenate() and \a MDNode::intersect() to maintain behaviour from
/// when self-referencing nodes were still uniqued.  If the first operand has
/// the same operands as \c Ops, return the first operand instead.
static MDNode *getOrSelfReference(LLVMContext &Context,
                                  ArrayRef<Metadata *> Ops) {
  if (!Ops.empty())
    if (MDNode *N = dyn_cast_or_null<MDNode>(Ops[0]))
      if (N->getNumOperands() == Ops.size() && N == N->getOperand(0)) {
        for (unsigned I = 1, E = Ops.size(); I != E; ++I)
          if (Ops[I] != N->getOperand(I))
            return MDNode::get(Context, Ops);
        return N;
      }

  return MDNode::get(Context, Ops);
}

MDNode *MDNode::concatenate(MDNode *A, MDNode *B) {
  if (!A)
    return B;
  if (!B)
    return A;

  SmallSetVector<Metadata *, 4> MDs(A->op_begin(), A->op_end());
  MDs.insert(B->op_begin(), B->op_end());

  // FIXME: This preserves long-standing behaviour, but is it really the right
  // behaviour?  Or was that an unintended side-effect of node uniquing?
  return getOrSelfReference(A->getContext(), MDs.getArrayRef());
}

MDNode *MDNode::intersect(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  SmallSetVector<Metadata *, 4> MDs(A->op_begin(), A->op_end());
  SmallPtrSet<Metadata *, 4> BSet(B->op_begin(), B->op_end());
  MDs.remove_if([&](Metadata *MD) { return !BSet.count(MD); });

  // FIXME: This preserves long-standing behaviour, but is it really the right
  // behaviour?  Or was that an unintended side-effect of node uniquing?
  return getOrSelfReference(A->getContext(), MDs.getArrayRef());
}

MDNode *MDNode::getMostGenericAliasScope(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  // Take the intersection of domains then union the scopes
  // within those domains
  SmallPtrSet<const MDNode *, 16> ADomains;
  SmallPtrSet<const MDNode *, 16> IntersectDomains;
  SmallSetVector<Metadata *, 4> MDs;
  for (const MDOperand &MDOp : A->operands())
    if (const MDNode *NAMD = dyn_cast<MDNode>(MDOp))
      if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain())
        ADomains.insert(Domain);

  for (const MDOperand &MDOp : B->operands())
    if (const MDNode *NAMD = dyn_cast<MDNode>(MDOp))
      if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain())
        if (ADomains.contains(Domain)) {
          IntersectDomains.insert(Domain);
          MDs.insert(MDOp);
        }

  for (const MDOperand &MDOp : A->operands())
    if (const MDNode *NAMD = dyn_cast<MDNode>(MDOp))
      if (const MDNode *Domain = AliasScopeNode(NAMD).getDomain())
        if (IntersectDomains.contains(Domain))
          MDs.insert(MDOp);

  return MDs.empty() ? nullptr
                     : getOrSelfReference(A->getContext(), MDs.getArrayRef());
}

MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  APFloat AVal = mdconst::extract<ConstantFP>(A->getOperand(0))->getValueAPF();
  APFloat BVal = mdconst::extract<ConstantFP>(B->getOperand(0))->getValueAPF();
  if (AVal < BVal)
    return A;
  return B;
}

// Call instructions with branch weights are only used in SamplePGO as
// documented in
/// https://llvm.org/docs/BranchWeightMetadata.html#callinst).
MDNode *MDNode::mergeDirectCallProfMetadata(MDNode *A, MDNode *B,
                                            const Instruction *AInstr,
                                            const Instruction *BInstr) {
  assert(A && B && AInstr && BInstr && "Caller should guarantee");
  auto &Ctx = AInstr->getContext();
  MDBuilder MDHelper(Ctx);

  // LLVM IR verifier verifies !prof metadata has at least 2 operands.
  assert(A->getNumOperands() >= 2 && B->getNumOperands() >= 2 &&
         "!prof annotations should have no less than 2 operands");
  MDString *AMDS = dyn_cast<MDString>(A->getOperand(0));
  MDString *BMDS = dyn_cast<MDString>(B->getOperand(0));
  // LLVM IR verfier verifies first operand is MDString.
  assert(AMDS != nullptr && BMDS != nullptr &&
         "first operand should be a non-null MDString");
  StringRef AProfName = AMDS->getString();
  StringRef BProfName = BMDS->getString();
  if (AProfName == MDProfLabels::BranchWeights &&
      BProfName == MDProfLabels::BranchWeights) {
    ConstantInt *AInstrWeight = mdconst::dyn_extract<ConstantInt>(
        A->getOperand(getBranchWeightOffset(A)));
    ConstantInt *BInstrWeight = mdconst::dyn_extract<ConstantInt>(
        B->getOperand(getBranchWeightOffset(B)));
    assert(AInstrWeight && BInstrWeight && "verified by LLVM verifier");
    return MDNode::get(Ctx,
                       {MDHelper.createString(MDProfLabels::BranchWeights),
                        MDHelper.createConstant(ConstantInt::get(
                            Type::getInt64Ty(Ctx),
                            SaturatingAdd(AInstrWeight->getZExtValue(),
                                          BInstrWeight->getZExtValue())))});
  }
  return nullptr;
}

// Pass in both instructions and nodes. Instruction information (e.g.,
// instruction type) helps interpret profiles and make implementation clearer.
MDNode *MDNode::getMergedProfMetadata(MDNode *A, MDNode *B,
                                      const Instruction *AInstr,
                                      const Instruction *BInstr) {
  // Check that it is legal to merge prof metadata based on the opcode.
  auto IsLegal = [](const Instruction &I) -> bool {
    switch (I.getOpcode()) {
    case Instruction::Invoke:
    case Instruction::Br:
    case Instruction::Switch:
    case Instruction::Call:
    case Instruction::IndirectBr:
    case Instruction::Select:
    case Instruction::CallBr:
      return true;
    default:
      return false;
    }
  };
  if (AInstr && !IsLegal(*AInstr))
    return nullptr;
  if (BInstr && !IsLegal(*BInstr))
    return nullptr;

  if (!(A && B)) {
    return A ? A : B;
  }

  assert(AInstr->getMetadata(LLVMContext::MD_prof) == A &&
         "Caller should guarantee");
  assert(BInstr->getMetadata(LLVMContext::MD_prof) == B &&
         "Caller should guarantee");

  const CallInst *ACall = dyn_cast<CallInst>(AInstr);
  const CallInst *BCall = dyn_cast<CallInst>(BInstr);

  // Both ACall and BCall are direct callsites.
  if (ACall && BCall && ACall->getCalledFunction() &&
      BCall->getCalledFunction())
    return mergeDirectCallProfMetadata(A, B, AInstr, BInstr);

  // The rest of the cases are not implemented but could be added
  // when there are use cases.
  return nullptr;
}

static bool isContiguous(const ConstantRange &A, const ConstantRange &B) {
  return A.getUpper() == B.getLower() || A.getLower() == B.getUpper();
}

static bool canBeMerged(const ConstantRange &A, const ConstantRange &B) {
  return !A.intersectWith(B).isEmptySet() || isContiguous(A, B);
}

static bool tryMergeRange(SmallVectorImpl<ConstantInt *> &EndPoints,
                          ConstantInt *Low, ConstantInt *High) {
  ConstantRange NewRange(Low->getValue(), High->getValue());
  unsigned Size = EndPoints.size();
  const APInt &LB = EndPoints[Size - 2]->getValue();
  const APInt &LE = EndPoints[Size - 1]->getValue();
  ConstantRange LastRange(LB, LE);
  if (canBeMerged(NewRange, LastRange)) {
    ConstantRange Union = LastRange.unionWith(NewRange);
    Type *Ty = High->getType();
    EndPoints[Size - 2] =
        cast<ConstantInt>(ConstantInt::get(Ty, Union.getLower()));
    EndPoints[Size - 1] =
        cast<ConstantInt>(ConstantInt::get(Ty, Union.getUpper()));
    return true;
  }
  return false;
}

static void addRange(SmallVectorImpl<ConstantInt *> &EndPoints,
                     ConstantInt *Low, ConstantInt *High) {
  if (!EndPoints.empty())
    if (tryMergeRange(EndPoints, Low, High))
      return;

  EndPoints.push_back(Low);
  EndPoints.push_back(High);
}

MDNode *MDNode::getMergedCalleeTypeMetadata(const MDNode *A, const MDNode *B) {
  // Drop the callee_type metadata if either of the call instructions do not
  // have it.
  if (!A || !B)
    return nullptr;
  SmallVector<Metadata *, 8> AB;
  SmallPtrSet<Metadata *, 8> MergedCallees;
  auto AddUniqueCallees = [&AB, &MergedCallees](const MDNode *N) {
    for (Metadata *MD : N->operands()) {
      if (MergedCallees.insert(MD).second)
        AB.push_back(MD);
    }
  };
  AddUniqueCallees(A);
  AddUniqueCallees(B);
  return MDNode::get(A->getContext(), AB);
}

MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
  // Given two ranges, we want to compute the union of the ranges. This
  // is slightly complicated by having to combine the intervals and merge
  // the ones that overlap.

  if (!A || !B)
    return nullptr;

  if (A == B)
    return A;

  // First, walk both lists in order of the lower boundary of each interval.
  // At each step, try to merge the new interval to the last one we added.
  SmallVector<ConstantInt *, 4> EndPoints;
  unsigned AI = 0;
  unsigned BI = 0;
  unsigned AN = A->getNumOperands() / 2;
  unsigned BN = B->getNumOperands() / 2;
  while (AI < AN && BI < BN) {
    ConstantInt *ALow = mdconst::extract<ConstantInt>(A->getOperand(2 * AI));
    ConstantInt *BLow = mdconst::extract<ConstantInt>(B->getOperand(2 * BI));

    if (ALow->getValue().slt(BLow->getValue())) {
      addRange(EndPoints, ALow,
               mdconst::extract<ConstantInt>(A->getOperand(2 * AI + 1)));
      ++AI;
    } else {
      addRange(EndPoints, BLow,
               mdconst::extract<ConstantInt>(B->getOperand(2 * BI + 1)));
      ++BI;
    }
  }
  while (AI < AN) {
    addRange(EndPoints, mdconst::extract<ConstantInt>(A->getOperand(2 * AI)),
             mdconst::extract<ConstantInt>(A->getOperand(2 * AI + 1)));
    ++AI;
  }
  while (BI < BN) {
    addRange(EndPoints, mdconst::extract<ConstantInt>(B->getOperand(2 * BI)),
             mdconst::extract<ConstantInt>(B->getOperand(2 * BI + 1)));
    ++BI;
  }

  // We haven't handled wrap in the previous merge,
  // if we have at least 2 ranges (4 endpoints) we have to try to merge
  // the last and first ones.
  unsigned Size = EndPoints.size();
  if (Size > 2) {
    ConstantInt *FB = EndPoints[0];
    ConstantInt *FE = EndPoints[1];
    if (tryMergeRange(EndPoints, FB, FE)) {
      for (unsigned i = 0; i < Size - 2; ++i) {
        EndPoints[i] = EndPoints[i + 2];
      }
      EndPoints.resize(Size - 2);
    }
  }

  // If in the end we have a single range, it is possible that it is now the
  // full range. Just drop the metadata in that case.
  if (EndPoints.size() == 2) {
    ConstantRange Range(EndPoints[0]->getValue(), EndPoints[1]->getValue());
    if (Range.isFullSet())
      return nullptr;
  }

  SmallVector<Metadata *, 4> MDs;
  MDs.reserve(EndPoints.size());
  for (auto *I : EndPoints)
    MDs.push_back(ConstantAsMetadata::get(I));
  return MDNode::get(A->getContext(), MDs);
}

MDNode *MDNode::getMostGenericNoaliasAddrspace(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  if (A == B)
    return A;

  SmallVector<ConstantRange> RangeListA, RangeListB;
  for (unsigned I = 0, E = A->getNumOperands() / 2; I != E; ++I) {
    auto *LowA = mdconst::extract<ConstantInt>(A->getOperand(2 * I + 0));
    auto *HighA = mdconst::extract<ConstantInt>(A->getOperand(2 * I + 1));
    RangeListA.push_back(ConstantRange(LowA->getValue(), HighA->getValue()));
  }

  for (unsigned I = 0, E = B->getNumOperands() / 2; I != E; ++I) {
    auto *LowB = mdconst::extract<ConstantInt>(B->getOperand(2 * I + 0));
    auto *HighB = mdconst::extract<ConstantInt>(B->getOperand(2 * I + 1));
    RangeListB.push_back(ConstantRange(LowB->getValue(), HighB->getValue()));
  }

  ConstantRangeList CRLA(RangeListA);
  ConstantRangeList CRLB(RangeListB);
  ConstantRangeList Result = CRLA.intersectWith(CRLB);
  if (Result.empty())
    return nullptr;

  SmallVector<Metadata *> MDs;
  for (const ConstantRange &CR : Result) {
    MDs.push_back(ConstantAsMetadata::get(
        ConstantInt::get(A->getContext(), CR.getLower())));
    MDs.push_back(ConstantAsMetadata::get(
        ConstantInt::get(A->getContext(), CR.getUpper())));
  }

  return MDNode::get(A->getContext(), MDs);
}

MDNode *MDNode::getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  ConstantInt *AVal = mdconst::extract<ConstantInt>(A->getOperand(0));
  ConstantInt *BVal = mdconst::extract<ConstantInt>(B->getOperand(0));
  if (AVal->getZExtValue() < BVal->getZExtValue())
    return A;
  return B;
}

CaptureComponents MDNode::toCaptureComponents(const MDNode *MD) {
  if (!MD)
    return CaptureComponents::All;

  CaptureComponents CC = CaptureComponents::None;
  for (Metadata *Op : MD->operands()) {
    CaptureComponents Component =
        StringSwitch<CaptureComponents>(cast<MDString>(Op)->getString())
            .Case("address", CaptureComponents::Address)
            .Case("address_is_null", CaptureComponents::AddressIsNull)
            .Case("provenance", CaptureComponents::Provenance)
            .Case("read_provenance", CaptureComponents::ReadProvenance);
    CC |= Component;
  }
  return CC;
}

MDNode *MDNode::fromCaptureComponents(LLVMContext &Ctx, CaptureComponents CC) {
  assert(!capturesNothing(CC) && "Can't encode captures(none)");
  if (capturesAll(CC))
    return nullptr;

  SmallVector<Metadata *> Components;
  if (capturesAddressIsNullOnly(CC))
    Components.push_back(MDString::get(Ctx, "address_is_null"));
  else if (capturesAddress(CC))
    Components.push_back(MDString::get(Ctx, "address"));
  if (capturesReadProvenanceOnly(CC))
    Components.push_back(MDString::get(Ctx, "read_provenance"));
  else if (capturesFullProvenance(CC))
    Components.push_back(MDString::get(Ctx, "provenance"));
  return MDNode::get(Ctx, Components);
}

//===----------------------------------------------------------------------===//
// NamedMDNode implementation.
//

static SmallVector<TrackingMDRef, 4> &getNMDOps(void *Operands) {
  return *(SmallVector<TrackingMDRef, 4> *)Operands;
}

NamedMDNode::NamedMDNode(const Twine &N)
    : Name(N.str()), Operands(new SmallVector<TrackingMDRef, 4>()) {}

NamedMDNode::~NamedMDNode() {
  dropAllReferences();
  delete &getNMDOps(Operands);
}

unsigned NamedMDNode::getNumOperands() const {
  return (unsigned)getNMDOps(Operands).size();
}

MDNode *NamedMDNode::getOperand(unsigned i) const {
  assert(i < getNumOperands() && "Invalid Operand number!");
  auto *N = getNMDOps(Operands)[i].get();
  return cast_or_null<MDNode>(N);
}

void NamedMDNode::addOperand(MDNode *M) { getNMDOps(Operands).emplace_back(M); }

void NamedMDNode::setOperand(unsigned I, MDNode *New) {
  assert(I < getNumOperands() && "Invalid operand number");
  getNMDOps(Operands)[I].reset(New);
}

void NamedMDNode::eraseFromParent() { getParent()->eraseNamedMetadata(this); }

void NamedMDNode::clearOperands() { getNMDOps(Operands).clear(); }

StringRef NamedMDNode::getName() const { return StringRef(Name); }

//===----------------------------------------------------------------------===//
// Instruction Metadata method implementations.
//

MDNode *MDAttachments::lookup(unsigned ID) const {
  for (const auto &A : Attachments)
    if (A.MDKind == ID)
      return A.Node;
  return nullptr;
}

void MDAttachments::get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const {
  for (const auto &A : Attachments)
    if (A.MDKind == ID)
      Result.push_back(A.Node);
}

void MDAttachments::getAll(
    SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
  for (const auto &A : Attachments)
    Result.emplace_back(A.MDKind, A.Node);

  // Sort the resulting array so it is stable with respect to metadata IDs. We
  // need to preserve the original insertion order though.
  if (Result.size() > 1)
    llvm::stable_sort(Result, less_first());
}

void MDAttachments::set(unsigned ID, MDNode *MD) {
  erase(ID);
  if (MD)
    insert(ID, *MD);
}

void MDAttachments::insert(unsigned ID, MDNode &MD) {
  Attachments.push_back({ID, TrackingMDNodeRef(&MD)});
}

bool MDAttachments::erase(unsigned ID) {
  if (empty())
    return false;

  // Common case is one value.
  if (Attachments.size() == 1 && Attachments.back().MDKind == ID) {
    Attachments.pop_back();
    return true;
  }

  auto OldSize = Attachments.size();
  llvm::erase_if(Attachments,
                 [ID](const Attachment &A) { return A.MDKind == ID; });
  return OldSize != Attachments.size();
}

MDNode *Value::getMetadata(StringRef Kind) const {
  if (!hasMetadata())
    return nullptr;
  unsigned KindID = getContext().getMDKindID(Kind);
  return getMetadataImpl(KindID);
}

MDNode *Value::getMetadataImpl(unsigned KindID) const {
  const LLVMContext &Ctx = getContext();
  const MDAttachments &Attachements = Ctx.pImpl->ValueMetadata.at(this);
  return Attachements.lookup(KindID);
}

void Value::getMetadata(unsigned KindID, SmallVectorImpl<MDNode *> &MDs) const {
  if (hasMetadata())
    getContext().pImpl->ValueMetadata.at(this).get(KindID, MDs);
}

void Value::getMetadata(StringRef Kind, SmallVectorImpl<MDNode *> &MDs) const {
  if (hasMetadata())
    getMetadata(getContext().getMDKindID(Kind), MDs);
}

void Value::getAllMetadata(
    SmallVectorImpl<std::pair<unsigned, MDNode *>> &MDs) const {
  if (hasMetadata()) {
    assert(getContext().pImpl->ValueMetadata.count(this) &&
           "bit out of sync with hash table");
    const MDAttachments &Info = getContext().pImpl->ValueMetadata.at(this);
    Info.getAll(MDs);
  }
}

void Value::setMetadata(unsigned KindID, MDNode *Node) {
  assert(isa<Instruction>(this) || isa<GlobalObject>(this));

  // Handle the case when we're adding/updating metadata on a value.
  if (Node) {
    MDAttachments &Info = getContext().pImpl->ValueMetadata[this];
    assert(!Info.empty() == HasMetadata && "bit out of sync with hash table");
    if (Info.empty())
      HasMetadata = true;
    Info.set(KindID, Node);
    return;
  }

  // Otherwise, we're removing metadata from an instruction.
  assert((HasMetadata == (getContext().pImpl->ValueMetadata.count(this) > 0)) &&
         "bit out of sync with hash table");
  if (!HasMetadata)
    return; // Nothing to remove!
  MDAttachments &Info = getContext().pImpl->ValueMetadata.find(this)->second;

  // Handle removal of an existing value.
  Info.erase(KindID);
  if (!Info.empty())
    return;
  getContext().pImpl->ValueMetadata.erase(this);
  HasMetadata = false;
}

void Value::setMetadata(StringRef Kind, MDNode *Node) {
  if (!Node && !HasMetadata)
    return;
  setMetadata(getContext().getMDKindID(Kind), Node);
}

void Value::addMetadata(unsigned KindID, MDNode &MD) {
  assert(isa<Instruction>(this) || isa<GlobalObject>(this));
  if (!HasMetadata)
    HasMetadata = true;
  getContext().pImpl->ValueMetadata[this].insert(KindID, MD);
}

void Value::addMetadata(StringRef Kind, MDNode &MD) {
  addMetadata(getContext().getMDKindID(Kind), MD);
}

bool Value::eraseMetadata(unsigned KindID) {
  // Nothing to unset.
  if (!HasMetadata)
    return false;

  MDAttachments &Store = getContext().pImpl->ValueMetadata.find(this)->second;
  bool Changed = Store.erase(KindID);
  if (Store.empty())
    clearMetadata();
  return Changed;
}

void Value::eraseMetadataIf(function_ref<bool(unsigned, MDNode *)> Pred) {
  if (!HasMetadata)
    return;

  auto &MetadataStore = getContext().pImpl->ValueMetadata;
  MDAttachments &Info = MetadataStore.find(this)->second;
  assert(!Info.empty() && "bit out of sync with hash table");
  Info.remove_if([Pred](const MDAttachments::Attachment &I) {
    return Pred(I.MDKind, I.Node);
  });

  if (Info.empty())
    clearMetadata();
}

void Value::clearMetadata() {
  if (!HasMetadata)
    return;
  assert(getContext().pImpl->ValueMetadata.count(this) &&
         "bit out of sync with hash table");
  getContext().pImpl->ValueMetadata.erase(this);
  HasMetadata = false;
}

void Instruction::setMetadata(StringRef Kind, MDNode *Node) {
  if (!Node && !hasMetadata())
    return;
  setMetadata(getContext().getMDKindID(Kind), Node);
}

MDNode *Instruction::getMetadataImpl(StringRef Kind) const {
  const LLVMContext &Ctx = getContext();
  unsigned KindID = Ctx.getMDKindID(Kind);
  if (KindID == LLVMContext::MD_dbg)
    return DbgLoc.getAsMDNode();
  return Value::getMetadata(KindID);
}

void Instruction::eraseMetadataIf(function_ref<bool(unsigned, MDNode *)> Pred) {
  if (DbgLoc && Pred(LLVMContext::MD_dbg, DbgLoc.getAsMDNode()))
    DbgLoc = {};

  Value::eraseMetadataIf(Pred);
}

void Instruction::dropUnknownNonDebugMetadata(ArrayRef<unsigned> KnownIDs) {
  if (!Value::hasMetadata())
    return; // Nothing to remove!

  SmallSet<unsigned, 32> KnownSet(llvm::from_range, KnownIDs);

  // A DIAssignID attachment is debug metadata, don't drop it.
  KnownSet.insert(LLVMContext::MD_DIAssignID);

  Value::eraseMetadataIf([&KnownSet](unsigned MDKind, MDNode *Node) {
    return !KnownSet.count(MDKind);
  });
}

void Instruction::updateDIAssignIDMapping(DIAssignID *ID) {
  auto &IDToInstrs = getContext().pImpl->AssignmentIDToInstrs;
  if (const DIAssignID *CurrentID =
          cast_or_null<DIAssignID>(getMetadata(LLVMContext::MD_DIAssignID))) {
    // Nothing to do if the ID isn't changing.
    if (ID == CurrentID)
      return;

    // Unmap this instruction from its current ID.
    auto InstrsIt = IDToInstrs.find(CurrentID);
    assert(InstrsIt != IDToInstrs.end() &&
           "Expect existing attachment to be mapped");

    auto &InstVec = InstrsIt->second;
    auto *InstIt = llvm::find(InstVec, this);
    assert(InstIt != InstVec.end() &&
           "Expect instruction to be mapped to attachment");
    // The vector contains a ptr to this. If this is the only element in the
    // vector, remove the ID:vector entry, otherwise just remove the
    // instruction from the vector.
    if (InstVec.size() == 1)
      IDToInstrs.erase(InstrsIt);
    else
      InstVec.erase(InstIt);
  }

  // Map this instruction to the new ID.
  if (ID)
    IDToInstrs[ID].push_back(this);
}

void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
  if (!Node && !hasMetadata())
    return;

  // Handle 'dbg' as a special case since it is not stored in the hash table.
  if (KindID == LLVMContext::MD_dbg) {
    DbgLoc = DebugLoc(Node);
    return;
  }

  // Update DIAssignID to Instruction(s) mapping.
  if (KindID == LLVMContext::MD_DIAssignID) {
    // The DIAssignID tracking infrastructure doesn't support RAUWing temporary
    // nodes with DIAssignIDs. The cast_or_null below would also catch this, but
    // having a dedicated assert helps make this obvious.
    assert((!Node || !Node->isTemporary()) &&
           "Temporary DIAssignIDs are invalid");
    updateDIAssignIDMapping(cast_or_null<DIAssignID>(Node));
  }

  Value::setMetadata(KindID, Node);
}

void Instruction::addAnnotationMetadata(SmallVector<StringRef> Annotations) {
  SmallVector<Metadata *, 4> Names;
  if (auto *Existing = getMetadata(LLVMContext::MD_annotation)) {
    SmallSetVector<StringRef, 2> AnnotationsSet(Annotations.begin(),
                                                Annotations.end());
    auto *Tuple = cast<MDTuple>(Existing);
    for (auto &N : Tuple->operands()) {
      if (isa<MDString>(N.get())) {
        Names.push_back(N);
        continue;
      }
      auto *MDAnnotationTuple = cast<MDTuple>(N);
      if (any_of(MDAnnotationTuple->operands(), [&AnnotationsSet](auto &Op) {
            return AnnotationsSet.contains(cast<MDString>(Op)->getString());
          }))
        return;
      Names.push_back(N);
    }
  }

  MDBuilder MDB(getContext());
  SmallVector<Metadata *> MDAnnotationStrings;
  for (StringRef Annotation : Annotations)
    MDAnnotationStrings.push_back(MDB.createString(Annotation));
  MDNode *InfoTuple = MDTuple::get(getContext(), MDAnnotationStrings);
  Names.push_back(InfoTuple);
  MDNode *MD = MDTuple::get(getContext(), Names);
  setMetadata(LLVMContext::MD_annotation, MD);
}

void Instruction::addAnnotationMetadata(StringRef Name) {
  SmallVector<Metadata *, 4> Names;
  if (auto *Existing = getMetadata(LLVMContext::MD_annotation)) {
    auto *Tuple = cast<MDTuple>(Existing);
    for (auto &N : Tuple->operands()) {
      if (isa<MDString>(N.get()) &&
          cast<MDString>(N.get())->getString() == Name)
        return;
      Names.push_back(N.get());
    }
  }

  MDBuilder MDB(getContext());
  Names.push_back(MDB.createString(Name));
  MDNode *MD = MDTuple::get(getContext(), Names);
  setMetadata(LLVMContext::MD_annotation, MD);
}

AAMDNodes Instruction::getAAMetadata() const {
  AAMDNodes Result;
  // Not using Instruction::hasMetadata() because we're not interested in
  // DebugInfoMetadata.
  if (Value::hasMetadata()) {
    const MDAttachments &Info = getContext().pImpl->ValueMetadata.at(this);
    Result.TBAA = Info.lookup(LLVMContext::MD_tbaa);
    Result.TBAAStruct = Info.lookup(LLVMContext::MD_tbaa_struct);
    Result.Scope = Info.lookup(LLVMContext::MD_alias_scope);
    Result.NoAlias = Info.lookup(LLVMContext::MD_noalias);
    Result.NoAliasAddrSpace = Info.lookup(LLVMContext::MD_noalias_addrspace);
  }
  return Result;
}

void Instruction::setAAMetadata(const AAMDNodes &N) {
  setMetadata(LLVMContext::MD_tbaa, N.TBAA);
  setMetadata(LLVMContext::MD_tbaa_struct, N.TBAAStruct);
  setMetadata(LLVMContext::MD_alias_scope, N.Scope);
  setMetadata(LLVMContext::MD_noalias, N.NoAlias);
  setMetadata(LLVMContext::MD_noalias_addrspace, N.NoAliasAddrSpace);
}

void Instruction::setNoSanitizeMetadata() {
  setMetadata(llvm::LLVMContext::MD_nosanitize,
              llvm::MDNode::get(getContext(), {}));
}

void Instruction::getAllMetadataImpl(
    SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
  Result.clear();

  // Handle 'dbg' as a special case since it is not stored in the hash table.
  if (DbgLoc) {
    Result.push_back(
        std::make_pair((unsigned)LLVMContext::MD_dbg, DbgLoc.getAsMDNode()));
  }
  Value::getAllMetadata(Result);
}

bool Instruction::extractProfTotalWeight(uint64_t &TotalVal) const {
  assert(
      (getOpcode() == Instruction::Br || getOpcode() == Instruction::Select ||
       getOpcode() == Instruction::Call || getOpcode() == Instruction::Invoke ||
       getOpcode() == Instruction::IndirectBr ||
       getOpcode() == Instruction::Switch) &&
      "Looking for branch weights on something besides branch");

  return ::extractProfTotalWeight(*this, TotalVal);
}

void GlobalObject::copyMetadata(const GlobalObject *Other, unsigned Offset) {
  SmallVector<std::pair<unsigned, MDNode *>, 8> MDs;
  Other->getAllMetadata(MDs);
  for (auto &MD : MDs) {
    // We need to adjust the type metadata offset.
    if (Offset != 0 && MD.first == LLVMContext::MD_type) {
      auto *OffsetConst = cast<ConstantInt>(
          cast<ConstantAsMetadata>(MD.second->getOperand(0))->getValue());
      Metadata *TypeId = MD.second->getOperand(1);
      auto *NewOffsetMD = ConstantAsMetadata::get(ConstantInt::get(
          OffsetConst->getType(), OffsetConst->getValue() + Offset));
      addMetadata(LLVMContext::MD_type,
                  *MDNode::get(getContext(), {NewOffsetMD, TypeId}));
      continue;
    }
    // If an offset adjustment was specified we need to modify the DIExpression
    // to prepend the adjustment:
    // !DIExpression(DW_OP_plus, Offset, [original expr])
    auto *Attachment = MD.second;
    if (Offset != 0 && MD.first == LLVMContext::MD_dbg) {
      DIGlobalVariable *GV = dyn_cast<DIGlobalVariable>(Attachment);
      DIExpression *E = nullptr;
      if (!GV) {
        auto *GVE = cast<DIGlobalVariableExpression>(Attachment);
        GV = GVE->getVariable();
        E = GVE->getExpression();
      }
      ArrayRef<uint64_t> OrigElements;
      if (E)
        OrigElements = E->getElements();
      std::vector<uint64_t> Elements(OrigElements.size() + 2);
      Elements[0] = dwarf::DW_OP_plus_uconst;
      Elements[1] = Offset;
      llvm::copy(OrigElements, Elements.begin() + 2);
      E = DIExpression::get(getContext(), Elements);
      Attachment = DIGlobalVariableExpression::get(getContext(), GV, E);
    }
    addMetadata(MD.first, *Attachment);
  }
}

void GlobalObject::addTypeMetadata(unsigned Offset, Metadata *TypeID) {
  addMetadata(
      LLVMContext::MD_type,
      *MDTuple::get(getContext(),
                    {ConstantAsMetadata::get(ConstantInt::get(
                         Type::getInt64Ty(getContext()), Offset)),
                     TypeID}));
}

void GlobalObject::setVCallVisibilityMetadata(VCallVisibility Visibility) {
  // Remove any existing vcall visibility metadata first in case we are
  // updating.
  eraseMetadata(LLVMContext::MD_vcall_visibility);
  addMetadata(LLVMContext::MD_vcall_visibility,
              *MDNode::get(getContext(),
                           {ConstantAsMetadata::get(ConstantInt::get(
                               Type::getInt64Ty(getContext()), Visibility))}));
}

GlobalObject::VCallVisibility GlobalObject::getVCallVisibility() const {
  if (MDNode *MD = getMetadata(LLVMContext::MD_vcall_visibility)) {
    uint64_t Val = cast<ConstantInt>(
                       cast<ConstantAsMetadata>(MD->getOperand(0))->getValue())
                       ->getZExtValue();
    assert(Val <= 2 && "unknown vcall visibility!");
    return (VCallVisibility)Val;
  }
  return VCallVisibility::VCallVisibilityPublic;
}

void Function::setSubprogram(DISubprogram *SP) {
  setMetadata(LLVMContext::MD_dbg, SP);
}

DISubprogram *Function::getSubprogram() const {
  return cast_or_null<DISubprogram>(getMetadata(LLVMContext::MD_dbg));
}

bool Function::shouldEmitDebugInfoForProfiling() const {
  if (DISubprogram *SP = getSubprogram()) {
    if (DICompileUnit *CU = SP->getUnit()) {
      return CU->getDebugInfoForProfiling();
    }
  }
  return false;
}

void GlobalVariable::addDebugInfo(DIGlobalVariableExpression *GV) {
  addMetadata(LLVMContext::MD_dbg, *GV);
}

void GlobalVariable::getDebugInfo(
    SmallVectorImpl<DIGlobalVariableExpression *> &GVs) const {
  SmallVector<MDNode *, 1> MDs;
  getMetadata(LLVMContext::MD_dbg, MDs);
  for (MDNode *MD : MDs)
    GVs.push_back(cast<DIGlobalVariableExpression>(MD));
}
