//===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
//
// 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 defines various helper methods and classes used by
// LLVMContextImpl for creating and managing constants.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
#define LLVM_LIB_IR_CONSTANTSCONTEXT_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/OperandTraits.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <utility>

#define DEBUG_TYPE "ir"

namespace llvm {

/// CastConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement cast constant exprs.
class CastConstantExpr final : public ConstantExpr {
public:
  CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
    : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
    Op<0>() = C;
  }

  // allocate space for exactly one operand
  void *operator new(size_t S) { return User::operator new(S, 1); }
  void operator delete(void *Ptr) { User::operator delete(Ptr); }

  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return Instruction::isCast(CE->getOpcode());
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs.
class BinaryConstantExpr final : public ConstantExpr {
public:
  BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
                     unsigned Flags)
    : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
    Op<0>() = C1;
    Op<1>() = C2;
    SubclassOptionalData = Flags;
  }

  // allocate space for exactly two operands
  void *operator new(size_t S) { return User::operator new(S, 2); }
  void operator delete(void *Ptr) { User::operator delete(Ptr); }

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return Instruction::isBinaryOp(CE->getOpcode());
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

/// ExtractElementConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// extractelement constant exprs.
class ExtractElementConstantExpr final : public ConstantExpr {
public:
  ExtractElementConstantExpr(Constant *C1, Constant *C2)
    : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
                   Instruction::ExtractElement, &Op<0>(), 2) {
    Op<0>() = C1;
    Op<1>() = C2;
  }

  // allocate space for exactly two operands
  void *operator new(size_t S) { return User::operator new(S, 2); }
  void operator delete(void *Ptr) { User::operator delete(Ptr); }

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return CE->getOpcode() == Instruction::ExtractElement;
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

/// InsertElementConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// insertelement constant exprs.
class InsertElementConstantExpr final : public ConstantExpr {
public:
  InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
    : ConstantExpr(C1->getType(), Instruction::InsertElement,
                   &Op<0>(), 3) {
    Op<0>() = C1;
    Op<1>() = C2;
    Op<2>() = C3;
  }

  // allocate space for exactly three operands
  void *operator new(size_t S) { return User::operator new(S, 3); }
  void operator delete(void *Ptr) { User::operator delete(Ptr); }

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return CE->getOpcode() == Instruction::InsertElement;
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

/// ShuffleVectorConstantExpr - This class is private to
/// Constants.cpp, and is used behind the scenes to implement
/// shufflevector constant exprs.
class ShuffleVectorConstantExpr final : public ConstantExpr {
public:
  ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)
      : ConstantExpr(VectorType::get(
                         cast<VectorType>(C1->getType())->getElementType(),
                         Mask.size(), isa<ScalableVectorType>(C1->getType())),
                     Instruction::ShuffleVector, &Op<0>(), 2) {
    assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&
           "Invalid shuffle vector instruction operands!");
    Op<0>() = C1;
    Op<1>() = C2;
    ShuffleMask.assign(Mask.begin(), Mask.end());
    ShuffleMaskForBitcode =
        ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType());
  }

  SmallVector<int, 4> ShuffleMask;
  Constant *ShuffleMaskForBitcode;

  void *operator new(size_t S) { return User::operator new(S, 2); }
  void operator delete(void *Ptr) { return User::operator delete(Ptr); }

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return CE->getOpcode() == Instruction::ShuffleVector;
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs.
class GetElementPtrConstantExpr final : public ConstantExpr {
  Type *SrcElementTy;
  Type *ResElementTy;

  GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
                            ArrayRef<Constant *> IdxList, Type *DestTy);

public:
  static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
                                           ArrayRef<Constant *> IdxList,
                                           Type *DestTy, unsigned Flags) {
    GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)
        GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy);
    Result->SubclassOptionalData = Flags;
    return Result;
  }

  Type *getSourceElementType() const;
  Type *getResultElementType() const;

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return CE->getOpcode() == Instruction::GetElementPtr;
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

