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/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"
39 #define DEBUG_TYPE "ir"
43 /// CastConstantExpr - This class is private to Constants.cpp, and is used
44 /// behind the scenes to implement cast constant exprs.
45 class CastConstantExpr final
: public ConstantExpr
{
47 CastConstantExpr(unsigned Opcode
, Constant
*C
, Type
*Ty
)
48 : ConstantExpr(Ty
, Opcode
, &Op
<0>(), 1) {
52 // allocate space for exactly one operand
53 void *operator new(size_t S
) { return User::operator new(S
, 1); }
54 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
56 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
58 static bool classof(const ConstantExpr
*CE
) {
59 return Instruction::isCast(CE
->getOpcode());
61 static bool classof(const Value
*V
) {
62 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
66 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
67 /// behind the scenes to implement binary constant exprs.
68 class BinaryConstantExpr final
: public ConstantExpr
{
70 BinaryConstantExpr(unsigned Opcode
, Constant
*C1
, Constant
*C2
,
72 : ConstantExpr(C1
->getType(), Opcode
, &Op
<0>(), 2) {
75 SubclassOptionalData
= Flags
;
78 // allocate space for exactly two operands
79 void *operator new(size_t S
) { return User::operator new(S
, 2); }
80 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
82 /// Transparently provide more efficient getOperand methods.
83 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
85 static bool classof(const ConstantExpr
*CE
) {
86 return Instruction::isBinaryOp(CE
->getOpcode());
88 static bool classof(const Value
*V
) {
89 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
93 /// ExtractElementConstantExpr - This class is private to
94 /// Constants.cpp, and is used behind the scenes to implement
95 /// extractelement constant exprs.
96 class ExtractElementConstantExpr final
: public ConstantExpr
{
98 ExtractElementConstantExpr(Constant
*C1
, Constant
*C2
)
99 : ConstantExpr(cast
<VectorType
>(C1
->getType())->getElementType(),
100 Instruction::ExtractElement
, &Op
<0>(), 2) {
105 // allocate space for exactly two operands
106 void *operator new(size_t S
) { return User::operator new(S
, 2); }
107 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
109 /// Transparently provide more efficient getOperand methods.
110 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
112 static bool classof(const ConstantExpr
*CE
) {
113 return CE
->getOpcode() == Instruction::ExtractElement
;
115 static bool classof(const Value
*V
) {
116 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
120 /// InsertElementConstantExpr - This class is private to
121 /// Constants.cpp, and is used behind the scenes to implement
122 /// insertelement constant exprs.
123 class InsertElementConstantExpr final
: public ConstantExpr
{
125 InsertElementConstantExpr(Constant
*C1
, Constant
*C2
, Constant
*C3
)
126 : ConstantExpr(C1
->getType(), Instruction::InsertElement
,
133 // allocate space for exactly three operands
134 void *operator new(size_t S
) { return User::operator new(S
, 3); }
135 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
137 /// Transparently provide more efficient getOperand methods.
138 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
140 static bool classof(const ConstantExpr
*CE
) {
141 return CE
->getOpcode() == Instruction::InsertElement
;
143 static bool classof(const Value
*V
) {
144 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
148 /// ShuffleVectorConstantExpr - This class is private to
149 /// Constants.cpp, and is used behind the scenes to implement
150 /// shufflevector constant exprs.
151 class ShuffleVectorConstantExpr final
: public ConstantExpr
{
153 ShuffleVectorConstantExpr(Constant
*C1
, Constant
*C2
, ArrayRef
<int> Mask
)
154 : ConstantExpr(VectorType::get(
155 cast
<VectorType
>(C1
->getType())->getElementType(),
156 Mask
.size(), isa
<ScalableVectorType
>(C1
->getType())),
157 Instruction::ShuffleVector
, &Op
<0>(), 2) {
158 assert(ShuffleVectorInst::isValidOperands(C1
, C2
, Mask
) &&
159 "Invalid shuffle vector instruction operands!");
162 ShuffleMask
.assign(Mask
.begin(), Mask
.end());
163 ShuffleMaskForBitcode
=
164 ShuffleVectorInst::convertShuffleMaskForBitcode(Mask
, getType());
167 SmallVector
<int, 4> ShuffleMask
;
168 Constant
*ShuffleMaskForBitcode
;
170 void *operator new(size_t S
) { return User::operator new(S
, 2); }
171 void operator delete(void *Ptr
) { return User::operator delete(Ptr
); }
173 /// Transparently provide more efficient getOperand methods.
174 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
176 static bool classof(const ConstantExpr
*CE
) {
177 return CE
->getOpcode() == Instruction::ShuffleVector
;
179 static bool classof(const Value
*V
) {
180 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
184 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
185 /// used behind the scenes to implement getelementpr constant exprs.
186 class GetElementPtrConstantExpr final
: public ConstantExpr
{
190 GetElementPtrConstantExpr(Type
*SrcElementTy
, Constant
*C
,
191 ArrayRef
<Constant
*> IdxList
, Type
*DestTy
);
194 static GetElementPtrConstantExpr
*Create(Type
*SrcElementTy
, Constant
*C
,
195 ArrayRef
<Constant
*> IdxList
,
196 Type
*DestTy
, unsigned Flags
) {
197 GetElementPtrConstantExpr
*Result
= new (IdxList
.size() + 1)
198 GetElementPtrConstantExpr(SrcElementTy
, C
, IdxList
, DestTy
);
199 Result
->SubclassOptionalData
= Flags
;
203 Type
*getSourceElementType() const;
204 Type
*getResultElementType() const;
206 /// Transparently provide more efficient getOperand methods.
207 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
209 static bool classof(const ConstantExpr
*CE
) {
210 return CE
->getOpcode() == Instruction::GetElementPtr
;
212 static bool classof(const Value
*V
) {
213 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
217 // CompareConstantExpr - This class is private to Constants.cpp, and is used
218 // behind the scenes to implement ICmp and FCmp constant expressions. This is
219 // needed in order to store the predicate value for these instructions.
220 class CompareConstantExpr final
: public ConstantExpr
{
222 unsigned short predicate
;
223 CompareConstantExpr(Type
*ty
, Instruction::OtherOps opc
,
224 unsigned short pred
, Constant
* LHS
, Constant
* RHS
)
225 : ConstantExpr(ty
, opc
, &Op
<0>(), 2), predicate(pred
) {
230 // allocate space for exactly two operands
231 void *operator new(size_t S
) { return User::operator new(S
, 2); }
232 void operator delete(void *Ptr
) { return User::operator delete(Ptr
); }
234 /// Transparently provide more efficient getOperand methods.
235 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
237 static bool classof(const ConstantExpr
*CE
) {
238 return CE
->getOpcode() == Instruction::ICmp
||
239 CE
->getOpcode() == Instruction::FCmp
;
241 static bool classof(const Value
*V
) {
242 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
247 struct OperandTraits
<CastConstantExpr
>
248 : public FixedNumOperandTraits
<CastConstantExpr
, 1> {};
249 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr
, Value
)
252 struct OperandTraits
<BinaryConstantExpr
>
253 : public FixedNumOperandTraits
<BinaryConstantExpr
, 2> {};
254 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr
, Value
)
257 struct OperandTraits
<ExtractElementConstantExpr
>
258 : public FixedNumOperandTraits
<ExtractElementConstantExpr
, 2> {};
259 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr
, Value
)
262 struct OperandTraits
<InsertElementConstantExpr
>
263 : public FixedNumOperandTraits
<InsertElementConstantExpr
, 3> {};
264 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr
, Value
)
267 struct OperandTraits
<ShuffleVectorConstantExpr
>
268 : public FixedNumOperandTraits
<ShuffleVectorConstantExpr
, 2> {};
269 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr
, Value
)
272 struct OperandTraits
<GetElementPtrConstantExpr
>
273 : public VariadicOperandTraits
<GetElementPtrConstantExpr
, 1> {};
275 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr
, Value
)
278 struct OperandTraits
<CompareConstantExpr
>
279 : public FixedNumOperandTraits
<CompareConstantExpr
, 2> {};
280 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr
, Value
)
282 template <class ConstantClass
> struct ConstantAggrKeyType
;
283 struct InlineAsmKeyType
;
284 struct ConstantExprKeyType
;
286 template <class ConstantClass
> struct ConstantInfo
;
287 template <> struct ConstantInfo
<ConstantExpr
> {
288 using ValType
= ConstantExprKeyType
;
289 using TypeClass
= Type
;
291 template <> struct ConstantInfo
<InlineAsm
> {
292 using ValType
= InlineAsmKeyType
;
293 using TypeClass
= PointerType
;
295 template <> struct ConstantInfo
<ConstantArray
> {
296 using ValType
= ConstantAggrKeyType
<ConstantArray
>;
297 using TypeClass
= ArrayType
;
299 template <> struct ConstantInfo
<ConstantStruct
> {
300 using ValType
= ConstantAggrKeyType
<ConstantStruct
>;
301 using TypeClass
= StructType
;
303 template <> struct ConstantInfo
<ConstantVector
> {
304 using ValType
= ConstantAggrKeyType
<ConstantVector
>;
305 using TypeClass
= VectorType
;
308 template <class ConstantClass
> struct ConstantAggrKeyType
{
309 ArrayRef
<Constant
*> Operands
;
311 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
) : Operands(Operands
) {}
313 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
, const ConstantClass
*)
314 : Operands(Operands
) {}
316 ConstantAggrKeyType(const ConstantClass
*C
,
317 SmallVectorImpl
<Constant
*> &Storage
) {
318 assert(Storage
.empty() && "Expected empty storage");
319 for (unsigned I
= 0, E
= C
->getNumOperands(); I
!= E
; ++I
)
320 Storage
.push_back(C
->getOperand(I
));
324 bool operator==(const ConstantAggrKeyType
&X
) const {
325 return Operands
== X
.Operands
;
328 bool operator==(const ConstantClass
*C
) const {
329 if (Operands
.size() != C
->getNumOperands())
331 for (unsigned I
= 0, E
= Operands
.size(); I
!= E
; ++I
)
332 if (Operands
[I
] != C
->getOperand(I
))
337 unsigned getHash() const {
338 return hash_combine_range(Operands
.begin(), Operands
.end());
341 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
343 ConstantClass
*create(TypeClass
*Ty
) const {
344 return new (Operands
.size()) ConstantClass(Ty
, Operands
);
348 struct InlineAsmKeyType
{
350 StringRef Constraints
;
354 InlineAsm::AsmDialect AsmDialect
;
357 InlineAsmKeyType(StringRef AsmString
, StringRef Constraints
,
358 FunctionType
*FTy
, bool HasSideEffects
, bool IsAlignStack
,
359 InlineAsm::AsmDialect AsmDialect
, bool canThrow
)
360 : AsmString(AsmString
), Constraints(Constraints
), FTy(FTy
),
361 HasSideEffects(HasSideEffects
), IsAlignStack(IsAlignStack
),
362 AsmDialect(AsmDialect
), CanThrow(canThrow
) {}
364 InlineAsmKeyType(const InlineAsm
*Asm
, SmallVectorImpl
<Constant
*> &)
365 : AsmString(Asm
->getAsmString()), Constraints(Asm
->getConstraintString()),
366 FTy(Asm
->getFunctionType()), HasSideEffects(Asm
->hasSideEffects()),
367 IsAlignStack(Asm
->isAlignStack()), AsmDialect(Asm
->getDialect()),
368 CanThrow(Asm
->canThrow()) {}
370 bool operator==(const InlineAsmKeyType
&X
) const {
371 return HasSideEffects
== X
.HasSideEffects
&&
372 IsAlignStack
== X
.IsAlignStack
&& AsmDialect
== X
.AsmDialect
&&
373 AsmString
== X
.AsmString
&& Constraints
== X
.Constraints
&&
374 FTy
== X
.FTy
&& CanThrow
== X
.CanThrow
;
377 bool operator==(const InlineAsm
*Asm
) const {
378 return HasSideEffects
== Asm
->hasSideEffects() &&
379 IsAlignStack
== Asm
->isAlignStack() &&
380 AsmDialect
== Asm
->getDialect() &&
381 AsmString
== Asm
->getAsmString() &&
382 Constraints
== Asm
->getConstraintString() &&
383 FTy
== Asm
->getFunctionType() && CanThrow
== Asm
->canThrow();
386 unsigned getHash() const {
387 return hash_combine(AsmString
, Constraints
, HasSideEffects
, IsAlignStack
,
388 AsmDialect
, FTy
, CanThrow
);
391 using TypeClass
= ConstantInfo
<InlineAsm
>::TypeClass
;
393 InlineAsm
*create(TypeClass
*Ty
) const {
394 assert(PointerType::getUnqual(FTy
) == Ty
);
395 return new InlineAsm(FTy
, std::string(AsmString
), std::string(Constraints
),
396 HasSideEffects
, IsAlignStack
, AsmDialect
, CanThrow
);
400 struct ConstantExprKeyType
{
403 uint8_t SubclassOptionalData
;
404 uint16_t SubclassData
;
405 ArrayRef
<Constant
*> Ops
;
406 ArrayRef
<int> ShuffleMask
;
409 static ArrayRef
<int> getShuffleMaskIfValid(const ConstantExpr
*CE
) {
410 if (CE
->getOpcode() == Instruction::ShuffleVector
)
411 return CE
->getShuffleMask();
415 static Type
*getSourceElementTypeIfValid(const ConstantExpr
*CE
) {
416 if (auto *GEPCE
= dyn_cast
<GetElementPtrConstantExpr
>(CE
))
417 return GEPCE
->getSourceElementType();
422 ConstantExprKeyType(unsigned Opcode
, ArrayRef
<Constant
*> Ops
,
423 unsigned short SubclassData
= 0,
424 unsigned short SubclassOptionalData
= 0,
425 ArrayRef
<int> ShuffleMask
= std::nullopt
,
426 Type
*ExplicitTy
= nullptr)
427 : Opcode(Opcode
), SubclassOptionalData(SubclassOptionalData
),
428 SubclassData(SubclassData
), Ops(Ops
), ShuffleMask(ShuffleMask
),
429 ExplicitTy(ExplicitTy
) {}
431 ConstantExprKeyType(ArrayRef
<Constant
*> Operands
, const ConstantExpr
*CE
)
432 : Opcode(CE
->getOpcode()),
433 SubclassOptionalData(CE
->getRawSubclassOptionalData()),
434 SubclassData(CE
->isCompare() ? CE
->getPredicate() : 0), Ops(Operands
),
435 ShuffleMask(getShuffleMaskIfValid(CE
)),
436 ExplicitTy(getSourceElementTypeIfValid(CE
)) {}
438 ConstantExprKeyType(const ConstantExpr
*CE
,
439 SmallVectorImpl
<Constant
*> &Storage
)
440 : Opcode(CE
->getOpcode()),
441 SubclassOptionalData(CE
->getRawSubclassOptionalData()),
442 SubclassData(CE
->isCompare() ? CE
->getPredicate() : 0),
443 ShuffleMask(getShuffleMaskIfValid(CE
)),
444 ExplicitTy(getSourceElementTypeIfValid(CE
)) {
445 assert(Storage
.empty() && "Expected empty storage");
446 for (unsigned I
= 0, E
= CE
->getNumOperands(); I
!= E
; ++I
)
447 Storage
.push_back(CE
->getOperand(I
));
451 bool operator==(const ConstantExprKeyType
&X
) const {
452 return Opcode
== X
.Opcode
&& SubclassData
== X
.SubclassData
&&
453 SubclassOptionalData
== X
.SubclassOptionalData
&& Ops
== X
.Ops
&&
454 ShuffleMask
== X
.ShuffleMask
&& ExplicitTy
== X
.ExplicitTy
;
457 bool operator==(const ConstantExpr
*CE
) const {
458 if (Opcode
!= CE
->getOpcode())
460 if (SubclassOptionalData
!= CE
->getRawSubclassOptionalData())
462 if (Ops
.size() != CE
->getNumOperands())
464 if (SubclassData
!= (CE
->isCompare() ? CE
->getPredicate() : 0))
466 for (unsigned I
= 0, E
= Ops
.size(); I
!= E
; ++I
)
467 if (Ops
[I
] != CE
->getOperand(I
))
469 if (ShuffleMask
!= getShuffleMaskIfValid(CE
))
471 if (ExplicitTy
!= getSourceElementTypeIfValid(CE
))
476 unsigned getHash() const {
478 Opcode
, SubclassOptionalData
, SubclassData
,
479 hash_combine_range(Ops
.begin(), Ops
.end()),
480 hash_combine_range(ShuffleMask
.begin(), ShuffleMask
.end()), ExplicitTy
);
483 using TypeClass
= ConstantInfo
<ConstantExpr
>::TypeClass
;
485 ConstantExpr
*create(TypeClass
*Ty
) const {
488 if (Instruction::isCast(Opcode
))
489 return new CastConstantExpr(Opcode
, Ops
[0], Ty
);
490 if ((Opcode
>= Instruction::BinaryOpsBegin
&&
491 Opcode
< Instruction::BinaryOpsEnd
))
492 return new BinaryConstantExpr(Opcode
, Ops
[0], Ops
[1],
493 SubclassOptionalData
);
494 llvm_unreachable("Invalid ConstantExpr!");
495 case Instruction::ExtractElement
:
496 return new ExtractElementConstantExpr(Ops
[0], Ops
[1]);
497 case Instruction::InsertElement
:
498 return new InsertElementConstantExpr(Ops
[0], Ops
[1], Ops
[2]);
499 case Instruction::ShuffleVector
:
500 return new ShuffleVectorConstantExpr(Ops
[0], Ops
[1], ShuffleMask
);
501 case Instruction::GetElementPtr
:
502 return GetElementPtrConstantExpr::Create(ExplicitTy
, Ops
[0], Ops
.slice(1),
503 Ty
, SubclassOptionalData
);
504 case Instruction::ICmp
:
505 return new CompareConstantExpr(Ty
, Instruction::ICmp
, SubclassData
,
507 case Instruction::FCmp
:
508 return new CompareConstantExpr(Ty
, Instruction::FCmp
, SubclassData
,
514 // Free memory for a given constant. Assumes the constant has already been
515 // removed from all relevant maps.
516 void deleteConstant(Constant
*C
);
518 template <class ConstantClass
> class ConstantUniqueMap
{
520 using ValType
= typename ConstantInfo
<ConstantClass
>::ValType
;
521 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
522 using LookupKey
= std::pair
<TypeClass
*, ValType
>;
524 /// Key and hash together, so that we compute the hash only once and reuse it.
525 using LookupKeyHashed
= std::pair
<unsigned, LookupKey
>;
529 using ConstantClassInfo
= DenseMapInfo
<ConstantClass
*>;
531 static inline ConstantClass
*getEmptyKey() {
532 return ConstantClassInfo::getEmptyKey();
535 static inline ConstantClass
*getTombstoneKey() {
536 return ConstantClassInfo::getTombstoneKey();
539 static unsigned getHashValue(const ConstantClass
*CP
) {
540 SmallVector
<Constant
*, 32> Storage
;
541 return getHashValue(LookupKey(CP
->getType(), ValType(CP
, Storage
)));
544 static bool isEqual(const ConstantClass
*LHS
, const ConstantClass
*RHS
) {
548 static unsigned getHashValue(const LookupKey
&Val
) {
549 return hash_combine(Val
.first
, Val
.second
.getHash());
552 static unsigned getHashValue(const LookupKeyHashed
&Val
) {
556 static bool isEqual(const LookupKey
&LHS
, const ConstantClass
*RHS
) {
557 if (RHS
== getEmptyKey() || RHS
== getTombstoneKey())
559 if (LHS
.first
!= RHS
->getType())
561 return LHS
.second
== RHS
;
564 static bool isEqual(const LookupKeyHashed
&LHS
, const ConstantClass
*RHS
) {
565 return isEqual(LHS
.second
, RHS
);
570 using MapTy
= DenseSet
<ConstantClass
*, MapInfo
>;
576 typename
MapTy::iterator
begin() { return Map
.begin(); }
577 typename
MapTy::iterator
end() { return Map
.end(); }
579 void freeConstants() {
585 ConstantClass
*create(TypeClass
*Ty
, ValType V
, LookupKeyHashed
&HashKey
) {
586 ConstantClass
*Result
= V
.create(Ty
);
588 assert(Result
->getType() == Ty
&& "Type specified is not correct!");
589 Map
.insert_as(Result
, HashKey
);
595 /// Return the specified constant from the map, creating it if necessary.
596 ConstantClass
*getOrCreate(TypeClass
*Ty
, ValType V
) {
597 LookupKey
Key(Ty
, V
);
598 /// Hash once, and reuse it for the lookup and the insertion if needed.
599 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
601 ConstantClass
*Result
= nullptr;
603 auto I
= Map
.find_as(Lookup
);
605 Result
= create(Ty
, V
, Lookup
);
608 assert(Result
&& "Unexpected nullptr");
613 /// Remove this constant from the map
614 void remove(ConstantClass
*CP
) {
615 typename
MapTy::iterator I
= Map
.find(CP
);
616 assert(I
!= Map
.end() && "Constant not found in constant table!");
617 assert(*I
== CP
&& "Didn't find correct element?");
621 ConstantClass
*replaceOperandsInPlace(ArrayRef
<Constant
*> Operands
,
622 ConstantClass
*CP
, Value
*From
,
623 Constant
*To
, unsigned NumUpdated
= 0,
624 unsigned OperandNo
= ~0u) {
625 LookupKey
Key(CP
->getType(), ValType(Operands
, CP
));
626 /// Hash once, and reuse it for the lookup and the insertion if needed.
627 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
629 auto ItMap
= Map
.find_as(Lookup
);
630 if (ItMap
!= Map
.end())
633 // Update to the new value. Optimize for the case when we have a single
634 // operand that we're changing, but handle bulk updates efficiently.
636 if (NumUpdated
== 1) {
637 assert(OperandNo
< CP
->getNumOperands() && "Invalid index");
638 assert(CP
->getOperand(OperandNo
) != To
&& "I didn't contain From!");
639 CP
->setOperand(OperandNo
, To
);
641 for (unsigned I
= 0, E
= CP
->getNumOperands(); I
!= E
; ++I
)
642 if (CP
->getOperand(I
) == From
)
643 CP
->setOperand(I
, To
);
645 Map
.insert_as(CP
, Lookup
);
650 LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
654 template <> inline void ConstantUniqueMap
<InlineAsm
>::freeConstants() {
659 } // end namespace llvm
661 #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H