1//===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines various helper methods and classes used by
10// LLVMContextImpl for creating and managing constants.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
15#define LLVM_LIB_IR_CONSTANTSCONTEXT_H
16
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"
35#include <cassert>
36#include <cstddef>
37#include <cstdint>
38#include <utility>
39
40#define DEBUG_TYPE "ir"
41
42namespace llvm {
43
44/// CastConstantExpr - This class is private to Constants.cpp, and is used
45/// behind the scenes to implement cast constant exprs.
46class CastConstantExpr final : public ConstantExpr {
47 constexpr static IntrusiveOperandsAllocMarker AllocMarker{.NumOps: 1};
48
49public:
50 CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
51 : ConstantExpr(Ty, Opcode, AllocMarker) {
52 Op<0>() = C;
53 }
54
55 // allocate space for exactly one operand
56 void *operator new(size_t S) { return User::operator new(Size: S, allocTrait: AllocMarker); }
57 void operator delete(void *Ptr) { User::operator delete(Usr: Ptr); }
58
59 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
60
61 static bool classof(const ConstantExpr *CE) {
62 return Instruction::isCast(Opcode: CE->getOpcode());
63 }
64 static bool classof(const Value *V) {
65 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
66 }
67};
68
69/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
70/// behind the scenes to implement binary constant exprs.
71class BinaryConstantExpr final : public ConstantExpr {
72 constexpr static IntrusiveOperandsAllocMarker AllocMarker{.NumOps: 2};
73
74public:
75 BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
76 unsigned Flags)
77 : ConstantExpr(C1->getType(), Opcode, AllocMarker) {
78 Op<0>() = C1;
79 Op<1>() = C2;
80 SubclassOptionalData = Flags;
81 }
82
83 // allocate space for exactly two operands
84 void *operator new(size_t S) { return User::operator new(Size: S, allocTrait: AllocMarker); }
85 void operator delete(void *Ptr) { User::operator delete(Usr: Ptr); }
86
87 /// Transparently provide more efficient getOperand methods.
88 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
89
90 static bool classof(const ConstantExpr *CE) {
91 return Instruction::isBinaryOp(Opcode: CE->getOpcode());
92 }
93 static bool classof(const Value *V) {
94 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
95 }
96};
97
98/// ExtractElementConstantExpr - This class is private to
99/// Constants.cpp, and is used behind the scenes to implement
100/// extractelement constant exprs.
101class ExtractElementConstantExpr final : public ConstantExpr {
102 constexpr static IntrusiveOperandsAllocMarker AllocMarker{.NumOps: 2};
103
104public:
105 ExtractElementConstantExpr(Constant *C1, Constant *C2)
106 : ConstantExpr(cast<VectorType>(Val: C1->getType())->getElementType(),
107 Instruction::ExtractElement, AllocMarker) {
108 Op<0>() = C1;
109 Op<1>() = C2;
110 }
111
112 // allocate space for exactly two operands
113 void *operator new(size_t S) { return User::operator new(Size: S, allocTrait: AllocMarker); }
114 void operator delete(void *Ptr) { User::operator delete(Usr: Ptr); }
115
116 /// Transparently provide more efficient getOperand methods.
117 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
118
119 static bool classof(const ConstantExpr *CE) {
120 return CE->getOpcode() == Instruction::ExtractElement;
121 }
122 static bool classof(const Value *V) {
123 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
124 }
125};
126
127/// InsertElementConstantExpr - This class is private to
128/// Constants.cpp, and is used behind the scenes to implement
129/// insertelement constant exprs.
130class InsertElementConstantExpr final : public ConstantExpr {
131 constexpr static IntrusiveOperandsAllocMarker AllocMarker{.NumOps: 3};
132
133public:
134 InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
135 : ConstantExpr(C1->getType(), Instruction::InsertElement, AllocMarker) {
136 Op<0>() = C1;
137 Op<1>() = C2;
138 Op<2>() = C3;
139 }
140
141 // allocate space for exactly three operands
142 void *operator new(size_t S) { return User::operator new(Size: S, allocTrait: AllocMarker); }
143 void operator delete(void *Ptr) { User::operator delete(Usr: Ptr); }
144
145 /// Transparently provide more efficient getOperand methods.
146 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
147
148 static bool classof(const ConstantExpr *CE) {
149 return CE->getOpcode() == Instruction::InsertElement;
150 }
151 static bool classof(const Value *V) {
152 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
153 }
154};
155
156/// ShuffleVectorConstantExpr - This class is private to
157/// Constants.cpp, and is used behind the scenes to implement
158/// shufflevector constant exprs.
159class ShuffleVectorConstantExpr final : public ConstantExpr {
160 constexpr static IntrusiveOperandsAllocMarker AllocMarker{.NumOps: 2};
161
162public:
163 ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)
164 : ConstantExpr(VectorType::get(
165 ElementType: cast<VectorType>(Val: C1->getType())->getElementType(),
166 NumElements: Mask.size(), Scalable: isa<ScalableVectorType>(Val: C1->getType())),
167 Instruction::ShuffleVector, AllocMarker) {
168 assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&
169 "Invalid shuffle vector instruction operands!");
170 Op<0>() = C1;
171 Op<1>() = C2;
172 ShuffleMask.assign(in_start: Mask.begin(), in_end: Mask.end());
173 ShuffleMaskForBitcode =
174 ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, ResultTy: getType());
175 }
176
177 SmallVector<int, 4> ShuffleMask;
178 Constant *ShuffleMaskForBitcode;
179
180 void *operator new(size_t S) { return User::operator new(Size: S, allocTrait: AllocMarker); }
181 void operator delete(void *Ptr) { return User::operator delete(Usr: Ptr); }
182
183 /// Transparently provide more efficient getOperand methods.
184 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
185
186 static bool classof(const ConstantExpr *CE) {
187 return CE->getOpcode() == Instruction::ShuffleVector;
188 }
189 static bool classof(const Value *V) {
190 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
191 }
192};
193
194/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
195/// used behind the scenes to implement getelementptr constant exprs.
196class GetElementPtrConstantExpr : public ConstantExpr {
197 Type *SrcElementTy;
198 Type *ResElementTy;
199 std::optional<ConstantRange> InRange;
200
201 GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
202 ArrayRef<Constant *> IdxList, Type *DestTy,
203 std::optional<ConstantRange> InRange,
204 AllocInfo AllocInfo);
205
206public:
207 static GetElementPtrConstantExpr *
208 Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList,
209 Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) {
210 IntrusiveOperandsAllocMarker AllocMarker{.NumOps: unsigned(IdxList.size() + 1)};
211 GetElementPtrConstantExpr *Result = new (AllocMarker)
212 GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy,
213 std::move(InRange), AllocMarker);
214 Result->SubclassOptionalData = Flags;
215 return Result;
216 }
217
218 Type *getSourceElementType() const;
219 Type *getResultElementType() const;
220 std::optional<ConstantRange> getInRange() const;
221
222 /// Transparently provide more efficient getOperand methods.
223 DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
224
225 static bool classof(const ConstantExpr *CE) {
226 return CE->getOpcode() == Instruction::GetElementPtr;
227 }
228 static bool classof(const Value *V) {
229 return isa<ConstantExpr>(Val: V) && classof(CE: cast<ConstantExpr>(Val: V));
230 }
231};
232
233template <>
234struct OperandTraits<CastConstantExpr>
235 : public FixedNumOperandTraits<CastConstantExpr, 1> {};
236DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value)
237
238template <>
239struct OperandTraits<BinaryConstantExpr>
240 : public FixedNumOperandTraits<BinaryConstantExpr, 2> {};
241DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
242
243template <>
244struct OperandTraits<ExtractElementConstantExpr>
245 : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};
246DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
247
248template <>
249struct OperandTraits<InsertElementConstantExpr>
250 : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};
251DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
252
253template <>
254struct OperandTraits<ShuffleVectorConstantExpr>
255 : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};
256DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
257
258template <>
259struct OperandTraits<GetElementPtrConstantExpr>
260 : public VariadicOperandTraits<GetElementPtrConstantExpr> {};
261
262DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
263
264template <class ConstantClass> struct ConstantAggrKeyType;
265struct InlineAsmKeyType;
266struct ConstantExprKeyType;
267struct ConstantPtrAuthKeyType;
268
269template <class ConstantClass> struct ConstantInfo;
270template <> struct ConstantInfo<ConstantExpr> {
271 using ValType = ConstantExprKeyType;
272 using TypeClass = Type;
273};
274template <> struct ConstantInfo<InlineAsm> {
275 using ValType = InlineAsmKeyType;
276 using TypeClass = PointerType;
277};
278template <> struct ConstantInfo<ConstantArray> {
279 using ValType = ConstantAggrKeyType<ConstantArray>;
280 using TypeClass = ArrayType;
281};
282template <> struct ConstantInfo<ConstantStruct> {
283 using ValType = ConstantAggrKeyType<ConstantStruct>;
284 using TypeClass = StructType;
285};
286template <> struct ConstantInfo<ConstantVector> {
287 using ValType = ConstantAggrKeyType<ConstantVector>;
288 using TypeClass = VectorType;
289};
290template <> struct ConstantInfo<ConstantPtrAuth> {
291 using ValType = ConstantPtrAuthKeyType;
292 using TypeClass = Type;
293};
294
295template <class ConstantClass> struct ConstantAggrKeyType {
296 ArrayRef<Constant *> Operands;
297
298 ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
299
300 ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
301 : Operands(Operands) {}
302
303 ConstantAggrKeyType(const ConstantClass *C,
304 SmallVectorImpl<Constant *> &Storage) {
305 assert(Storage.empty() && "Expected empty storage");
306 Storage.reserve(N: C->getNumOperands());
307 for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
308 Storage.push_back(Elt: C->getOperand(I));
309 Operands = Storage;
310 }
311
312 bool operator==(const ConstantAggrKeyType &X) const {
313 return Operands == X.Operands;
314 }
315
316 bool operator==(const ConstantClass *C) const {
317 if (Operands.size() != C->getNumOperands())
318 return false;
319 for (unsigned I = 0, E = Operands.size(); I != E; ++I)
320 if (Operands[I] != C->getOperand(I))
321 return false;
322 return true;
323 }
324
325 unsigned getHash() const { return hash_combine_range(R: Operands); }
326
327 using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
328
329 ConstantClass *create(TypeClass *Ty) const {
330 User::IntrusiveOperandsAllocMarker AllocMarker{.NumOps: unsigned(Operands.size())};
331 return new (AllocMarker) ConstantClass(Ty, Operands, AllocMarker);
332 }
333};
334
335struct InlineAsmKeyType {
336 StringRef AsmString;
337 StringRef Constraints;
338 FunctionType *FTy;
339 bool HasSideEffects;
340 bool IsAlignStack;
341 InlineAsm::AsmDialect AsmDialect;
342 bool CanThrow;
343
344 InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
345 FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,
346 InlineAsm::AsmDialect AsmDialect, bool canThrow)
347 : AsmString(AsmString), Constraints(Constraints), FTy(FTy),
348 HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
349 AsmDialect(AsmDialect), CanThrow(canThrow) {}
350
351 InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
352 : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
353 FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),
354 IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),
355 CanThrow(Asm->canThrow()) {}
356
357 bool operator==(const InlineAsmKeyType &X) const {
358 return HasSideEffects == X.HasSideEffects &&
359 IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
360 AsmString == X.AsmString && Constraints == X.Constraints &&
361 FTy == X.FTy && CanThrow == X.CanThrow;
362 }
363
364 bool operator==(const InlineAsm *Asm) const {
365 return HasSideEffects == Asm->hasSideEffects() &&
366 IsAlignStack == Asm->isAlignStack() &&
367 AsmDialect == Asm->getDialect() &&
368 AsmString == Asm->getAsmString() &&
369 Constraints == Asm->getConstraintString() &&
370 FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();
371 }
372
373 unsigned getHash() const {
374 return hash_combine(args: AsmString, args: Constraints, args: HasSideEffects, args: IsAlignStack,
375 args: AsmDialect, args: FTy, args: CanThrow);
376 }
377
378 using TypeClass = ConstantInfo<InlineAsm>::TypeClass;
379
380 InlineAsm *create(TypeClass *Ty) const {
381 assert(PointerType::getUnqual(FTy->getContext()) == Ty);
382 return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),
383 HasSideEffects, IsAlignStack, AsmDialect, CanThrow);
384 }
385};
386
387struct ConstantExprKeyType {
388private:
389 uint8_t Opcode;
390 uint8_t SubclassOptionalData;
391 ArrayRef<Constant *> Ops;
392 ArrayRef<int> ShuffleMask;
393 Type *ExplicitTy;
394 std::optional<ConstantRange> InRange;
395
396 static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
397 if (CE->getOpcode() == Instruction::ShuffleVector)
398 return CE->getShuffleMask();
399 return {};
400 }
401
402 static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {
403 if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(Val: CE))
404 return GEPCE->getSourceElementType();
405 return nullptr;
406 }
407
408 static std::optional<ConstantRange>
409 getInRangeIfValid(const ConstantExpr *CE) {
410 if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(Val: CE))
411 return GEPCE->getInRange();
412 return std::nullopt;
413 }
414
415public:
416 ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
417 unsigned short SubclassOptionalData = 0,
418 ArrayRef<int> ShuffleMask = {},
419 Type *ExplicitTy = nullptr,
420 std::optional<ConstantRange> InRange = std::nullopt)
421 : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), Ops(Ops),
422 ShuffleMask(ShuffleMask), ExplicitTy(ExplicitTy),
423 InRange(std::move(InRange)) {}
424
425 ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
426 : Opcode(CE->getOpcode()),
427 SubclassOptionalData(CE->getRawSubclassOptionalData()), Ops(Operands),
428 ShuffleMask(getShuffleMaskIfValid(CE)),
429 ExplicitTy(getSourceElementTypeIfValid(CE)),
430 InRange(getInRangeIfValid(CE)) {}
431
432 ConstantExprKeyType(const ConstantExpr *CE,
433 SmallVectorImpl<Constant *> &Storage)
434 : Opcode(CE->getOpcode()),
435 SubclassOptionalData(CE->getRawSubclassOptionalData()),
436 ShuffleMask(getShuffleMaskIfValid(CE)),
437 ExplicitTy(getSourceElementTypeIfValid(CE)),
438 InRange(getInRangeIfValid(CE)) {
439 assert(Storage.empty() && "Expected empty storage");
440 for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
441 Storage.push_back(Elt: CE->getOperand(i_nocapture: I));
442 Ops = Storage;
443 }
444
445 static bool rangesEqual(const std::optional<ConstantRange> &A,
446 const std::optional<ConstantRange> &B) {
447 if (!A.has_value() || !B.has_value())
448 return A.has_value() == B.has_value();
449 return A->getBitWidth() == B->getBitWidth() && A == B;
450 }
451
452 bool operator==(const ConstantExprKeyType &X) const {
453 return Opcode == X.Opcode &&
454 SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
455 ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy &&
456 rangesEqual(A: InRange, B: X.InRange);
457 }
458
459 bool operator==(const ConstantExpr *CE) const {
460 if (Opcode != CE->getOpcode())
461 return false;
462 if (SubclassOptionalData != CE->getRawSubclassOptionalData())
463 return false;
464 if (Ops.size() != CE->getNumOperands())
465 return false;
466 for (unsigned I = 0, E = Ops.size(); I != E; ++I)
467 if (Ops[I] != CE->getOperand(i_nocapture: I))
468 return false;
469 if (ShuffleMask != getShuffleMaskIfValid(CE))
470 return false;
471 if (ExplicitTy != getSourceElementTypeIfValid(CE))
472 return false;
473 if (!rangesEqual(A: InRange, B: getInRangeIfValid(CE)))
474 return false;
475 return true;
476 }
477
478 unsigned getHash() const {
479 return hash_combine(args: Opcode, args: SubclassOptionalData, args: hash_combine_range(R: Ops),
480 args: hash_combine_range(R: ShuffleMask), args: ExplicitTy);
481 }
482
483 using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;
484
485 ConstantExpr *create(TypeClass *Ty) const {
486 switch (Opcode) {
487 default:
488 if (Instruction::isCast(Opcode))
489 return new CastConstantExpr(Opcode, Ops[0], Ty);
490 if (Instruction::isBinaryOp(Opcode))
491 return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
492 SubclassOptionalData);
493 llvm_unreachable("Invalid ConstantExpr!");
494 case Instruction::ExtractElement:
495 return new ExtractElementConstantExpr(Ops[0], Ops[1]);
496 case Instruction::InsertElement:
497 return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
498 case Instruction::ShuffleVector:
499 return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
500 case Instruction::GetElementPtr:
501 return GetElementPtrConstantExpr::Create(
502 SrcElementTy: ExplicitTy, C: Ops[0], IdxList: Ops.slice(N: 1), DestTy: Ty, Flags: SubclassOptionalData, InRange);
503 }
504 }
505};
506
507struct ConstantPtrAuthKeyType {
508 ArrayRef<Constant *> Operands;
509
510 ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
511
512 ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands, const ConstantPtrAuth *)
513 : Operands(Operands) {}
514
515 ConstantPtrAuthKeyType(const ConstantPtrAuth *C,
516 SmallVectorImpl<Constant *> &Storage) {
517 assert(Storage.empty() && "Expected empty storage");
518 for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
519 Storage.push_back(Elt: cast<Constant>(Val: C->getOperand(i_nocapture: I)));
520 Operands = Storage;
521 }
522
523 bool operator==(const ConstantPtrAuthKeyType &X) const {
524 return Operands == X.Operands;
525 }
526
527 bool operator==(const ConstantPtrAuth *C) const {
528 if (Operands.size() != C->getNumOperands())
529 return false;
530 for (unsigned I = 0, E = Operands.size(); I != E; ++I)
531 if (Operands[I] != C->getOperand(i_nocapture: I))
532 return false;
533 return true;
534 }
535
536 unsigned getHash() const { return hash_combine_range(R: Operands); }
537
538 using TypeClass = typename ConstantInfo<ConstantPtrAuth>::TypeClass;
539
540 ConstantPtrAuth *create(TypeClass *Ty) const {
541 return new ConstantPtrAuth(Operands[0], cast<ConstantInt>(Val: Operands[1]),
542 cast<ConstantInt>(Val: Operands[2]), Operands[3]);
543 }
544};
545
546// Free memory for a given constant. Assumes the constant has already been
547// removed from all relevant maps.
548void deleteConstant(Constant *C);
549
550template <class ConstantClass> class ConstantUniqueMap {
551public:
552 using ValType = typename ConstantInfo<ConstantClass>::ValType;
553 using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
554 using LookupKey = std::pair<TypeClass *, ValType>;
555
556 /// Key and hash together, so that we compute the hash only once and reuse it.
557 using LookupKeyHashed = std::pair<unsigned, LookupKey>;
558
559private:
560 struct MapInfo {
561 using ConstantClassInfo = DenseMapInfo<ConstantClass *>;
562
563 static inline ConstantClass *getEmptyKey() {
564 return ConstantClassInfo::getEmptyKey();
565 }
566
567 static inline ConstantClass *getTombstoneKey() {
568 return ConstantClassInfo::getTombstoneKey();
569 }
570
571 static unsigned getHashValue(const ConstantClass *CP) {
572 SmallVector<Constant *, 32> Storage;
573 return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
574 }
575
576 static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
577 return LHS == RHS;
578 }
579
580 static unsigned getHashValue(const LookupKey &Val) {
581 return hash_combine(Val.first, Val.second.getHash());
582 }
583
584 static unsigned getHashValue(const LookupKeyHashed &Val) {
585 return Val.first;
586 }
587
588 static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
589 if (RHS == getEmptyKey() || RHS == getTombstoneKey())
590 return false;
591 if (LHS.first != RHS->getType())
592 return false;
593 return LHS.second == RHS;
594 }
595
596 static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
597 return isEqual(LHS.second, RHS);
598 }
599 };
600
601public:
602 using MapTy = DenseSet<ConstantClass *, MapInfo>;
603
604private:
605 MapTy Map;
606
607public:
608 typename MapTy::iterator begin() { return Map.begin(); }
609 typename MapTy::iterator end() { return Map.end(); }
610
611 void freeConstants() {
612 for (auto &I : Map)
613 deleteConstant(I);
614 }
615
616private:
617 ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
618 ConstantClass *Result = V.create(Ty);
619
620 assert(Result->getType() == Ty && "Type specified is not correct!");
621 Map.insert_as(Result, HashKey);
622
623 return Result;
624 }
625
626public:
627 /// Return the specified constant from the map, creating it if necessary.
628 ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
629 LookupKey Key(Ty, V);
630 /// Hash once, and reuse it for the lookup and the insertion if needed.
631 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
632
633 ConstantClass *Result = nullptr;
634
635 auto I = Map.find_as(Lookup);
636 if (I == Map.end())
637 Result = create(Ty, V, HashKey&: Lookup);
638 else
639 Result = *I;
640 assert(Result && "Unexpected nullptr");
641
642 return Result;
643 }
644
645 /// Remove this constant from the map
646 void remove(ConstantClass *CP) {
647 typename MapTy::iterator I = Map.find(CP);
648 assert(I != Map.end() && "Constant not found in constant table!");
649 assert(*I == CP && "Didn't find correct element?");
650 Map.erase(I);
651 }
652
653 ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
654 ConstantClass *CP, Value *From,
655 Constant *To, unsigned NumUpdated = 0,
656 unsigned OperandNo = ~0u) {
657 LookupKey Key(CP->getType(), ValType(Operands, CP));
658 /// Hash once, and reuse it for the lookup and the insertion if needed.
659 LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
660
661 auto ItMap = Map.find_as(Lookup);
662 if (ItMap != Map.end())
663 return *ItMap;
664
665 // Update to the new value. Optimize for the case when we have a single
666 // operand that we're changing, but handle bulk updates efficiently.
667 remove(CP);
668 if (NumUpdated == 1) {
669 assert(OperandNo < CP->getNumOperands() && "Invalid index");
670 assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
671 CP->setOperand(OperandNo, To);
672 } else {
673 for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
674 if (CP->getOperand(I) == From)
675 CP->setOperand(I, To);
676 }
677 Map.insert_as(CP, Lookup);
678 return nullptr;
679 }
680
681 void dump() const {
682 LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
683 }
684};
685
686template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {
687 for (auto &I : Map)
688 delete I;
689}
690
691} // end namespace llvm
692
693#endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H
694