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