//===- 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/CommandLine.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;

namespace llvm {
extern cl::opt<bool> ProfcheckDisableMetadataFixes;
}

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;
}

MDString *MDString::getIfExists(LLVMContext &Context, StringRef Str) {
  auto &Store = Context.pImpl->MDStringCache;
  auto I = Store.find(Str);
  if (I == Store.end())
    return nullptr;
  return &I->getValue();
}

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::CondBr:
    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);

  if (A == B && !ProfcheckDisableMetadataFixes)
    return A;

  // 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::getMostGenericNoFPClass(MDNode *A, MDNode *B) {
  if (!A || !B)
    return nullptr;

  if (A == B)
    return A;

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

  return MDNode::get(A->getContext(), ConstantAsMetadata::get(ConstantInt::get(
                                          AVal->getType(), Intersect)));
}

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::CondBr ||
          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));
}