// CompareConstantExpr - This class is private to Constants.cpp, and is used
// behind the scenes to implement ICmp and FCmp constant expressions. This is
// needed in order to store the predicate value for these instructions.
class CompareConstantExpr final : public ConstantExpr {
public:
  unsigned short predicate;
  CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
                      unsigned short pred,  Constant* LHS, Constant* RHS)
    : ConstantExpr(ty, opc, &Op<0>(), 2), predicate(pred) {
    Op<0>() = LHS;
    Op<1>() = RHS;
  }

  // allocate space for exactly two operands
  void *operator new(size_t S) { return User::operator new(S, 2); }
  void operator delete(void *Ptr) { return User::operator delete(Ptr); }

  /// Transparently provide more efficient getOperand methods.
  DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);

  static bool classof(const ConstantExpr *CE) {
    return CE->getOpcode() == Instruction::ICmp ||
           CE->getOpcode() == Instruction::FCmp;
  }
  static bool classof(const Value *V) {
    return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
  }
};

template <>
struct OperandTraits<CastConstantExpr>
    : public FixedNumOperandTraits<CastConstantExpr, 1> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value)

template <>
struct OperandTraits<BinaryConstantExpr>
    : public FixedNumOperandTraits<BinaryConstantExpr, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)

template <>
struct OperandTraits<ExtractElementConstantExpr>
    : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)

template <>
struct OperandTraits<InsertElementConstantExpr>
    : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)

template <>
struct OperandTraits<ShuffleVectorConstantExpr>
    : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)

template <>
struct OperandTraits<GetElementPtrConstantExpr>
    : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {};

DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)

template <>
struct OperandTraits<CompareConstantExpr>
    : public FixedNumOperandTraits<CompareConstantExpr, 2> {};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)

template <class ConstantClass> struct ConstantAggrKeyType;
struct InlineAsmKeyType;
struct ConstantExprKeyType;

template <class ConstantClass> struct ConstantInfo;
template <> struct ConstantInfo<ConstantExpr> {
  using ValType = ConstantExprKeyType;
  using TypeClass = Type;
};
template <> struct ConstantInfo<InlineAsm> {
  using ValType = InlineAsmKeyType;
  using TypeClass = PointerType;
};
template <> struct ConstantInfo<ConstantArray> {
  using ValType = ConstantAggrKeyType<ConstantArray>;
  using TypeClass = ArrayType;
};
template <> struct ConstantInfo<ConstantStruct> {
  using ValType = ConstantAggrKeyType<ConstantStruct>;
  using TypeClass = StructType;
};
template <> struct ConstantInfo<ConstantVector> {
  using ValType = ConstantAggrKeyType<ConstantVector>;
  using TypeClass = VectorType;
};

template <class ConstantClass> struct ConstantAggrKeyType {
  ArrayRef<Constant *> Operands;

  ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}

  ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
      : Operands(Operands) {}

  ConstantAggrKeyType(const ConstantClass *C,
                      SmallVectorImpl<Constant *> &Storage) {
    assert(Storage.empty() && "Expected empty storage");
    for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
      Storage.push_back(C->getOperand(I));
    Operands = Storage;
  }

  bool operator==(const ConstantAggrKeyType &X) const {
    return Operands == X.Operands;
  }

  bool operator==(const ConstantClass *C) const {
    if (Operands.size() != C->getNumOperands())
      return false;
    for (unsigned I = 0, E = Operands.size(); I != E; ++I)
      if (Operands[I] != C->getOperand(I))
        return false;
    return true;
  }

  unsigned getHash() const {
    return hash_combine_range(Operands.begin(), Operands.end());
  }

  using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;

  ConstantClass *create(TypeClass *Ty) const {
    return new (Operands.size()) ConstantClass(Ty, Operands);
  }
};

struct InlineAsmKeyType {
  StringRef AsmString;
  StringRef Constraints;
  FunctionType *FTy;
  bool HasSideEffects;
  bool IsAlignStack;
  InlineAsm::AsmDialect AsmDialect;
  bool CanThrow;

  InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
                   FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,
                   InlineAsm::AsmDialect AsmDialect, bool canThrow)
      : AsmString(AsmString), Constraints(Constraints), FTy(FTy),
        HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
        AsmDialect(AsmDialect), CanThrow(canThrow) {}

  InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
      : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
        FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),
        IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),
        CanThrow(Asm->canThrow()) {}

  bool operator==(const InlineAsmKeyType &X) const {
    return HasSideEffects == X.HasSideEffects &&
           IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
           AsmString == X.AsmString && Constraints == X.Constraints &&
           FTy == X.FTy && CanThrow == X.CanThrow;
  }

  bool operator==(const InlineAsm *Asm) const {
    return HasSideEffects == Asm->hasSideEffects() &&
           IsAlignStack == Asm->isAlignStack() &&
           AsmDialect == Asm->getDialect() &&
           AsmString == Asm->getAsmString() &&
           Constraints == Asm->getConstraintString() &&
           FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();
  }

  unsigned getHash() const {
    return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
                        AsmDialect, FTy, CanThrow);
  }

  using TypeClass = ConstantInfo<InlineAsm>::TypeClass;

  InlineAsm *create(TypeClass *Ty) const {
    assert(PointerType::getUnqual(FTy) == Ty);
    return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),
                         HasSideEffects, IsAlignStack, AsmDialect, CanThrow);
  }
};

struct ConstantExprKeyType {
private:
  uint8_t Opcode;
  uint8_t SubclassOptionalData;
  uint16_t SubclassData;
  ArrayRef<Constant *> Ops;
  ArrayRef<int> ShuffleMask;
  Type *ExplicitTy;

  static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
    if (CE->getOpcode() == Instruction::ShuffleVector)
      return CE->getShuffleMask();
    return std::nullopt;
  }

  static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {
    if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
      return GEPCE->getSourceElementType();
    return nullptr;
  }

public:
  ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
                      unsigned short SubclassData = 0,
                      unsigned short SubclassOptionalData = 0,
                      ArrayRef<int> ShuffleMask = std::nullopt,
                      Type *ExplicitTy = nullptr)
      : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
        SubclassData(SubclassData), Ops(Ops), ShuffleMask(ShuffleMask),
        ExplicitTy(ExplicitTy) {}

  ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
      : Opcode(CE->getOpcode()),
        SubclassOptionalData(CE->getRawSubclassOptionalData()),
        SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands),
        ShuffleMask(getShuffleMaskIfValid(CE)),
        ExplicitTy(getSourceElementTypeIfValid(CE)) {}

  ConstantExprKeyType(const ConstantExpr *CE,
                      SmallVectorImpl<Constant *> &Storage)
      : Opcode(CE->getOpcode()),
        SubclassOptionalData(CE->getRawSubclassOptionalData()),
        SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
        ShuffleMask(getShuffleMaskIfValid(CE)),
        ExplicitTy(getSourceElementTypeIfValid(CE)) {
    assert(Storage.empty() && "Expected empty storage");
    for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
      Storage.push_back(CE->getOperand(I));
    Ops = Storage;
  }

  bool operator==(const ConstantExprKeyType &X) const {
    return Opcode == X.Opcode && SubclassData == X.SubclassData &&
           SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
           ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy;
  }

  bool operator==(const ConstantExpr *CE) const {
    if (Opcode != CE->getOpcode())
      return false;
    if (SubclassOptionalData != CE->getRawSubclassOptionalData())
      return false;
    if (Ops.size() != CE->getNumOperands())
      return false;
    if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
      return false;
    for (unsigned I = 0, E = Ops.size(); I != E; ++I)
      if (Ops[I] != CE->getOperand(I))
        return false;
    if (ShuffleMask != getShuffleMaskIfValid(CE))
      return false;
    if (ExplicitTy != getSourceElementTypeIfValid(CE))
      return false;
    return true;
  }

  unsigned getHash() const {
    return hash_combine(
        Opcode, SubclassOptionalData, SubclassData,
        hash_combine_range(Ops.begin(), Ops.end()),
        hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy);
  }

  using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;

  ConstantExpr *create(TypeClass *Ty) const {
    switch (Opcode) {
    default:
      if (Instruction::isCast(Opcode))
        return new CastConstantExpr(Opcode, Ops[0], Ty);
      if ((Opcode >= Instruction::BinaryOpsBegin &&
           Opcode < Instruction::BinaryOpsEnd))
        return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
                                      SubclassOptionalData);
      llvm_unreachable("Invalid ConstantExpr!");
    case Instruction::ExtractElement:
      return new ExtractElementConstantExpr(Ops[0], Ops[1]);
    case Instruction::InsertElement:
      return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
    case Instruction::ShuffleVector:
      return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
    case Instruction::GetElementPtr:
      return GetElementPtrConstantExpr::Create(ExplicitTy, Ops[0], Ops.slice(1),
                                               Ty, SubclassOptionalData);
    case Instruction::ICmp:
      return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
                                     Ops[0], Ops[1]);
    case Instruction::FCmp:
      return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
                                     Ops[0], Ops[1]);
    }
  }
};

