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