Path: blob/main/contrib/llvm-project/llvm/lib/IR/ConstantsContext.h
35233 views
//===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file defines various helper methods and classes used by9// LLVMContextImpl for creating and managing constants.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H14#define LLVM_LIB_IR_CONSTANTSCONTEXT_H1516#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/DenseMapInfo.h"18#include "llvm/ADT/DenseSet.h"19#include "llvm/ADT/Hashing.h"20#include "llvm/ADT/SmallVector.h"21#include "llvm/ADT/StringRef.h"22#include "llvm/IR/Constant.h"23#include "llvm/IR/Constants.h"24#include "llvm/IR/DerivedTypes.h"25#include "llvm/IR/GlobalVariable.h"26#include "llvm/IR/InlineAsm.h"27#include "llvm/IR/Instruction.h"28#include "llvm/IR/Instructions.h"29#include "llvm/IR/OperandTraits.h"30#include "llvm/Support/Casting.h"31#include "llvm/Support/Debug.h"32#include "llvm/Support/ErrorHandling.h"33#include "llvm/Support/raw_ostream.h"34#include <cassert>35#include <cstddef>36#include <cstdint>37#include <utility>3839#define DEBUG_TYPE "ir"4041namespace llvm {4243/// CastConstantExpr - This class is private to Constants.cpp, and is used44/// behind the scenes to implement cast constant exprs.45class CastConstantExpr final : public ConstantExpr {46public:47CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty)48: ConstantExpr(Ty, Opcode, &Op<0>(), 1) {49Op<0>() = C;50}5152// allocate space for exactly one operand53void *operator new(size_t S) { return User::operator new(S, 1); }54void operator delete(void *Ptr) { User::operator delete(Ptr); }5556DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);5758static bool classof(const ConstantExpr *CE) {59return Instruction::isCast(CE->getOpcode());60}61static bool classof(const Value *V) {62return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));63}64};6566/// BinaryConstantExpr - This class is private to Constants.cpp, and is used67/// behind the scenes to implement binary constant exprs.68class BinaryConstantExpr final : public ConstantExpr {69public:70BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,71unsigned Flags)72: ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {73Op<0>() = C1;74Op<1>() = C2;75SubclassOptionalData = Flags;76}7778// allocate space for exactly two operands79void *operator new(size_t S) { return User::operator new(S, 2); }80void operator delete(void *Ptr) { User::operator delete(Ptr); }8182/// Transparently provide more efficient getOperand methods.83DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);8485static bool classof(const ConstantExpr *CE) {86return Instruction::isBinaryOp(CE->getOpcode());87}88static bool classof(const Value *V) {89return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));90}91};9293/// ExtractElementConstantExpr - This class is private to94/// Constants.cpp, and is used behind the scenes to implement95/// extractelement constant exprs.96class ExtractElementConstantExpr final : public ConstantExpr {97public:98ExtractElementConstantExpr(Constant *C1, Constant *C2)99: ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),100Instruction::ExtractElement, &Op<0>(), 2) {101Op<0>() = C1;102Op<1>() = C2;103}104105// allocate space for exactly two operands106void *operator new(size_t S) { return User::operator new(S, 2); }107void operator delete(void *Ptr) { User::operator delete(Ptr); }108109/// Transparently provide more efficient getOperand methods.110DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);111112static bool classof(const ConstantExpr *CE) {113return CE->getOpcode() == Instruction::ExtractElement;114}115static bool classof(const Value *V) {116return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));117}118};119120/// InsertElementConstantExpr - This class is private to121/// Constants.cpp, and is used behind the scenes to implement122/// insertelement constant exprs.123class InsertElementConstantExpr final : public ConstantExpr {124public:125InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)126: ConstantExpr(C1->getType(), Instruction::InsertElement,127&Op<0>(), 3) {128Op<0>() = C1;129Op<1>() = C2;130Op<2>() = C3;131}132133// allocate space for exactly three operands134void *operator new(size_t S) { return User::operator new(S, 3); }135void operator delete(void *Ptr) { User::operator delete(Ptr); }136137/// Transparently provide more efficient getOperand methods.138DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);139140static bool classof(const ConstantExpr *CE) {141return CE->getOpcode() == Instruction::InsertElement;142}143static bool classof(const Value *V) {144return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));145}146};147148/// ShuffleVectorConstantExpr - This class is private to149/// Constants.cpp, and is used behind the scenes to implement150/// shufflevector constant exprs.151class ShuffleVectorConstantExpr final : public ConstantExpr {152public:153ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)154: ConstantExpr(VectorType::get(155cast<VectorType>(C1->getType())->getElementType(),156Mask.size(), isa<ScalableVectorType>(C1->getType())),157Instruction::ShuffleVector, &Op<0>(), 2) {158assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&159"Invalid shuffle vector instruction operands!");160Op<0>() = C1;161Op<1>() = C2;162ShuffleMask.assign(Mask.begin(), Mask.end());163ShuffleMaskForBitcode =164ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType());165}166167SmallVector<int, 4> ShuffleMask;168Constant *ShuffleMaskForBitcode;169170void *operator new(size_t S) { return User::operator new(S, 2); }171void operator delete(void *Ptr) { return User::operator delete(Ptr); }172173/// Transparently provide more efficient getOperand methods.174DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);175176static bool classof(const ConstantExpr *CE) {177return CE->getOpcode() == Instruction::ShuffleVector;178}179static bool classof(const Value *V) {180return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));181}182};183184/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is185/// used behind the scenes to implement getelementptr constant exprs.186class GetElementPtrConstantExpr : public ConstantExpr {187Type *SrcElementTy;188Type *ResElementTy;189std::optional<ConstantRange> InRange;190191GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,192ArrayRef<Constant *> IdxList, Type *DestTy,193std::optional<ConstantRange> InRange);194195public:196static GetElementPtrConstantExpr *197Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList,198Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) {199GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)200GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy,201std::move(InRange));202Result->SubclassOptionalData = Flags;203return Result;204}205206Type *getSourceElementType() const;207Type *getResultElementType() const;208std::optional<ConstantRange> getInRange() const;209210/// Transparently provide more efficient getOperand methods.211DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);212213static bool classof(const ConstantExpr *CE) {214return CE->getOpcode() == Instruction::GetElementPtr;215}216static bool classof(const Value *V) {217return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));218}219};220221template <>222struct OperandTraits<CastConstantExpr>223: public FixedNumOperandTraits<CastConstantExpr, 1> {};224DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value)225226template <>227struct OperandTraits<BinaryConstantExpr>228: public FixedNumOperandTraits<BinaryConstantExpr, 2> {};229DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)230231template <>232struct OperandTraits<ExtractElementConstantExpr>233: public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};234DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)235236template <>237struct OperandTraits<InsertElementConstantExpr>238: public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};239DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)240241template <>242struct OperandTraits<ShuffleVectorConstantExpr>243: public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};244DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)245246template <>247struct OperandTraits<GetElementPtrConstantExpr>248: public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {};249250DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)251252template <class ConstantClass> struct ConstantAggrKeyType;253struct InlineAsmKeyType;254struct ConstantExprKeyType;255struct ConstantPtrAuthKeyType;256257template <class ConstantClass> struct ConstantInfo;258template <> struct ConstantInfo<ConstantExpr> {259using ValType = ConstantExprKeyType;260using TypeClass = Type;261};262template <> struct ConstantInfo<InlineAsm> {263using ValType = InlineAsmKeyType;264using TypeClass = PointerType;265};266template <> struct ConstantInfo<ConstantArray> {267using ValType = ConstantAggrKeyType<ConstantArray>;268using TypeClass = ArrayType;269};270template <> struct ConstantInfo<ConstantStruct> {271using ValType = ConstantAggrKeyType<ConstantStruct>;272using TypeClass = StructType;273};274template <> struct ConstantInfo<ConstantVector> {275using ValType = ConstantAggrKeyType<ConstantVector>;276using TypeClass = VectorType;277};278template <> struct ConstantInfo<ConstantPtrAuth> {279using ValType = ConstantPtrAuthKeyType;280using TypeClass = Type;281};282283template <class ConstantClass> struct ConstantAggrKeyType {284ArrayRef<Constant *> Operands;285286ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}287288ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)289: Operands(Operands) {}290291ConstantAggrKeyType(const ConstantClass *C,292SmallVectorImpl<Constant *> &Storage) {293assert(Storage.empty() && "Expected empty storage");294for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)295Storage.push_back(C->getOperand(I));296Operands = Storage;297}298299bool operator==(const ConstantAggrKeyType &X) const {300return Operands == X.Operands;301}302303bool operator==(const ConstantClass *C) const {304if (Operands.size() != C->getNumOperands())305return false;306for (unsigned I = 0, E = Operands.size(); I != E; ++I)307if (Operands[I] != C->getOperand(I))308return false;309return true;310}311312unsigned getHash() const {313return hash_combine_range(Operands.begin(), Operands.end());314}315316using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;317318ConstantClass *create(TypeClass *Ty) const {319return new (Operands.size()) ConstantClass(Ty, Operands);320}321};322323struct InlineAsmKeyType {324StringRef AsmString;325StringRef Constraints;326FunctionType *FTy;327bool HasSideEffects;328bool IsAlignStack;329InlineAsm::AsmDialect AsmDialect;330bool CanThrow;331332InlineAsmKeyType(StringRef AsmString, StringRef Constraints,333FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,334InlineAsm::AsmDialect AsmDialect, bool canThrow)335: AsmString(AsmString), Constraints(Constraints), FTy(FTy),336HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),337AsmDialect(AsmDialect), CanThrow(canThrow) {}338339InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)340: AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),341FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),342IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),343CanThrow(Asm->canThrow()) {}344345bool operator==(const InlineAsmKeyType &X) const {346return HasSideEffects == X.HasSideEffects &&347IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&348AsmString == X.AsmString && Constraints == X.Constraints &&349FTy == X.FTy && CanThrow == X.CanThrow;350}351352bool operator==(const InlineAsm *Asm) const {353return HasSideEffects == Asm->hasSideEffects() &&354IsAlignStack == Asm->isAlignStack() &&355AsmDialect == Asm->getDialect() &&356AsmString == Asm->getAsmString() &&357Constraints == Asm->getConstraintString() &&358FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();359}360361unsigned getHash() const {362return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,363AsmDialect, FTy, CanThrow);364}365366using TypeClass = ConstantInfo<InlineAsm>::TypeClass;367368InlineAsm *create(TypeClass *Ty) const {369assert(PointerType::getUnqual(FTy) == Ty);370return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),371HasSideEffects, IsAlignStack, AsmDialect, CanThrow);372}373};374375struct ConstantExprKeyType {376private:377uint8_t Opcode;378uint8_t SubclassOptionalData;379ArrayRef<Constant *> Ops;380ArrayRef<int> ShuffleMask;381Type *ExplicitTy;382std::optional<ConstantRange> InRange;383384static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {385if (CE->getOpcode() == Instruction::ShuffleVector)386return CE->getShuffleMask();387return std::nullopt;388}389390static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {391if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))392return GEPCE->getSourceElementType();393return nullptr;394}395396static std::optional<ConstantRange>397getInRangeIfValid(const ConstantExpr *CE) {398if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))399return GEPCE->getInRange();400return std::nullopt;401}402403public:404ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,405unsigned short SubclassOptionalData = 0,406ArrayRef<int> ShuffleMask = std::nullopt,407Type *ExplicitTy = nullptr,408std::optional<ConstantRange> InRange = std::nullopt)409: Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), Ops(Ops),410ShuffleMask(ShuffleMask), ExplicitTy(ExplicitTy),411InRange(std::move(InRange)) {}412413ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)414: Opcode(CE->getOpcode()),415SubclassOptionalData(CE->getRawSubclassOptionalData()), Ops(Operands),416ShuffleMask(getShuffleMaskIfValid(CE)),417ExplicitTy(getSourceElementTypeIfValid(CE)),418InRange(getInRangeIfValid(CE)) {}419420ConstantExprKeyType(const ConstantExpr *CE,421SmallVectorImpl<Constant *> &Storage)422: Opcode(CE->getOpcode()),423SubclassOptionalData(CE->getRawSubclassOptionalData()),424ShuffleMask(getShuffleMaskIfValid(CE)),425ExplicitTy(getSourceElementTypeIfValid(CE)),426InRange(getInRangeIfValid(CE)) {427assert(Storage.empty() && "Expected empty storage");428for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)429Storage.push_back(CE->getOperand(I));430Ops = Storage;431}432433static bool rangesEqual(const std::optional<ConstantRange> &A,434const std::optional<ConstantRange> &B) {435if (!A.has_value() || !B.has_value())436return A.has_value() == B.has_value();437return A->getBitWidth() == B->getBitWidth() && A == B;438}439440bool operator==(const ConstantExprKeyType &X) const {441return Opcode == X.Opcode &&442SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&443ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy &&444rangesEqual(InRange, X.InRange);445}446447bool operator==(const ConstantExpr *CE) const {448if (Opcode != CE->getOpcode())449return false;450if (SubclassOptionalData != CE->getRawSubclassOptionalData())451return false;452if (Ops.size() != CE->getNumOperands())453return false;454for (unsigned I = 0, E = Ops.size(); I != E; ++I)455if (Ops[I] != CE->getOperand(I))456return false;457if (ShuffleMask != getShuffleMaskIfValid(CE))458return false;459if (ExplicitTy != getSourceElementTypeIfValid(CE))460return false;461if (!rangesEqual(InRange, getInRangeIfValid(CE)))462return false;463return true;464}465466unsigned getHash() const {467return hash_combine(468Opcode, SubclassOptionalData,469hash_combine_range(Ops.begin(), Ops.end()),470hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy);471}472473using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;474475ConstantExpr *create(TypeClass *Ty) const {476switch (Opcode) {477default:478if (Instruction::isCast(Opcode))479return new CastConstantExpr(Opcode, Ops[0], Ty);480if ((Opcode >= Instruction::BinaryOpsBegin &&481Opcode < Instruction::BinaryOpsEnd))482return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],483SubclassOptionalData);484llvm_unreachable("Invalid ConstantExpr!");485case Instruction::ExtractElement:486return new ExtractElementConstantExpr(Ops[0], Ops[1]);487case Instruction::InsertElement:488return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);489case Instruction::ShuffleVector:490return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);491case Instruction::GetElementPtr:492return GetElementPtrConstantExpr::Create(493ExplicitTy, Ops[0], Ops.slice(1), Ty, SubclassOptionalData, InRange);494}495}496};497498struct ConstantPtrAuthKeyType {499ArrayRef<Constant *> Operands;500501ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}502503ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands, const ConstantPtrAuth *)504: Operands(Operands) {}505506ConstantPtrAuthKeyType(const ConstantPtrAuth *C,507SmallVectorImpl<Constant *> &Storage) {508assert(Storage.empty() && "Expected empty storage");509for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)510Storage.push_back(cast<Constant>(C->getOperand(I)));511Operands = Storage;512}513514bool operator==(const ConstantPtrAuthKeyType &X) const {515return Operands == X.Operands;516}517518bool operator==(const ConstantPtrAuth *C) const {519if (Operands.size() != C->getNumOperands())520return false;521for (unsigned I = 0, E = Operands.size(); I != E; ++I)522if (Operands[I] != C->getOperand(I))523return false;524return true;525}526527unsigned getHash() const {528return hash_combine_range(Operands.begin(), Operands.end());529}530531using TypeClass = typename ConstantInfo<ConstantPtrAuth>::TypeClass;532533ConstantPtrAuth *create(TypeClass *Ty) const {534return new ConstantPtrAuth(Operands[0], cast<ConstantInt>(Operands[1]),535cast<ConstantInt>(Operands[2]), Operands[3]);536}537};538539// Free memory for a given constant. Assumes the constant has already been540// removed from all relevant maps.541void deleteConstant(Constant *C);542543template <class ConstantClass> class ConstantUniqueMap {544public:545using ValType = typename ConstantInfo<ConstantClass>::ValType;546using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;547using LookupKey = std::pair<TypeClass *, ValType>;548549/// Key and hash together, so that we compute the hash only once and reuse it.550using LookupKeyHashed = std::pair<unsigned, LookupKey>;551552private:553struct MapInfo {554using ConstantClassInfo = DenseMapInfo<ConstantClass *>;555556static inline ConstantClass *getEmptyKey() {557return ConstantClassInfo::getEmptyKey();558}559560static inline ConstantClass *getTombstoneKey() {561return ConstantClassInfo::getTombstoneKey();562}563564static unsigned getHashValue(const ConstantClass *CP) {565SmallVector<Constant *, 32> Storage;566return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));567}568569static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {570return LHS == RHS;571}572573static unsigned getHashValue(const LookupKey &Val) {574return hash_combine(Val.first, Val.second.getHash());575}576577static unsigned getHashValue(const LookupKeyHashed &Val) {578return Val.first;579}580581static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {582if (RHS == getEmptyKey() || RHS == getTombstoneKey())583return false;584if (LHS.first != RHS->getType())585return false;586return LHS.second == RHS;587}588589static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {590return isEqual(LHS.second, RHS);591}592};593594public:595using MapTy = DenseSet<ConstantClass *, MapInfo>;596597private:598MapTy Map;599600public:601typename MapTy::iterator begin() { return Map.begin(); }602typename MapTy::iterator end() { return Map.end(); }603604void freeConstants() {605for (auto &I : Map)606deleteConstant(I);607}608609private:610ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {611ConstantClass *Result = V.create(Ty);612613assert(Result->getType() == Ty && "Type specified is not correct!");614Map.insert_as(Result, HashKey);615616return Result;617}618619public:620/// Return the specified constant from the map, creating it if necessary.621ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {622LookupKey Key(Ty, V);623/// Hash once, and reuse it for the lookup and the insertion if needed.624LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);625626ConstantClass *Result = nullptr;627628auto I = Map.find_as(Lookup);629if (I == Map.end())630Result = create(Ty, V, Lookup);631else632Result = *I;633assert(Result && "Unexpected nullptr");634635return Result;636}637638/// Remove this constant from the map639void remove(ConstantClass *CP) {640typename MapTy::iterator I = Map.find(CP);641assert(I != Map.end() && "Constant not found in constant table!");642assert(*I == CP && "Didn't find correct element?");643Map.erase(I);644}645646ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,647ConstantClass *CP, Value *From,648Constant *To, unsigned NumUpdated = 0,649unsigned OperandNo = ~0u) {650LookupKey Key(CP->getType(), ValType(Operands, CP));651/// Hash once, and reuse it for the lookup and the insertion if needed.652LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);653654auto ItMap = Map.find_as(Lookup);655if (ItMap != Map.end())656return *ItMap;657658// Update to the new value. Optimize for the case when we have a single659// operand that we're changing, but handle bulk updates efficiently.660remove(CP);661if (NumUpdated == 1) {662assert(OperandNo < CP->getNumOperands() && "Invalid index");663assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");664CP->setOperand(OperandNo, To);665} else {666for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)667if (CP->getOperand(I) == From)668CP->setOperand(I, To);669}670Map.insert_as(CP, Lookup);671return nullptr;672}673674void dump() const {675LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");676}677};678679template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {680for (auto &I : Map)681delete I;682}683684} // end namespace llvm685686#endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H687688689