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/None.h"
22 #include "llvm/ADT/SmallVector.h"
23 #include "llvm/ADT/StringRef.h"
24 #include "llvm/IR/Constant.h"
25 #include "llvm/IR/Constants.h"
26 #include "llvm/IR/DerivedTypes.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 /// UnaryConstantExpr - This class is private to Constants.cpp, and is used
45 /// behind the scenes to implement unary constant exprs.
46 class UnaryConstantExpr final
: public ConstantExpr
{
48 UnaryConstantExpr(unsigned Opcode
, Constant
*C
, Type
*Ty
)
49 : ConstantExpr(Ty
, Opcode
, &Op
<0>(), 1) {
53 // allocate space for exactly one operand
54 void *operator new(size_t S
) { return User::operator new(S
, 1); }
55 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
57 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
59 static bool classof(const ConstantExpr
*CE
) {
60 return Instruction::isCast(CE
->getOpcode()) ||
61 Instruction::isUnaryOp(CE
->getOpcode());
63 static bool classof(const Value
*V
) {
64 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
68 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
69 /// behind the scenes to implement binary constant exprs.
70 class BinaryConstantExpr final
: public ConstantExpr
{
72 BinaryConstantExpr(unsigned Opcode
, Constant
*C1
, Constant
*C2
,
74 : ConstantExpr(C1
->getType(), Opcode
, &Op
<0>(), 2) {
77 SubclassOptionalData
= Flags
;
80 // allocate space for exactly two operands
81 void *operator new(size_t S
) { return User::operator new(S
, 2); }
82 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
84 /// Transparently provide more efficient getOperand methods.
85 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
87 static bool classof(const ConstantExpr
*CE
) {
88 return Instruction::isBinaryOp(CE
->getOpcode());
90 static bool classof(const Value
*V
) {
91 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
95 /// SelectConstantExpr - This class is private to Constants.cpp, and is used
96 /// behind the scenes to implement select constant exprs.
97 class SelectConstantExpr final
: public ConstantExpr
{
99 SelectConstantExpr(Constant
*C1
, Constant
*C2
, Constant
*C3
)
100 : ConstantExpr(C2
->getType(), Instruction::Select
, &Op
<0>(), 3) {
106 // allocate space for exactly three operands
107 void *operator new(size_t S
) { return User::operator new(S
, 3); }
108 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
110 /// Transparently provide more efficient getOperand methods.
111 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
113 static bool classof(const ConstantExpr
*CE
) {
114 return CE
->getOpcode() == Instruction::Select
;
116 static bool classof(const Value
*V
) {
117 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
121 /// ExtractElementConstantExpr - This class is private to
122 /// Constants.cpp, and is used behind the scenes to implement
123 /// extractelement constant exprs.
124 class ExtractElementConstantExpr final
: public ConstantExpr
{
126 ExtractElementConstantExpr(Constant
*C1
, Constant
*C2
)
127 : ConstantExpr(cast
<VectorType
>(C1
->getType())->getElementType(),
128 Instruction::ExtractElement
, &Op
<0>(), 2) {
133 // allocate space for exactly two operands
134 void *operator new(size_t S
) { return User::operator new(S
, 2); }
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::ExtractElement
;
143 static bool classof(const Value
*V
) {
144 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
148 /// InsertElementConstantExpr - This class is private to
149 /// Constants.cpp, and is used behind the scenes to implement
150 /// insertelement constant exprs.
151 class InsertElementConstantExpr final
: public ConstantExpr
{
153 InsertElementConstantExpr(Constant
*C1
, Constant
*C2
, Constant
*C3
)
154 : ConstantExpr(C1
->getType(), Instruction::InsertElement
,
161 // allocate space for exactly three operands
162 void *operator new(size_t S
) { return User::operator new(S
, 3); }
163 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
165 /// Transparently provide more efficient getOperand methods.
166 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
168 static bool classof(const ConstantExpr
*CE
) {
169 return CE
->getOpcode() == Instruction::InsertElement
;
171 static bool classof(const Value
*V
) {
172 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
176 /// ShuffleVectorConstantExpr - This class is private to
177 /// Constants.cpp, and is used behind the scenes to implement
178 /// shufflevector constant exprs.
179 class ShuffleVectorConstantExpr final
: public ConstantExpr
{
181 ShuffleVectorConstantExpr(Constant
*C1
, Constant
*C2
, ArrayRef
<int> Mask
)
182 : ConstantExpr(VectorType::get(
183 cast
<VectorType
>(C1
->getType())->getElementType(),
184 Mask
.size(), isa
<ScalableVectorType
>(C1
->getType())),
185 Instruction::ShuffleVector
, &Op
<0>(), 2) {
186 assert(ShuffleVectorInst::isValidOperands(C1
, C2
, Mask
) &&
187 "Invalid shuffle vector instruction operands!");
190 ShuffleMask
.assign(Mask
.begin(), Mask
.end());
191 ShuffleMaskForBitcode
=
192 ShuffleVectorInst::convertShuffleMaskForBitcode(Mask
, getType());
195 SmallVector
<int, 4> ShuffleMask
;
196 Constant
*ShuffleMaskForBitcode
;
198 void *operator new(size_t S
) { return User::operator new(S
, 2); }
199 void operator delete(void *Ptr
) { return User::operator delete(Ptr
); }
201 /// Transparently provide more efficient getOperand methods.
202 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
204 static bool classof(const ConstantExpr
*CE
) {
205 return CE
->getOpcode() == Instruction::ShuffleVector
;
207 static bool classof(const Value
*V
) {
208 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
212 /// ExtractValueConstantExpr - This class is private to
213 /// Constants.cpp, and is used behind the scenes to implement
214 /// extractvalue constant exprs.
215 class ExtractValueConstantExpr final
: public ConstantExpr
{
217 ExtractValueConstantExpr(Constant
*Agg
, ArrayRef
<unsigned> IdxList
,
219 : ConstantExpr(DestTy
, Instruction::ExtractValue
, &Op
<0>(), 1),
220 Indices(IdxList
.begin(), IdxList
.end()) {
224 // allocate space for exactly one operand
225 void *operator new(size_t S
) { return User::operator new(S
, 1); }
226 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
228 /// Indices - These identify which value to extract.
229 const SmallVector
<unsigned, 4> Indices
;
231 /// Transparently provide more efficient getOperand methods.
232 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
234 static bool classof(const ConstantExpr
*CE
) {
235 return CE
->getOpcode() == Instruction::ExtractValue
;
237 static bool classof(const Value
*V
) {
238 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
242 /// InsertValueConstantExpr - This class is private to
243 /// Constants.cpp, and is used behind the scenes to implement
244 /// insertvalue constant exprs.
245 class InsertValueConstantExpr final
: public ConstantExpr
{
247 InsertValueConstantExpr(Constant
*Agg
, Constant
*Val
,
248 ArrayRef
<unsigned> IdxList
, Type
*DestTy
)
249 : ConstantExpr(DestTy
, Instruction::InsertValue
, &Op
<0>(), 2),
250 Indices(IdxList
.begin(), IdxList
.end()) {
255 // allocate space for exactly one operand
256 void *operator new(size_t S
) { return User::operator new(S
, 2); }
257 void operator delete(void *Ptr
) { User::operator delete(Ptr
); }
259 /// Indices - These identify the position for the insertion.
260 const SmallVector
<unsigned, 4> Indices
;
262 /// Transparently provide more efficient getOperand methods.
263 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
265 static bool classof(const ConstantExpr
*CE
) {
266 return CE
->getOpcode() == Instruction::InsertValue
;
268 static bool classof(const Value
*V
) {
269 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
273 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
274 /// used behind the scenes to implement getelementpr constant exprs.
275 class GetElementPtrConstantExpr final
: public ConstantExpr
{
279 GetElementPtrConstantExpr(Type
*SrcElementTy
, Constant
*C
,
280 ArrayRef
<Constant
*> IdxList
, Type
*DestTy
);
283 static GetElementPtrConstantExpr
*Create(Type
*SrcElementTy
, Constant
*C
,
284 ArrayRef
<Constant
*> IdxList
,
285 Type
*DestTy
, unsigned Flags
) {
286 GetElementPtrConstantExpr
*Result
= new (IdxList
.size() + 1)
287 GetElementPtrConstantExpr(SrcElementTy
, C
, IdxList
, DestTy
);
288 Result
->SubclassOptionalData
= Flags
;
292 Type
*getSourceElementType() const;
293 Type
*getResultElementType() const;
295 /// Transparently provide more efficient getOperand methods.
296 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
298 static bool classof(const ConstantExpr
*CE
) {
299 return CE
->getOpcode() == Instruction::GetElementPtr
;
301 static bool classof(const Value
*V
) {
302 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
306 // CompareConstantExpr - This class is private to Constants.cpp, and is used
307 // behind the scenes to implement ICmp and FCmp constant expressions. This is
308 // needed in order to store the predicate value for these instructions.
309 class CompareConstantExpr final
: public ConstantExpr
{
311 unsigned short predicate
;
312 CompareConstantExpr(Type
*ty
, Instruction::OtherOps opc
,
313 unsigned short pred
, Constant
* LHS
, Constant
* RHS
)
314 : ConstantExpr(ty
, opc
, &Op
<0>(), 2), predicate(pred
) {
319 // allocate space for exactly two operands
320 void *operator new(size_t S
) { return User::operator new(S
, 2); }
321 void operator delete(void *Ptr
) { return User::operator delete(Ptr
); }
323 /// Transparently provide more efficient getOperand methods.
324 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value
);
326 static bool classof(const ConstantExpr
*CE
) {
327 return CE
->getOpcode() == Instruction::ICmp
||
328 CE
->getOpcode() == Instruction::FCmp
;
330 static bool classof(const Value
*V
) {
331 return isa
<ConstantExpr
>(V
) && classof(cast
<ConstantExpr
>(V
));
336 struct OperandTraits
<UnaryConstantExpr
>
337 : public FixedNumOperandTraits
<UnaryConstantExpr
, 1> {};
338 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr
, Value
)
341 struct OperandTraits
<BinaryConstantExpr
>
342 : public FixedNumOperandTraits
<BinaryConstantExpr
, 2> {};
343 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr
, Value
)
346 struct OperandTraits
<SelectConstantExpr
>
347 : public FixedNumOperandTraits
<SelectConstantExpr
, 3> {};
348 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr
, Value
)
351 struct OperandTraits
<ExtractElementConstantExpr
>
352 : public FixedNumOperandTraits
<ExtractElementConstantExpr
, 2> {};
353 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr
, Value
)
356 struct OperandTraits
<InsertElementConstantExpr
>
357 : public FixedNumOperandTraits
<InsertElementConstantExpr
, 3> {};
358 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr
, Value
)
361 struct OperandTraits
<ShuffleVectorConstantExpr
>
362 : public FixedNumOperandTraits
<ShuffleVectorConstantExpr
, 2> {};
363 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr
, Value
)
366 struct OperandTraits
<ExtractValueConstantExpr
>
367 : public FixedNumOperandTraits
<ExtractValueConstantExpr
, 1> {};
368 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr
, Value
)
371 struct OperandTraits
<InsertValueConstantExpr
>
372 : public FixedNumOperandTraits
<InsertValueConstantExpr
, 2> {};
373 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr
, Value
)
376 struct OperandTraits
<GetElementPtrConstantExpr
>
377 : public VariadicOperandTraits
<GetElementPtrConstantExpr
, 1> {};
379 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr
, Value
)
382 struct OperandTraits
<CompareConstantExpr
>
383 : public FixedNumOperandTraits
<CompareConstantExpr
, 2> {};
384 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr
, Value
)
386 template <class ConstantClass
> struct ConstantAggrKeyType
;
387 struct InlineAsmKeyType
;
388 struct ConstantExprKeyType
;
390 template <class ConstantClass
> struct ConstantInfo
;
391 template <> struct ConstantInfo
<ConstantExpr
> {
392 using ValType
= ConstantExprKeyType
;
393 using TypeClass
= Type
;
395 template <> struct ConstantInfo
<InlineAsm
> {
396 using ValType
= InlineAsmKeyType
;
397 using TypeClass
= PointerType
;
399 template <> struct ConstantInfo
<ConstantArray
> {
400 using ValType
= ConstantAggrKeyType
<ConstantArray
>;
401 using TypeClass
= ArrayType
;
403 template <> struct ConstantInfo
<ConstantStruct
> {
404 using ValType
= ConstantAggrKeyType
<ConstantStruct
>;
405 using TypeClass
= StructType
;
407 template <> struct ConstantInfo
<ConstantVector
> {
408 using ValType
= ConstantAggrKeyType
<ConstantVector
>;
409 using TypeClass
= VectorType
;
412 template <class ConstantClass
> struct ConstantAggrKeyType
{
413 ArrayRef
<Constant
*> Operands
;
415 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
) : Operands(Operands
) {}
417 ConstantAggrKeyType(ArrayRef
<Constant
*> Operands
, const ConstantClass
*)
418 : Operands(Operands
) {}
420 ConstantAggrKeyType(const ConstantClass
*C
,
421 SmallVectorImpl
<Constant
*> &Storage
) {
422 assert(Storage
.empty() && "Expected empty storage");
423 for (unsigned I
= 0, E
= C
->getNumOperands(); I
!= E
; ++I
)
424 Storage
.push_back(C
->getOperand(I
));
428 bool operator==(const ConstantAggrKeyType
&X
) const {
429 return Operands
== X
.Operands
;
432 bool operator==(const ConstantClass
*C
) const {
433 if (Operands
.size() != C
->getNumOperands())
435 for (unsigned I
= 0, E
= Operands
.size(); I
!= E
; ++I
)
436 if (Operands
[I
] != C
->getOperand(I
))
441 unsigned getHash() const {
442 return hash_combine_range(Operands
.begin(), Operands
.end());
445 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
447 ConstantClass
*create(TypeClass
*Ty
) const {
448 return new (Operands
.size()) ConstantClass(Ty
, Operands
);
452 struct InlineAsmKeyType
{
454 StringRef Constraints
;
458 InlineAsm::AsmDialect AsmDialect
;
461 InlineAsmKeyType(StringRef AsmString
, StringRef Constraints
,
462 FunctionType
*FTy
, bool HasSideEffects
, bool IsAlignStack
,
463 InlineAsm::AsmDialect AsmDialect
, bool canThrow
)
464 : AsmString(AsmString
), Constraints(Constraints
), FTy(FTy
),
465 HasSideEffects(HasSideEffects
), IsAlignStack(IsAlignStack
),
466 AsmDialect(AsmDialect
), CanThrow(canThrow
) {}
468 InlineAsmKeyType(const InlineAsm
*Asm
, SmallVectorImpl
<Constant
*> &)
469 : AsmString(Asm
->getAsmString()), Constraints(Asm
->getConstraintString()),
470 FTy(Asm
->getFunctionType()), HasSideEffects(Asm
->hasSideEffects()),
471 IsAlignStack(Asm
->isAlignStack()), AsmDialect(Asm
->getDialect()),
472 CanThrow(Asm
->canThrow()) {}
474 bool operator==(const InlineAsmKeyType
&X
) const {
475 return HasSideEffects
== X
.HasSideEffects
&&
476 IsAlignStack
== X
.IsAlignStack
&& AsmDialect
== X
.AsmDialect
&&
477 AsmString
== X
.AsmString
&& Constraints
== X
.Constraints
&&
478 FTy
== X
.FTy
&& CanThrow
== X
.CanThrow
;
481 bool operator==(const InlineAsm
*Asm
) const {
482 return HasSideEffects
== Asm
->hasSideEffects() &&
483 IsAlignStack
== Asm
->isAlignStack() &&
484 AsmDialect
== Asm
->getDialect() &&
485 AsmString
== Asm
->getAsmString() &&
486 Constraints
== Asm
->getConstraintString() &&
487 FTy
== Asm
->getFunctionType() && CanThrow
== Asm
->canThrow();
490 unsigned getHash() const {
491 return hash_combine(AsmString
, Constraints
, HasSideEffects
, IsAlignStack
,
492 AsmDialect
, FTy
, CanThrow
);
495 using TypeClass
= ConstantInfo
<InlineAsm
>::TypeClass
;
497 InlineAsm
*create(TypeClass
*Ty
) const {
498 assert(PointerType::getUnqual(FTy
) == Ty
);
499 return new InlineAsm(FTy
, std::string(AsmString
), std::string(Constraints
),
500 HasSideEffects
, IsAlignStack
, AsmDialect
, CanThrow
);
504 struct ConstantExprKeyType
{
507 uint8_t SubclassOptionalData
;
508 uint16_t SubclassData
;
509 ArrayRef
<Constant
*> Ops
;
510 ArrayRef
<unsigned> Indexes
;
511 ArrayRef
<int> ShuffleMask
;
514 static ArrayRef
<int> getShuffleMaskIfValid(const ConstantExpr
*CE
) {
515 if (CE
->getOpcode() == Instruction::ShuffleVector
)
516 return CE
->getShuffleMask();
520 static ArrayRef
<unsigned> getIndicesIfValid(const ConstantExpr
*CE
) {
521 if (CE
->hasIndices())
522 return CE
->getIndices();
526 static Type
*getSourceElementTypeIfValid(const ConstantExpr
*CE
) {
527 if (auto *GEPCE
= dyn_cast
<GetElementPtrConstantExpr
>(CE
))
528 return GEPCE
->getSourceElementType();
533 ConstantExprKeyType(unsigned Opcode
, ArrayRef
<Constant
*> Ops
,
534 unsigned short SubclassData
= 0,
535 unsigned short SubclassOptionalData
= 0,
536 ArrayRef
<unsigned> Indexes
= None
,
537 ArrayRef
<int> ShuffleMask
= None
,
538 Type
*ExplicitTy
= nullptr)
539 : Opcode(Opcode
), SubclassOptionalData(SubclassOptionalData
),
540 SubclassData(SubclassData
), Ops(Ops
), Indexes(Indexes
),
541 ShuffleMask(ShuffleMask
), ExplicitTy(ExplicitTy
) {}
543 ConstantExprKeyType(ArrayRef
<Constant
*> Operands
, const ConstantExpr
*CE
)
544 : Opcode(CE
->getOpcode()),
545 SubclassOptionalData(CE
->getRawSubclassOptionalData()),
546 SubclassData(CE
->isCompare() ? CE
->getPredicate() : 0), Ops(Operands
),
547 Indexes(getIndicesIfValid(CE
)), ShuffleMask(getShuffleMaskIfValid(CE
)),
548 ExplicitTy(getSourceElementTypeIfValid(CE
)) {}
550 ConstantExprKeyType(const ConstantExpr
*CE
,
551 SmallVectorImpl
<Constant
*> &Storage
)
552 : Opcode(CE
->getOpcode()),
553 SubclassOptionalData(CE
->getRawSubclassOptionalData()),
554 SubclassData(CE
->isCompare() ? CE
->getPredicate() : 0),
555 Indexes(getIndicesIfValid(CE
)), ShuffleMask(getShuffleMaskIfValid(CE
)),
556 ExplicitTy(getSourceElementTypeIfValid(CE
)) {
557 assert(Storage
.empty() && "Expected empty storage");
558 for (unsigned I
= 0, E
= CE
->getNumOperands(); I
!= E
; ++I
)
559 Storage
.push_back(CE
->getOperand(I
));
563 bool operator==(const ConstantExprKeyType
&X
) const {
564 return Opcode
== X
.Opcode
&& SubclassData
== X
.SubclassData
&&
565 SubclassOptionalData
== X
.SubclassOptionalData
&& Ops
== X
.Ops
&&
566 Indexes
== X
.Indexes
&& ShuffleMask
== X
.ShuffleMask
&&
567 ExplicitTy
== X
.ExplicitTy
;
570 bool operator==(const ConstantExpr
*CE
) const {
571 if (Opcode
!= CE
->getOpcode())
573 if (SubclassOptionalData
!= CE
->getRawSubclassOptionalData())
575 if (Ops
.size() != CE
->getNumOperands())
577 if (SubclassData
!= (CE
->isCompare() ? CE
->getPredicate() : 0))
579 for (unsigned I
= 0, E
= Ops
.size(); I
!= E
; ++I
)
580 if (Ops
[I
] != CE
->getOperand(I
))
582 if (Indexes
!= getIndicesIfValid(CE
))
584 if (ShuffleMask
!= getShuffleMaskIfValid(CE
))
586 if (ExplicitTy
!= getSourceElementTypeIfValid(CE
))
591 unsigned getHash() const {
593 Opcode
, SubclassOptionalData
, SubclassData
,
594 hash_combine_range(Ops
.begin(), Ops
.end()),
595 hash_combine_range(Indexes
.begin(), Indexes
.end()),
596 hash_combine_range(ShuffleMask
.begin(), ShuffleMask
.end()), ExplicitTy
);
599 using TypeClass
= ConstantInfo
<ConstantExpr
>::TypeClass
;
601 ConstantExpr
*create(TypeClass
*Ty
) const {
604 if (Instruction::isCast(Opcode
) ||
605 (Opcode
>= Instruction::UnaryOpsBegin
&&
606 Opcode
< Instruction::UnaryOpsEnd
))
607 return new UnaryConstantExpr(Opcode
, Ops
[0], Ty
);
608 if ((Opcode
>= Instruction::BinaryOpsBegin
&&
609 Opcode
< Instruction::BinaryOpsEnd
))
610 return new BinaryConstantExpr(Opcode
, Ops
[0], Ops
[1],
611 SubclassOptionalData
);
612 llvm_unreachable("Invalid ConstantExpr!");
613 case Instruction::Select
:
614 return new SelectConstantExpr(Ops
[0], Ops
[1], Ops
[2]);
615 case Instruction::ExtractElement
:
616 return new ExtractElementConstantExpr(Ops
[0], Ops
[1]);
617 case Instruction::InsertElement
:
618 return new InsertElementConstantExpr(Ops
[0], Ops
[1], Ops
[2]);
619 case Instruction::ShuffleVector
:
620 return new ShuffleVectorConstantExpr(Ops
[0], Ops
[1], ShuffleMask
);
621 case Instruction::InsertValue
:
622 return new InsertValueConstantExpr(Ops
[0], Ops
[1], Indexes
, Ty
);
623 case Instruction::ExtractValue
:
624 return new ExtractValueConstantExpr(Ops
[0], Indexes
, Ty
);
625 case Instruction::GetElementPtr
:
626 return GetElementPtrConstantExpr::Create(ExplicitTy
, Ops
[0], Ops
.slice(1),
627 Ty
, SubclassOptionalData
);
628 case Instruction::ICmp
:
629 return new CompareConstantExpr(Ty
, Instruction::ICmp
, SubclassData
,
631 case Instruction::FCmp
:
632 return new CompareConstantExpr(Ty
, Instruction::FCmp
, SubclassData
,
638 // Free memory for a given constant. Assumes the constant has already been
639 // removed from all relevant maps.
640 void deleteConstant(Constant
*C
);
642 template <class ConstantClass
> class ConstantUniqueMap
{
644 using ValType
= typename ConstantInfo
<ConstantClass
>::ValType
;
645 using TypeClass
= typename ConstantInfo
<ConstantClass
>::TypeClass
;
646 using LookupKey
= std::pair
<TypeClass
*, ValType
>;
648 /// Key and hash together, so that we compute the hash only once and reuse it.
649 using LookupKeyHashed
= std::pair
<unsigned, LookupKey
>;
653 using ConstantClassInfo
= DenseMapInfo
<ConstantClass
*>;
655 static inline ConstantClass
*getEmptyKey() {
656 return ConstantClassInfo::getEmptyKey();
659 static inline ConstantClass
*getTombstoneKey() {
660 return ConstantClassInfo::getTombstoneKey();
663 static unsigned getHashValue(const ConstantClass
*CP
) {
664 SmallVector
<Constant
*, 32> Storage
;
665 return getHashValue(LookupKey(CP
->getType(), ValType(CP
, Storage
)));
668 static bool isEqual(const ConstantClass
*LHS
, const ConstantClass
*RHS
) {
672 static unsigned getHashValue(const LookupKey
&Val
) {
673 return hash_combine(Val
.first
, Val
.second
.getHash());
676 static unsigned getHashValue(const LookupKeyHashed
&Val
) {
680 static bool isEqual(const LookupKey
&LHS
, const ConstantClass
*RHS
) {
681 if (RHS
== getEmptyKey() || RHS
== getTombstoneKey())
683 if (LHS
.first
!= RHS
->getType())
685 return LHS
.second
== RHS
;
688 static bool isEqual(const LookupKeyHashed
&LHS
, const ConstantClass
*RHS
) {
689 return isEqual(LHS
.second
, RHS
);
694 using MapTy
= DenseSet
<ConstantClass
*, MapInfo
>;
700 typename
MapTy::iterator
begin() { return Map
.begin(); }
701 typename
MapTy::iterator
end() { return Map
.end(); }
703 void freeConstants() {
709 ConstantClass
*create(TypeClass
*Ty
, ValType V
, LookupKeyHashed
&HashKey
) {
710 ConstantClass
*Result
= V
.create(Ty
);
712 assert(Result
->getType() == Ty
&& "Type specified is not correct!");
713 Map
.insert_as(Result
, HashKey
);
719 /// Return the specified constant from the map, creating it if necessary.
720 ConstantClass
*getOrCreate(TypeClass
*Ty
, ValType V
) {
721 LookupKey
Key(Ty
, V
);
722 /// Hash once, and reuse it for the lookup and the insertion if needed.
723 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
725 ConstantClass
*Result
= nullptr;
727 auto I
= Map
.find_as(Lookup
);
729 Result
= create(Ty
, V
, Lookup
);
732 assert(Result
&& "Unexpected nullptr");
737 /// Remove this constant from the map
738 void remove(ConstantClass
*CP
) {
739 typename
MapTy::iterator I
= Map
.find(CP
);
740 assert(I
!= Map
.end() && "Constant not found in constant table!");
741 assert(*I
== CP
&& "Didn't find correct element?");
745 ConstantClass
*replaceOperandsInPlace(ArrayRef
<Constant
*> Operands
,
746 ConstantClass
*CP
, Value
*From
,
747 Constant
*To
, unsigned NumUpdated
= 0,
748 unsigned OperandNo
= ~0u) {
749 LookupKey
Key(CP
->getType(), ValType(Operands
, CP
));
750 /// Hash once, and reuse it for the lookup and the insertion if needed.
751 LookupKeyHashed
Lookup(MapInfo::getHashValue(Key
), Key
);
753 auto ItMap
= Map
.find_as(Lookup
);
754 if (ItMap
!= Map
.end())
757 // Update to the new value. Optimize for the case when we have a single
758 // operand that we're changing, but handle bulk updates efficiently.
760 if (NumUpdated
== 1) {
761 assert(OperandNo
< CP
->getNumOperands() && "Invalid index");
762 assert(CP
->getOperand(OperandNo
) != To
&& "I didn't contain From!");
763 CP
->setOperand(OperandNo
, To
);
765 for (unsigned I
= 0, E
= CP
->getNumOperands(); I
!= E
; ++I
)
766 if (CP
->getOperand(I
) == From
)
767 CP
->setOperand(I
, To
);
769 Map
.insert_as(CP
, Lookup
);
774 LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
778 template <> inline void ConstantUniqueMap
<InlineAsm
>::freeConstants() {
783 } // end namespace llvm
785 #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H