// Free memory for a given constant.  Assumes the constant has already been
// removed from all relevant maps.
void deleteConstant(Constant *C);

template <class ConstantClass> class ConstantUniqueMap {
public:
  using ValType = typename ConstantInfo<ConstantClass>::ValType;
  using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
  using LookupKey = std::pair<TypeClass *, ValType>;

  /// Key and hash together, so that we compute the hash only once and reuse it.
  using LookupKeyHashed = std::pair<unsigned, LookupKey>;

private:
  struct MapInfo {
    using ConstantClassInfo = DenseMapInfo<ConstantClass *>;

    static inline ConstantClass *getEmptyKey() {
      return ConstantClassInfo::getEmptyKey();
    }

    static inline ConstantClass *getTombstoneKey() {
      return ConstantClassInfo::getTombstoneKey();
    }

    static unsigned getHashValue(const ConstantClass *CP) {
      SmallVector<Constant *, 32> Storage;
      return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
    }

    static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
      return LHS == RHS;
    }

    static unsigned getHashValue(const LookupKey &Val) {
      return hash_combine(Val.first, Val.second.getHash());
    }

    static unsigned getHashValue(const LookupKeyHashed &Val) {
      return Val.first;
    }

    static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
      if (RHS == getEmptyKey() || RHS == getTombstoneKey())
        return false;
      if (LHS.first != RHS->getType())
        return false;
      return LHS.second == RHS;
    }

    static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
      return isEqual(LHS.second, RHS);
    }
  };

public:
  using MapTy = DenseSet<ConstantClass *, MapInfo>;

private:
  MapTy Map;

public:
  typename MapTy::iterator begin() { return Map.begin(); }
  typename MapTy::iterator end() { return Map.end(); }

  void freeConstants() {
    for (auto &I : Map)
      deleteConstant(I);
  }

private:
  ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
    ConstantClass *Result = V.create(Ty);

    assert(Result->getType() == Ty && "Type specified is not correct!");
    Map.insert_as(Result, HashKey);

    return Result;
  }

public:
  /// Return the specified constant from the map, creating it if necessary.
  ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
    LookupKey Key(Ty, V);
    /// Hash once, and reuse it for the lookup and the insertion if needed.
    LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);

    ConstantClass *Result = nullptr;

    auto I = Map.find_as(Lookup);
    if (I == Map.end())
      Result = create(Ty, V, Lookup);
    else
      Result = *I;
    assert(Result && "Unexpected nullptr");

    return Result;
  }

  /// Remove this constant from the map
  void remove(ConstantClass *CP) {
    typename MapTy::iterator I = Map.find(CP);
    assert(I != Map.end() && "Constant not found in constant table!");
    assert(*I == CP && "Didn't find correct element?");
    Map.erase(I);
  }

  ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
                                        ConstantClass *CP, Value *From,
                                        Constant *To, unsigned NumUpdated = 0,
                                        unsigned OperandNo = ~0u) {
    LookupKey Key(CP->getType(), ValType(Operands, CP));
    /// Hash once, and reuse it for the lookup and the insertion if needed.
    LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);

    auto ItMap = Map.find_as(Lookup);
    if (ItMap != Map.end())
      return *ItMap;

    // Update to the new value.  Optimize for the case when we have a single
    // operand that we're changing, but handle bulk updates efficiently.
    remove(CP);
    if (NumUpdated == 1) {
      assert(OperandNo < CP->getNumOperands() && "Invalid index");
      assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
      CP->setOperand(OperandNo, To);
    } else {
      for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
        if (CP->getOperand(I) == From)
          CP->setOperand(I, To);
    }
    Map.insert_as(CP, Lookup);
    return nullptr;
  }

  void dump() const {
    LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
  }
};

template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {
  for (auto &I : Map)
    delete I;
}

} // end namespace llvm

#endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H
