diff options
Diffstat (limited to 'llvm/lib/IR/ConstantsContext.h')
| -rw-r--r-- | llvm/lib/IR/ConstantsContext.h | 708 |
1 files changed, 708 insertions, 0 deletions
diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h new file mode 100644 index 0000000000000..1ec9087551f86 --- /dev/null +++ b/llvm/lib/IR/ConstantsContext.h @@ -0,0 +1,708 @@ +//===-- 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/None.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/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 { + +/// UnaryConstantExpr - This class is private to Constants.cpp, and is used +/// behind the scenes to implement unary constant exprs. +class UnaryConstantExpr : public ConstantExpr { +public: + UnaryConstantExpr(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); + } + + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// BinaryConstantExpr - This class is private to Constants.cpp, and is used +/// behind the scenes to implement binary constant exprs. +class BinaryConstantExpr : 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); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// SelectConstantExpr - This class is private to Constants.cpp, and is used +/// behind the scenes to implement select constant exprs. +class SelectConstantExpr : public ConstantExpr { +public: + SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3) + : ConstantExpr(C2->getType(), Instruction::Select, &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); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// ExtractElementConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// extractelement constant exprs. +class ExtractElementConstantExpr : 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); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// InsertElementConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// insertelement constant exprs. +class InsertElementConstantExpr : 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); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// ShuffleVectorConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// shufflevector constant exprs. +class ShuffleVectorConstantExpr : public ConstantExpr { +public: + ShuffleVectorConstantExpr(Constant *C1, Constant *C2, Constant *C3) + : ConstantExpr(VectorType::get( + cast<VectorType>(C1->getType())->getElementType(), + cast<VectorType>(C3->getType())->getNumElements()), + Instruction::ShuffleVector, + &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); + } + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); +}; + +/// ExtractValueConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// extractvalue constant exprs. +class ExtractValueConstantExpr : public ConstantExpr { +public: + ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList, + Type *DestTy) + : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1), + Indices(IdxList.begin(), IdxList.end()) { + Op<0>() = Agg; + } + + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 1); + } + + /// Indices - These identify which value to extract. + const SmallVector<unsigned, 4> Indices; + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + static bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::ExtractValue; + } + static bool classof(const Value *V) { + return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V)); + } +}; + +/// InsertValueConstantExpr - This class is private to +/// Constants.cpp, and is used behind the scenes to implement +/// insertvalue constant exprs. +class InsertValueConstantExpr : public ConstantExpr { +public: + InsertValueConstantExpr(Constant *Agg, Constant *Val, + ArrayRef<unsigned> IdxList, Type *DestTy) + : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2), + Indices(IdxList.begin(), IdxList.end()) { + Op<0>() = Agg; + Op<1>() = Val; + } + + // allocate space for exactly one operand + void *operator new(size_t s) { + return User::operator new(s, 2); + } + + /// Indices - These identify the position for the insertion. + const SmallVector<unsigned, 4> Indices; + + /// Transparently provide more efficient getOperand methods. + DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); + + static bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Instruction::InsertValue; + } + 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 : 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 : 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); + } + + /// 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<UnaryConstantExpr> + : public FixedNumOperandTraits<UnaryConstantExpr, 1> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value) + +template <> +struct OperandTraits<BinaryConstantExpr> + : public FixedNumOperandTraits<BinaryConstantExpr, 2> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value) + +template <> +struct OperandTraits<SelectConstantExpr> + : public FixedNumOperandTraits<SelectConstantExpr, 3> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, 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, 3> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value) + +template <> +struct OperandTraits<ExtractValueConstantExpr> + : public FixedNumOperandTraits<ExtractValueConstantExpr, 1> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value) + +template <> +struct OperandTraits<InsertValueConstantExpr> + : public FixedNumOperandTraits<InsertValueConstantExpr, 2> {}; +DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, 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; + + InlineAsmKeyType(StringRef AsmString, StringRef Constraints, + FunctionType *FTy, bool HasSideEffects, bool IsAlignStack, + InlineAsm::AsmDialect AsmDialect) + : AsmString(AsmString), Constraints(Constraints), FTy(FTy), + HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), + AsmDialect(AsmDialect) {} + + InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &) + : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), + FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()), + IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {} + + 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; + } + + 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(); + } + + unsigned getHash() const { + return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, + AsmDialect, FTy); + } + + using TypeClass = ConstantInfo<InlineAsm>::TypeClass; + + InlineAsm *create(TypeClass *Ty) const { + assert(PointerType::getUnqual(FTy) == Ty); + return new InlineAsm(FTy, AsmString, Constraints, HasSideEffects, + IsAlignStack, AsmDialect); + } +}; + +struct ConstantExprKeyType { + uint8_t Opcode; + uint8_t SubclassOptionalData; + uint16_t SubclassData; + ArrayRef<Constant *> Ops; + ArrayRef<unsigned> Indexes; + Type *ExplicitTy; + + ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, + unsigned short SubclassData = 0, + unsigned short SubclassOptionalData = 0, + ArrayRef<unsigned> Indexes = None, + Type *ExplicitTy = nullptr) + : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), + SubclassData(SubclassData), Ops(Ops), Indexes(Indexes), + ExplicitTy(ExplicitTy) {} + + ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()), + ExplicitTy(nullptr) {} + + ConstantExprKeyType(const ConstantExpr *CE, + SmallVectorImpl<Constant *> &Storage) + : Opcode(CE->getOpcode()), + SubclassOptionalData(CE->getRawSubclassOptionalData()), + SubclassData(CE->isCompare() ? CE->getPredicate() : 0), + Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()), + ExplicitTy(nullptr) { + 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 && + Indexes == X.Indexes; + } + + 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 (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>())) + return false; + return true; + } + + unsigned getHash() const { + return hash_combine(Opcode, SubclassOptionalData, SubclassData, + hash_combine_range(Ops.begin(), Ops.end()), + hash_combine_range(Indexes.begin(), Indexes.end())); + } + + using TypeClass = ConstantInfo<ConstantExpr>::TypeClass; + + ConstantExpr *create(TypeClass *Ty) const { + switch (Opcode) { + default: + if (Instruction::isCast(Opcode) || + (Opcode >= Instruction::UnaryOpsBegin && + Opcode < Instruction::UnaryOpsEnd)) + return new UnaryConstantExpr(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::Select: + return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]); + 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], Ops[2]); + case Instruction::InsertValue: + return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty); + case Instruction::ExtractValue: + return new ExtractValueConstantExpr(Ops[0], Indexes, Ty); + case Instruction::GetElementPtr: + return GetElementPtrConstantExpr::Create( + ExplicitTy ? ExplicitTy + : cast<PointerType>(Ops[0]->getType()->getScalarType()) + ->getElementType(), + 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]); + } + } +}; + +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) + delete I; // Asserts that use_empty(). + } + +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"); + } +}; + +} // end namespace llvm + +#endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H |
