1 //===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines various helper methods and classes used by
10 // LLVMContextImpl for creating and managing constants.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
15 #define LLVM_LIB_IR_CONSTANTSCONTEXT_H
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/DenseMapInfo.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ADT/Hashing.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/IR/Constant.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/GlobalVariable.h"
27 #include "llvm/IR/InlineAsm.h"
28 #include "llvm/IR/Instruction.h"
29 #include "llvm/IR/Instructions.h"
30 #include "llvm/IR/OperandTraits.h"
31 #include "llvm/Support/Casting.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/raw_ostream.h"
40 #define DEBUG_TYPE "ir"
44 /// CastConstantExpr - This class is private to Constants.cpp, and is used
45 /// behind the scenes to implement cast constant exprs.
46 class CastConstantExpr final
: public ConstantExpr
{
47 constexpr static IntrusiveOperandsAllocMarker AllocMarker
{1};
50 CastConstantExpr(unsigned Opcode
, Constant
*C
, Type
*Ty
)
51 : ConstantExpr(Ty
, Opcode
, AllocMarker
) {
55 // allocate space for exactly one operand
56 void *operator new(size_t S
) { return User::operator new(S
, AllocMarker
); }
57 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
59 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
61 static bool classof(const ConstantExpr
*CE
) {
62 return Instruction::isCast(CE
->getOpcode());
64 static bool classof(const Value
*V
) {
65 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
69 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
70 /// behind the scenes to implement binary constant exprs.
71 class BinaryConstantExpr final
: public ConstantExpr
{
72 constexpr static IntrusiveOperandsAllocMarker AllocMarker
{2};
75 BinaryConstantExpr(unsigned Opcode
, Constant
*C1
, Constant
*C2
,
77 : ConstantExpr(C1
->getType(), Opcode
, AllocMarker
) {
80 SubclassOptionalData
= Flags
;
83 // allocate space for exactly two operands
84 void *operator new(size_t S
) { return User::operator new(S
, AllocMarker
); }
85 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
87 /// Transparently provide more efficient getOperand methods.
88 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
90 static bool classof(const ConstantExpr
*CE
) {
91 return Instruction::isBinaryOp(CE
->getOpcode());
93 static bool classof(const Value
*V
) {
94 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
98 /// ExtractElementConstantExpr - This class is private to
99 /// Constants.cpp, and is used behind the scenes to implement
100 /// extractelement constant exprs.
101 class ExtractElementConstantExpr final
: public ConstantExpr
{
102 constexpr static IntrusiveOperandsAllocMarker AllocMarker
{2};
105 ExtractElementConstantExpr(Constant
*C1
, Constant
*C2
)
106 : ConstantExpr(cast
<VectorType
>(C1
->getType())->getElementType(),
107 Instruction::ExtractElement
, AllocMarker
) {
112 // allocate space for exactly two operands
113 void *operator new(size_t S
) { return User::operator new(S
, AllocMarker
); }
114 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
116 /// Transparently provide more efficient getOperand methods.
117 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
119 static bool classof(const ConstantExpr
*CE
) {
120 return CE
->getOpcode() == Instruction::ExtractElement
;
122 static bool classof(const Value
*V
) {
123 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
127 /// InsertElementConstantExpr - This class is private to
128 /// Constants.cpp, and is used behind the scenes to implement
129 /// insertelement constant exprs.
130 class InsertElementConstantExpr final
: public ConstantExpr
{
131 constexpr static IntrusiveOperandsAllocMarker AllocMarker
{3};
134 InsertElementConstantExpr(Constant
*C1
, Constant
*C2
, Constant
*C3
)
135 : ConstantExpr(C1
->getType(), Instruction::InsertElement
, AllocMarker
) {
141 // allocate space for exactly three operands
142 void *operator new(size_t S
) { return User::operator new(S
, AllocMarker
); }
143 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
145 /// Transparently provide more efficient getOperand methods.
146 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
148 static bool classof(const ConstantExpr
*CE
) {
149 return CE
->getOpcode() == Instruction::InsertElement
;
151 static bool classof(const Value
*V
) {
152 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
156 /// ShuffleVectorConstantExpr - This class is private to
157 /// Constants.cpp, and is used behind the scenes to implement
158 /// shufflevector constant exprs.
159 class ShuffleVectorConstantExpr final
: public ConstantExpr
{
160 constexpr static IntrusiveOperandsAllocMarker AllocMarker
{2};
163 ShuffleVectorConstantExpr(Constant
*C1
, Constant
*C2
, ArrayRef
<int> Mask
)
164 : ConstantExpr(VectorType::get(
165 cast
<VectorType
>(C1
->getType())->getElementType(),
166 Mask
.size(), isa
<ScalableVectorType
>(C1
->getType())),
167 Instruction::ShuffleVector
, AllocMarker
) {
168 assert(ShuffleVectorInst::isValidOperands(C1
, C2
, Mask
) &&
169 "Invalid shuffle vector instruction operands!");
172 ShuffleMask
.assign(Mask
.begin(), Mask
.end());
173 ShuffleMaskForBitcode
=
174 ShuffleVectorInst::convertShuffleMaskForBitcode(Mask
, getType());
177 SmallVector
<int, 4> ShuffleMask
;
178 Constant
*ShuffleMaskForBitcode
;
180 void *operator new(size_t S
) { return User::operator new(S
, AllocMarker
); }
181 void operator delete(void *Ptr
) { return User::operator delete(Ptr
); }
183 /// Transparently provide more efficient getOperand methods.
184 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
186 static bool classof(const ConstantExpr
*CE
) {
187 return CE
->getOpcode() == Instruction::ShuffleVector
;
189 static bool classof(const Value
*V
) {
190 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
194 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
195 /// used behind the scenes to implement getelementptr constant exprs.
196 class GetElementPtrConstantExpr
: public ConstantExpr
{
199 std::optional
<ConstantRange
> InRange
;
201 GetElementPtrConstantExpr(Type
*SrcElementTy
, Constant
*C
,
202 ArrayRef
<Constant
*> IdxList
, Type
*DestTy
,
203 std::optional
<ConstantRange
> InRange
,
204 AllocInfo AllocInfo
);
207 static GetElementPtrConstantExpr
*
208 Create(Type
*SrcElementTy
, Constant
*C
, ArrayRef
<Constant
*> IdxList
,
209 Type
*DestTy
, unsigned Flags
, std::optional
<ConstantRange
> InRange
) {
210 IntrusiveOperandsAllocMarker AllocMarker
{unsigned(IdxList
.size() + 1)};
211 GetElementPtrConstantExpr
*Result
= new (AllocMarker
)
212 GetElementPtrConstantExpr(SrcElementTy
, C
, IdxList
, DestTy
,
213 std::move(InRange
), AllocMarker
);
214 Result
->SubclassOptionalData
= Flags
;
218 Type
*getSourceElementType() const;
219 Type
*getResultElementType() const;
220 std::optional
<ConstantRange
> getInRange() const;
222 /// Transparently provide more efficient getOperand methods.
223 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
225 static bool classof(const ConstantExpr
*CE
) {
226 return CE
->getOpcode() == Instruction::GetElementPtr
;
228 static bool classof(const Value
*V
) {
229 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
234 struct OperandTraits
<CastConstantExpr
>
235 : public FixedNumOperandTraits
<CastConstantExpr
, 1> {};
236 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr
, Value
)
239 struct OperandTraits
<BinaryConstantExpr
>
240 : public FixedNumOperandTraits
<BinaryConstantExpr
, 2> {};
241 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr
, Value
)
244 struct OperandTraits
<ExtractElementConstantExpr
>
245 : public FixedNumOperandTraits
<ExtractElementConstantExpr
, 2> {};
246 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr
, Value
)
249 struct OperandTraits
<InsertElementConstantExpr
>
250 : public FixedNumOperandTraits
<InsertElementConstantExpr
, 3> {};
251 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr
, Value
)
254 struct OperandTraits
<ShuffleVectorConstantExpr
>
255 : public FixedNumOperandTraits
<ShuffleVectorConstantExpr
, 2> {};
256 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr
, Value
)
259 struct OperandTraits
<GetElementPtrConstantExpr
>
260 : public VariadicOperandTraits
<GetElementPtrConstantExpr
> {};
262 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr
, Value
)
264 template <class ConstantClass
> struct ConstantAggrKeyType
;
265 struct InlineAsmKeyType
;
266 struct ConstantExprKeyType
;
267 struct ConstantPtrAuthKeyType
;
269 template <class ConstantClass
> struct ConstantInfo
;
270 template <> struct ConstantInfo
<ConstantExpr
> {
271 using ValType
= ConstantExprKeyType
;
272 using TypeClass
= Type
;
274 template <> struct ConstantInfo
<InlineAsm
> {
275 using ValType
= InlineAsmKeyType
;
276 using TypeClass
= PointerType
;
278 template <> struct ConstantInfo
<ConstantArray
> {
279 using ValType
= ConstantAggrKeyType
<ConstantArray
>;
280 using TypeClass
= ArrayType
;
282 template <> struct ConstantInfo
<ConstantStruct
> {
283 using ValType
= ConstantAggrKeyType
<ConstantStruct
>;
284 using TypeClass
= StructType
;
286 template <> struct ConstantInfo
<ConstantVector
> {
287 using ValType
= ConstantAggrKeyType
<ConstantVector
>;
288 using TypeClass
= VectorType
;
290 template <> struct ConstantInfo
<ConstantPtrAuth
> {
291 using ValType
= ConstantPtrAuthKeyType
;
292 using TypeClass
= Type
;
295 template <class ConstantClass
> struct ConstantAggrKeyType
{
296 ArrayRef
<Constant
*> Operands
;
298 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
) : Operands(Operands
) {}
300 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
, const ConstantClass
*)
301 : Operands(Operands
) {}
303 ConstantAggrKeyType(const ConstantClass
*C
,
304 SmallVectorImpl
<Constant
*> &Storage
) {
305 assert(Storage
.empty() && "Expected empty storage");
306 Storage
.reserve(C
->getNumOperands());
307 for (unsigned I
= 0, E
= C
->getNumOperands(); I
!= E
; ++I
)
308 Storage
.push_back(C
->getOperand(I
));
312 bool operator==(const ConstantAggrKeyType
&X
) const {
313 return Operands
== X
.Operands
;
316 bool operator==(const ConstantClass
*C
) const {
317 if (Operands
.size() != C
->getNumOperands())
319 for (unsigned I
= 0, E
= Operands
.size(); I
!= E
; ++I
)
320 if (Operands
[I
] != C
->getOperand(I
))
325 unsigned getHash() const {
326 return hash_combine_range(Operands
.begin(), Operands
.end());
329 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
331 ConstantClass
*create(TypeClass
*Ty
) const {
332 User::IntrusiveOperandsAllocMarker AllocMarker
{unsigned(Operands
.size())};
333 return new (AllocMarker
) ConstantClass(Ty
, Operands
, AllocMarker
);
337 struct InlineAsmKeyType
{
339 StringRef Constraints
;
343 InlineAsm::AsmDialect AsmDialect
;
346 InlineAsmKeyType(StringRef AsmString
, StringRef Constraints
,
347 FunctionType
*FTy
, bool HasSideEffects
, bool IsAlignStack
,
348 InlineAsm::AsmDialect AsmDialect
, bool canThrow
)
349 : AsmString(AsmString
), Constraints(Constraints
), FTy(FTy
),
350 HasSideEffects(HasSideEffects
), IsAlignStack(IsAlignStack
),
351 AsmDialect(AsmDialect
), CanThrow(canThrow
) {}
353 InlineAsmKeyType(const InlineAsm
*Asm
, SmallVectorImpl
<Constant
*> &)
354 : AsmString(Asm
->getAsmString()), Constraints(Asm
->getConstraintString()),
355 FTy(Asm
->getFunctionType()), HasSideEffects(Asm
->hasSideEffects()),
356 IsAlignStack(Asm
->isAlignStack()), AsmDialect(Asm
->getDialect()),
357 CanThrow(Asm
->canThrow()) {}
359 bool operator==(const InlineAsmKeyType
&X
) const {
360 return HasSideEffects
== X
.HasSideEffects
&&
361 IsAlignStack
== X
.IsAlignStack
&& AsmDialect
== X
.AsmDialect
&&
362 AsmString
== X
.AsmString
&& Constraints
== X
.Constraints
&&
363 FTy
== X
.FTy
&& CanThrow
== X
.CanThrow
;
366 bool operator==(const InlineAsm
*Asm
) const {
367 return HasSideEffects
== Asm
->hasSideEffects() &&
368 IsAlignStack
== Asm
->isAlignStack() &&
369 AsmDialect
== Asm
->getDialect() &&
370 AsmString
== Asm
->getAsmString() &&
371 Constraints
== Asm
->getConstraintString() &&
372 FTy
== Asm
->getFunctionType() && CanThrow
== Asm
->canThrow();
375 unsigned getHash() const {
376 return hash_combine(AsmString
, Constraints
, HasSideEffects
, IsAlignStack
,
377 AsmDialect
, FTy
, CanThrow
);
380 using TypeClass
= ConstantInfo
<InlineAsm
>::TypeClass
;
382 InlineAsm
*create(TypeClass
*Ty
) const {
383 assert(PointerType::getUnqual(FTy
) == Ty
);
384 return new InlineAsm(FTy
, std::string(AsmString
), std::string(Constraints
),
385 HasSideEffects
, IsAlignStack
, AsmDialect
, CanThrow
);
389 struct ConstantExprKeyType
{
392 uint8_t SubclassOptionalData
;
393 ArrayRef
<Constant
*> Ops
;
394 ArrayRef
<int> ShuffleMask
;
396 std::optional
<ConstantRange
> InRange
;
398 static ArrayRef
<int> getShuffleMaskIfValid(const ConstantExpr
*CE
) {
399 if (CE
->getOpcode() == Instruction::ShuffleVector
)
400 return CE
->getShuffleMask();
404 static Type
*getSourceElementTypeIfValid(const ConstantExpr
*CE
) {
405 if (auto *GEPCE
= dyn_cast
<GetElementPtrConstantExpr
>(CE
))
406 return GEPCE
->getSourceElementType();
410 static std::optional
<ConstantRange
>
411 getInRangeIfValid(const ConstantExpr
*CE
) {
412 if (auto *GEPCE
= dyn_cast
<GetElementPtrConstantExpr
>(CE
))
413 return GEPCE
->getInRange();
418 ConstantExprKeyType(unsigned Opcode
, ArrayRef
<Constant
*> Ops
,
419 unsigned short SubclassOptionalData
= 0,
420 ArrayRef
<int> ShuffleMask
= {},
421 Type
*ExplicitTy
= nullptr,
422 std::optional
<ConstantRange
> InRange
= std::nullopt
)
423 : Opcode(Opcode
), SubclassOptionalData(SubclassOptionalData
), Ops(Ops
),
424 ShuffleMask(ShuffleMask
), ExplicitTy(ExplicitTy
),
425 InRange(std::move(InRange
)) {}
427 ConstantExprKeyType(ArrayRef
<Constant
*> Operands
, const ConstantExpr
*CE
)
428 : Opcode(CE
->getOpcode()),
429 SubclassOptionalData(CE
->getRawSubclassOptionalData()), Ops(Operands
),
430 ShuffleMask(getShuffleMaskIfValid(CE
)),
431 ExplicitTy(getSourceElementTypeIfValid(CE
)),
432 InRange(getInRangeIfValid(CE
)) {}
434 ConstantExprKeyType(const ConstantExpr
*CE
,
435 SmallVectorImpl
<Constant
*> &Storage
)
436 : Opcode(CE
->getOpcode()),
437 SubclassOptionalData(CE
->getRawSubclassOptionalData()),
438 ShuffleMask(getShuffleMaskIfValid(CE
)),
439 ExplicitTy(getSourceElementTypeIfValid(CE
)),
440 InRange(getInRangeIfValid(CE
)) {
441 assert(Storage
.empty() && "Expected empty storage");
442 for (unsigned I
= 0, E
= CE
->getNumOperands(); I
!= E
; ++I
)
443 Storage
.push_back(CE
->getOperand(I
));
447 static bool rangesEqual(const std::optional
<ConstantRange
> &A
,
448 const std::optional
<ConstantRange
> &B
) {
449 if (!A
.has_value() || !B
.has_value())
450 return A
.has_value() == B
.has_value();
451 return A
->getBitWidth() == B
->getBitWidth() && A
== B
;
454 bool operator==(const ConstantExprKeyType
&X
) const {
455 return Opcode
== X
.Opcode
&&
456 SubclassOptionalData
== X
.SubclassOptionalData
&& Ops
== X
.Ops
&&
457 ShuffleMask
== X
.ShuffleMask
&& ExplicitTy
== X
.ExplicitTy
&&
458 rangesEqual(InRange
, X
.InRange
);
461 bool operator==(const ConstantExpr
*CE
) const {
462 if (Opcode
!= CE
->getOpcode())
464 if (SubclassOptionalData
!= CE
->getRawSubclassOptionalData())
466 if (Ops
.size() != CE
->getNumOperands())
468 for (unsigned I
= 0, E
= Ops
.size(); I
!= E
; ++I
)
469 if (Ops
[I
] != CE
->getOperand(I
))
471 if (ShuffleMask
!= getShuffleMaskIfValid(CE
))
473 if (ExplicitTy
!= getSourceElementTypeIfValid(CE
))
475 if (!rangesEqual(InRange
, getInRangeIfValid(CE
)))
480 unsigned getHash() const {
482 Opcode
, SubclassOptionalData
,
483 hash_combine_range(Ops
.begin(), Ops
.end()),
484 hash_combine_range(ShuffleMask
.begin(), ShuffleMask
.end()), ExplicitTy
);
487 using TypeClass
= ConstantInfo
<ConstantExpr
>::TypeClass
;
489 ConstantExpr
*create(TypeClass
*Ty
) const {
492 if (Instruction::isCast(Opcode
))
493 return new CastConstantExpr(Opcode
, Ops
[0], Ty
);
494 if (Instruction::isBinaryOp(Opcode
))
495 return new BinaryConstantExpr(Opcode
, Ops
[0], Ops
[1],
496 SubclassOptionalData
);
497 llvm_unreachable("Invalid ConstantExpr!");
498 case Instruction::ExtractElement
:
499 return new ExtractElementConstantExpr(Ops
[0], Ops
[1]);
500 case Instruction::InsertElement
:
501 return new InsertElementConstantExpr(Ops
[0], Ops
[1], Ops
[2]);
502 case Instruction::ShuffleVector
:
503 return new ShuffleVectorConstantExpr(Ops
[0], Ops
[1], ShuffleMask
);
504 case Instruction::GetElementPtr
:
505 return GetElementPtrConstantExpr::Create(
506 ExplicitTy
, Ops
[0], Ops
.slice(1), Ty
, SubclassOptionalData
, InRange
);
511 struct ConstantPtrAuthKeyType
{
512 ArrayRef
<Constant
*> Operands
;
514 ConstantPtrAuthKeyType(ArrayRef
<Constant
*> Operands
) : Operands(Operands
) {}
516 ConstantPtrAuthKeyType(ArrayRef
<Constant
*> Operands
, const ConstantPtrAuth
*)
517 : Operands(Operands
) {}
519 ConstantPtrAuthKeyType(const ConstantPtrAuth
*C
,
520 SmallVectorImpl
<Constant
*> &Storage
) {
521 assert(Storage
.empty() && "Expected empty storage");
522 for (unsigned I
= 0, E
= C
->getNumOperands(); I
!= E
; ++I
)
523 Storage
.push_back(cast
<Constant
>(C
->getOperand(I
)));
527 bool operator==(const ConstantPtrAuthKeyType
&X
) const {
528 return Operands
== X
.Operands
;
531 bool operator==(const ConstantPtrAuth
*C
) const {
532 if (Operands
.size() != C
->getNumOperands())
534 for (unsigned I
= 0, E
= Operands
.size(); I
!= E
; ++I
)
535 if (Operands
[I
] != C
->getOperand(I
))
540 unsigned getHash() const {
541 return hash_combine_range(Operands
.begin(), Operands
.end());
544 using TypeClass
= typename ConstantInfo
<ConstantPtrAuth
>::TypeClass
;
546 ConstantPtrAuth
*create(TypeClass
*Ty
) const {
547 return new ConstantPtrAuth(Operands
[0], cast
<ConstantInt
>(Operands
[1]),
548 cast
<ConstantInt
>(Operands
[2]), Operands
[3]);
552 // Free memory for a given constant. Assumes the constant has already been
553 // removed from all relevant maps.
554 void deleteConstant(Constant
*C
);
556 template <class ConstantClass
> class ConstantUniqueMap
{
558 using ValType
= typename ConstantInfo
<ConstantClass
>::ValType
;
559 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
560 using LookupKey
= std::pair
<TypeClass
*, ValType
>;
562 /// Key and hash together, so that we compute the hash only once and reuse it.
563 using LookupKeyHashed
= std::pair
<unsigned, LookupKey
>;
567 using ConstantClassInfo
= DenseMapInfo
<ConstantClass
*>;
569 static inline ConstantClass
*getEmptyKey() {
570 return ConstantClassInfo::getEmptyKey();
573 static inline ConstantClass
*getTombstoneKey() {
574 return ConstantClassInfo::getTombstoneKey();
577 static unsigned getHashValue(const ConstantClass
*CP
) {
578 SmallVector
<Constant
*, 32> Storage
;
579 return getHashValue(LookupKey(CP
->getType(), ValType(CP
, Storage
)));
582 static bool isEqual(const ConstantClass
*LHS
, const ConstantClass
*RHS
) {
586 static unsigned getHashValue(const LookupKey
&Val
) {
587 return hash_combine(Val
.first
, Val
.second
.getHash());
590 static unsigned getHashValue(const LookupKeyHashed
&Val
) {
594 static bool isEqual(const LookupKey
&LHS
, const ConstantClass
*RHS
) {
595 if (RHS
== getEmptyKey() || RHS
== getTombstoneKey())
597 if (LHS
.first
!= RHS
->getType())
599 return LHS
.second
== RHS
;
602 static bool isEqual(const LookupKeyHashed
&LHS
, const ConstantClass
*RHS
) {
603 return isEqual(LHS
.second
, RHS
);
608 using MapTy
= DenseSet
<ConstantClass
*, MapInfo
>;
614 typename
MapTy::iterator
begin() { return Map
.begin(); }
615 typename
MapTy::iterator
end() { return Map
.end(); }
617 void freeConstants() {
623 ConstantClass
*create(TypeClass
*Ty
, ValType V
, LookupKeyHashed
&HashKey
) {
624 ConstantClass
*Result
= V
.create(Ty
);
626 assert(Result
->getType() == Ty
&& "Type specified is not correct!");
627 Map
.insert_as(Result
, HashKey
);
633 /// Return the specified constant from the map, creating it if necessary.
634 ConstantClass
*getOrCreate(TypeClass
*Ty
, ValType V
) {
635 LookupKey
Key(Ty
, V
);
636 /// Hash once, and reuse it for the lookup and the insertion if needed.
637 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
639 ConstantClass
*Result
= nullptr;
641 auto I
= Map
.find_as(Lookup
);
643 Result
= create(Ty
, V
, Lookup
);
646 assert(Result
&& "Unexpected nullptr");
651 /// Remove this constant from the map
652 void remove(ConstantClass
*CP
) {
653 typename
MapTy::iterator I
= Map
.find(CP
);
654 assert(I
!= Map
.end() && "Constant not found in constant table!");
655 assert(*I
== CP
&& "Didn't find correct element?");
659 ConstantClass
*replaceOperandsInPlace(ArrayRef
<Constant
*> Operands
,
660 ConstantClass
*CP
, Value
*From
,
661 Constant
*To
, unsigned NumUpdated
= 0,
662 unsigned OperandNo
= ~0u) {
663 LookupKey
Key(CP
->getType(), ValType(Operands
, CP
));
664 /// Hash once, and reuse it for the lookup and the insertion if needed.
665 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
667 auto ItMap
= Map
.find_as(Lookup
);
668 if (ItMap
!= Map
.end())
671 // Update to the new value. Optimize for the case when we have a single
672 // operand that we're changing, but handle bulk updates efficiently.
674 if (NumUpdated
== 1) {
675 assert(OperandNo
< CP
->getNumOperands() && "Invalid index");
676 assert(CP
->getOperand(OperandNo
) != To
&& "I didn't contain From!");
677 CP
->setOperand(OperandNo
, To
);
679 for (unsigned I
= 0, E
= CP
->getNumOperands(); I
!= E
; ++I
)
680 if (CP
->getOperand(I
) == From
)
681 CP
->setOperand(I
, To
);
683 Map
.insert_as(CP
, Lookup
);
688 LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
692 template <> inline void ConstantUniqueMap
<InlineAsm
>::freeConstants() {
697 } // end namespace llvm
699 #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H