xref: /openbsd/gnu/llvm/llvm/lib/IR/ConstantsContext.h (revision d415bd75)
109467b48Spatrick //===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick //  This file defines various helper methods and classes used by
1009467b48Spatrick // LLVMContextImpl for creating and managing constants.
1109467b48Spatrick //
1209467b48Spatrick //===----------------------------------------------------------------------===//
1309467b48Spatrick 
1409467b48Spatrick #ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
1509467b48Spatrick #define LLVM_LIB_IR_CONSTANTSCONTEXT_H
1609467b48Spatrick 
1709467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1809467b48Spatrick #include "llvm/ADT/DenseMapInfo.h"
1909467b48Spatrick #include "llvm/ADT/DenseSet.h"
2009467b48Spatrick #include "llvm/ADT/Hashing.h"
2109467b48Spatrick #include "llvm/ADT/SmallVector.h"
2209467b48Spatrick #include "llvm/ADT/StringRef.h"
2309467b48Spatrick #include "llvm/IR/Constant.h"
2409467b48Spatrick #include "llvm/IR/Constants.h"
2509467b48Spatrick #include "llvm/IR/DerivedTypes.h"
2609467b48Spatrick #include "llvm/IR/InlineAsm.h"
2709467b48Spatrick #include "llvm/IR/Instruction.h"
28097a140dSpatrick #include "llvm/IR/Instructions.h"
2909467b48Spatrick #include "llvm/IR/OperandTraits.h"
3009467b48Spatrick #include "llvm/Support/Casting.h"
3109467b48Spatrick #include "llvm/Support/Debug.h"
3209467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3309467b48Spatrick #include "llvm/Support/raw_ostream.h"
3409467b48Spatrick #include <cassert>
3509467b48Spatrick #include <cstddef>
3609467b48Spatrick #include <cstdint>
3709467b48Spatrick #include <utility>
3809467b48Spatrick 
3909467b48Spatrick #define DEBUG_TYPE "ir"
4009467b48Spatrick 
4109467b48Spatrick namespace llvm {
4209467b48Spatrick 
43*d415bd75Srobert /// CastConstantExpr - This class is private to Constants.cpp, and is used
44*d415bd75Srobert /// behind the scenes to implement cast constant exprs.
45*d415bd75Srobert class CastConstantExpr final : public ConstantExpr {
4609467b48Spatrick public:
CastConstantExpr(unsigned Opcode,Constant * C,Type * Ty)47*d415bd75Srobert   CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
4809467b48Spatrick     : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
4909467b48Spatrick     Op<0>() = C;
5009467b48Spatrick   }
5109467b48Spatrick 
5209467b48Spatrick   // allocate space for exactly one operand
new(size_t S)5373471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 1); }
delete(void * Ptr)5473471bf0Spatrick   void operator delete(void *Ptr) { User::operator delete(Ptr); }
5509467b48Spatrick 
5609467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
57097a140dSpatrick 
classof(const ConstantExpr * CE)58097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
59*d415bd75Srobert     return Instruction::isCast(CE->getOpcode());
60097a140dSpatrick   }
classof(const Value * V)61097a140dSpatrick   static bool classof(const Value *V) {
62097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
63097a140dSpatrick   }
6409467b48Spatrick };
6509467b48Spatrick 
6609467b48Spatrick /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
6709467b48Spatrick /// behind the scenes to implement binary constant exprs.
68097a140dSpatrick class BinaryConstantExpr final : public ConstantExpr {
6909467b48Spatrick public:
BinaryConstantExpr(unsigned Opcode,Constant * C1,Constant * C2,unsigned Flags)7009467b48Spatrick   BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
7109467b48Spatrick                      unsigned Flags)
7209467b48Spatrick     : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
7309467b48Spatrick     Op<0>() = C1;
7409467b48Spatrick     Op<1>() = C2;
7509467b48Spatrick     SubclassOptionalData = Flags;
7609467b48Spatrick   }
7709467b48Spatrick 
7809467b48Spatrick   // allocate space for exactly two operands
new(size_t S)7973471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)8073471bf0Spatrick   void operator delete(void *Ptr) { User::operator delete(Ptr); }
8109467b48Spatrick 
8209467b48Spatrick   /// Transparently provide more efficient getOperand methods.
8309467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
84097a140dSpatrick 
classof(const ConstantExpr * CE)85097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
86097a140dSpatrick     return Instruction::isBinaryOp(CE->getOpcode());
87097a140dSpatrick   }
classof(const Value * V)88097a140dSpatrick   static bool classof(const Value *V) {
89097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
90097a140dSpatrick   }
9109467b48Spatrick };
9209467b48Spatrick 
9309467b48Spatrick /// SelectConstantExpr - This class is private to Constants.cpp, and is used
9409467b48Spatrick /// behind the scenes to implement select constant exprs.
95097a140dSpatrick class SelectConstantExpr final : public ConstantExpr {
9609467b48Spatrick public:
SelectConstantExpr(Constant * C1,Constant * C2,Constant * C3)9709467b48Spatrick   SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
9809467b48Spatrick     : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
9909467b48Spatrick     Op<0>() = C1;
10009467b48Spatrick     Op<1>() = C2;
10109467b48Spatrick     Op<2>() = C3;
10209467b48Spatrick   }
10309467b48Spatrick 
10409467b48Spatrick   // allocate space for exactly three operands
new(size_t S)10573471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 3); }
delete(void * Ptr)10673471bf0Spatrick   void operator delete(void *Ptr) { User::operator delete(Ptr); }
10709467b48Spatrick 
10809467b48Spatrick   /// Transparently provide more efficient getOperand methods.
10909467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
110097a140dSpatrick 
classof(const ConstantExpr * CE)111097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
112097a140dSpatrick     return CE->getOpcode() == Instruction::Select;
113097a140dSpatrick   }
classof(const Value * V)114097a140dSpatrick   static bool classof(const Value *V) {
115097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
116097a140dSpatrick   }
11709467b48Spatrick };
11809467b48Spatrick 
11909467b48Spatrick /// ExtractElementConstantExpr - This class is private to
12009467b48Spatrick /// Constants.cpp, and is used behind the scenes to implement
12109467b48Spatrick /// extractelement constant exprs.
122097a140dSpatrick class ExtractElementConstantExpr final : public ConstantExpr {
12309467b48Spatrick public:
ExtractElementConstantExpr(Constant * C1,Constant * C2)12409467b48Spatrick   ExtractElementConstantExpr(Constant *C1, Constant *C2)
12509467b48Spatrick     : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
12609467b48Spatrick                    Instruction::ExtractElement, &Op<0>(), 2) {
12709467b48Spatrick     Op<0>() = C1;
12809467b48Spatrick     Op<1>() = C2;
12909467b48Spatrick   }
13009467b48Spatrick 
13109467b48Spatrick   // allocate space for exactly two operands
new(size_t S)13273471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)13373471bf0Spatrick   void operator delete(void *Ptr) { User::operator delete(Ptr); }
13409467b48Spatrick 
13509467b48Spatrick   /// Transparently provide more efficient getOperand methods.
13609467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
137097a140dSpatrick 
classof(const ConstantExpr * CE)138097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
139097a140dSpatrick     return CE->getOpcode() == Instruction::ExtractElement;
140097a140dSpatrick   }
classof(const Value * V)141097a140dSpatrick   static bool classof(const Value *V) {
142097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
143097a140dSpatrick   }
14409467b48Spatrick };
14509467b48Spatrick 
14609467b48Spatrick /// InsertElementConstantExpr - This class is private to
14709467b48Spatrick /// Constants.cpp, and is used behind the scenes to implement
14809467b48Spatrick /// insertelement constant exprs.
149097a140dSpatrick class InsertElementConstantExpr final : public ConstantExpr {
15009467b48Spatrick public:
InsertElementConstantExpr(Constant * C1,Constant * C2,Constant * C3)15109467b48Spatrick   InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
15209467b48Spatrick     : ConstantExpr(C1->getType(), Instruction::InsertElement,
15309467b48Spatrick                    &Op<0>(), 3) {
15409467b48Spatrick     Op<0>() = C1;
15509467b48Spatrick     Op<1>() = C2;
15609467b48Spatrick     Op<2>() = C3;
15709467b48Spatrick   }
15809467b48Spatrick 
15909467b48Spatrick   // allocate space for exactly three operands
new(size_t S)16073471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 3); }
delete(void * Ptr)16173471bf0Spatrick   void operator delete(void *Ptr) { User::operator delete(Ptr); }
16209467b48Spatrick 
16309467b48Spatrick   /// Transparently provide more efficient getOperand methods.
16409467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
165097a140dSpatrick 
classof(const ConstantExpr * CE)166097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
167097a140dSpatrick     return CE->getOpcode() == Instruction::InsertElement;
168097a140dSpatrick   }
classof(const Value * V)169097a140dSpatrick   static bool classof(const Value *V) {
170097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
171097a140dSpatrick   }
17209467b48Spatrick };
17309467b48Spatrick 
17409467b48Spatrick /// ShuffleVectorConstantExpr - This class is private to
17509467b48Spatrick /// Constants.cpp, and is used behind the scenes to implement
17609467b48Spatrick /// shufflevector constant exprs.
177097a140dSpatrick class ShuffleVectorConstantExpr final : public ConstantExpr {
17809467b48Spatrick public:
ShuffleVectorConstantExpr(Constant * C1,Constant * C2,ArrayRef<int> Mask)179097a140dSpatrick   ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)
18009467b48Spatrick       : ConstantExpr(VectorType::get(
18109467b48Spatrick                          cast<VectorType>(C1->getType())->getElementType(),
182097a140dSpatrick                          Mask.size(), isa<ScalableVectorType>(C1->getType())),
183097a140dSpatrick                      Instruction::ShuffleVector, &Op<0>(), 2) {
184097a140dSpatrick     assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&
185097a140dSpatrick            "Invalid shuffle vector instruction operands!");
18609467b48Spatrick     Op<0>() = C1;
18709467b48Spatrick     Op<1>() = C2;
188097a140dSpatrick     ShuffleMask.assign(Mask.begin(), Mask.end());
189097a140dSpatrick     ShuffleMaskForBitcode =
190097a140dSpatrick         ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType());
19109467b48Spatrick   }
19209467b48Spatrick 
193097a140dSpatrick   SmallVector<int, 4> ShuffleMask;
194097a140dSpatrick   Constant *ShuffleMaskForBitcode;
195097a140dSpatrick 
new(size_t S)19673471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)19773471bf0Spatrick   void operator delete(void *Ptr) { return User::operator delete(Ptr); }
19809467b48Spatrick 
19909467b48Spatrick   /// Transparently provide more efficient getOperand methods.
20009467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
201097a140dSpatrick 
classof(const ConstantExpr * CE)202097a140dSpatrick   static bool classof(const ConstantExpr *CE) {
203097a140dSpatrick     return CE->getOpcode() == Instruction::ShuffleVector;
204097a140dSpatrick   }
classof(const Value * V)205097a140dSpatrick   static bool classof(const Value *V) {
206097a140dSpatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
207097a140dSpatrick   }
20809467b48Spatrick };
20909467b48Spatrick 
21009467b48Spatrick /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
21109467b48Spatrick /// used behind the scenes to implement getelementpr constant exprs.
212097a140dSpatrick class GetElementPtrConstantExpr final : public ConstantExpr {
21309467b48Spatrick   Type *SrcElementTy;
21409467b48Spatrick   Type *ResElementTy;
21509467b48Spatrick 
21609467b48Spatrick   GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
21709467b48Spatrick                             ArrayRef<Constant *> IdxList, Type *DestTy);
21809467b48Spatrick 
21909467b48Spatrick public:
Create(Type * SrcElementTy,Constant * C,ArrayRef<Constant * > IdxList,Type * DestTy,unsigned Flags)22009467b48Spatrick   static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
22109467b48Spatrick                                            ArrayRef<Constant *> IdxList,
22209467b48Spatrick                                            Type *DestTy, unsigned Flags) {
22309467b48Spatrick     GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)
22409467b48Spatrick         GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy);
22509467b48Spatrick     Result->SubclassOptionalData = Flags;
22609467b48Spatrick     return Result;
22709467b48Spatrick   }
22809467b48Spatrick 
22909467b48Spatrick   Type *getSourceElementType() const;
23009467b48Spatrick   Type *getResultElementType() const;
23109467b48Spatrick 
23209467b48Spatrick   /// Transparently provide more efficient getOperand methods.
23309467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
23409467b48Spatrick 
classof(const ConstantExpr * CE)23509467b48Spatrick   static bool classof(const ConstantExpr *CE) {
23609467b48Spatrick     return CE->getOpcode() == Instruction::GetElementPtr;
23709467b48Spatrick   }
classof(const Value * V)23809467b48Spatrick   static bool classof(const Value *V) {
23909467b48Spatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
24009467b48Spatrick   }
24109467b48Spatrick };
24209467b48Spatrick 
24309467b48Spatrick // CompareConstantExpr - This class is private to Constants.cpp, and is used
24409467b48Spatrick // behind the scenes to implement ICmp and FCmp constant expressions. This is
24509467b48Spatrick // needed in order to store the predicate value for these instructions.
246097a140dSpatrick class CompareConstantExpr final : public ConstantExpr {
24709467b48Spatrick public:
24809467b48Spatrick   unsigned short predicate;
CompareConstantExpr(Type * ty,Instruction::OtherOps opc,unsigned short pred,Constant * LHS,Constant * RHS)24909467b48Spatrick   CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
25009467b48Spatrick                       unsigned short pred,  Constant* LHS, Constant* RHS)
25109467b48Spatrick     : ConstantExpr(ty, opc, &Op<0>(), 2), predicate(pred) {
25209467b48Spatrick     Op<0>() = LHS;
25309467b48Spatrick     Op<1>() = RHS;
25409467b48Spatrick   }
25509467b48Spatrick 
25609467b48Spatrick   // allocate space for exactly two operands
new(size_t S)25773471bf0Spatrick   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)25873471bf0Spatrick   void operator delete(void *Ptr) { return User::operator delete(Ptr); }
25909467b48Spatrick 
26009467b48Spatrick   /// Transparently provide more efficient getOperand methods.
26109467b48Spatrick   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
26209467b48Spatrick 
classof(const ConstantExpr * CE)26309467b48Spatrick   static bool classof(const ConstantExpr *CE) {
26409467b48Spatrick     return CE->getOpcode() == Instruction::ICmp ||
26509467b48Spatrick            CE->getOpcode() == Instruction::FCmp;
26609467b48Spatrick   }
classof(const Value * V)26709467b48Spatrick   static bool classof(const Value *V) {
26809467b48Spatrick     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
26909467b48Spatrick   }
27009467b48Spatrick };
27109467b48Spatrick 
27209467b48Spatrick template <>
273*d415bd75Srobert struct OperandTraits<CastConstantExpr>
274*d415bd75Srobert     : public FixedNumOperandTraits<CastConstantExpr, 1> {};
275*d415bd75Srobert DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value)
27609467b48Spatrick 
27709467b48Spatrick template <>
27809467b48Spatrick struct OperandTraits<BinaryConstantExpr>
27909467b48Spatrick     : public FixedNumOperandTraits<BinaryConstantExpr, 2> {};
28009467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
28109467b48Spatrick 
28209467b48Spatrick template <>
28309467b48Spatrick struct OperandTraits<SelectConstantExpr>
28409467b48Spatrick     : public FixedNumOperandTraits<SelectConstantExpr, 3> {};
28509467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value)
28609467b48Spatrick 
28709467b48Spatrick template <>
28809467b48Spatrick struct OperandTraits<ExtractElementConstantExpr>
28909467b48Spatrick     : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};
29009467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
29109467b48Spatrick 
29209467b48Spatrick template <>
29309467b48Spatrick struct OperandTraits<InsertElementConstantExpr>
29409467b48Spatrick     : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};
29509467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
29609467b48Spatrick 
29709467b48Spatrick template <>
29809467b48Spatrick struct OperandTraits<ShuffleVectorConstantExpr>
299097a140dSpatrick     : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};
30009467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
30109467b48Spatrick 
30209467b48Spatrick template <>
30309467b48Spatrick struct OperandTraits<GetElementPtrConstantExpr>
30409467b48Spatrick     : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {};
30509467b48Spatrick 
30609467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
30709467b48Spatrick 
30809467b48Spatrick template <>
30909467b48Spatrick struct OperandTraits<CompareConstantExpr>
31009467b48Spatrick     : public FixedNumOperandTraits<CompareConstantExpr, 2> {};
31109467b48Spatrick DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
31209467b48Spatrick 
31309467b48Spatrick template <class ConstantClass> struct ConstantAggrKeyType;
31409467b48Spatrick struct InlineAsmKeyType;
31509467b48Spatrick struct ConstantExprKeyType;
31609467b48Spatrick 
31709467b48Spatrick template <class ConstantClass> struct ConstantInfo;
31809467b48Spatrick template <> struct ConstantInfo<ConstantExpr> {
31909467b48Spatrick   using ValType = ConstantExprKeyType;
32009467b48Spatrick   using TypeClass = Type;
32109467b48Spatrick };
32209467b48Spatrick template <> struct ConstantInfo<InlineAsm> {
32309467b48Spatrick   using ValType = InlineAsmKeyType;
32409467b48Spatrick   using TypeClass = PointerType;
32509467b48Spatrick };
32609467b48Spatrick template <> struct ConstantInfo<ConstantArray> {
32709467b48Spatrick   using ValType = ConstantAggrKeyType<ConstantArray>;
32809467b48Spatrick   using TypeClass = ArrayType;
32909467b48Spatrick };
33009467b48Spatrick template <> struct ConstantInfo<ConstantStruct> {
33109467b48Spatrick   using ValType = ConstantAggrKeyType<ConstantStruct>;
33209467b48Spatrick   using TypeClass = StructType;
33309467b48Spatrick };
33409467b48Spatrick template <> struct ConstantInfo<ConstantVector> {
33509467b48Spatrick   using ValType = ConstantAggrKeyType<ConstantVector>;
33609467b48Spatrick   using TypeClass = VectorType;
33709467b48Spatrick };
33809467b48Spatrick 
33909467b48Spatrick template <class ConstantClass> struct ConstantAggrKeyType {
34009467b48Spatrick   ArrayRef<Constant *> Operands;
34109467b48Spatrick 
34209467b48Spatrick   ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
34309467b48Spatrick 
34409467b48Spatrick   ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
34509467b48Spatrick       : Operands(Operands) {}
34609467b48Spatrick 
34709467b48Spatrick   ConstantAggrKeyType(const ConstantClass *C,
34809467b48Spatrick                       SmallVectorImpl<Constant *> &Storage) {
34909467b48Spatrick     assert(Storage.empty() && "Expected empty storage");
35009467b48Spatrick     for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
35109467b48Spatrick       Storage.push_back(C->getOperand(I));
35209467b48Spatrick     Operands = Storage;
35309467b48Spatrick   }
35409467b48Spatrick 
35509467b48Spatrick   bool operator==(const ConstantAggrKeyType &X) const {
35609467b48Spatrick     return Operands == X.Operands;
35709467b48Spatrick   }
35809467b48Spatrick 
35909467b48Spatrick   bool operator==(const ConstantClass *C) const {
36009467b48Spatrick     if (Operands.size() != C->getNumOperands())
36109467b48Spatrick       return false;
36209467b48Spatrick     for (unsigned I = 0, E = Operands.size(); I != E; ++I)
36309467b48Spatrick       if (Operands[I] != C->getOperand(I))
36409467b48Spatrick         return false;
36509467b48Spatrick     return true;
36609467b48Spatrick   }
36709467b48Spatrick 
36809467b48Spatrick   unsigned getHash() const {
36909467b48Spatrick     return hash_combine_range(Operands.begin(), Operands.end());
37009467b48Spatrick   }
37109467b48Spatrick 
37209467b48Spatrick   using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
37309467b48Spatrick 
37409467b48Spatrick   ConstantClass *create(TypeClass *Ty) const {
37509467b48Spatrick     return new (Operands.size()) ConstantClass(Ty, Operands);
37609467b48Spatrick   }
37709467b48Spatrick };
37809467b48Spatrick 
37909467b48Spatrick struct InlineAsmKeyType {
38009467b48Spatrick   StringRef AsmString;
38109467b48Spatrick   StringRef Constraints;
38209467b48Spatrick   FunctionType *FTy;
38309467b48Spatrick   bool HasSideEffects;
38409467b48Spatrick   bool IsAlignStack;
38509467b48Spatrick   InlineAsm::AsmDialect AsmDialect;
38673471bf0Spatrick   bool CanThrow;
38709467b48Spatrick 
38809467b48Spatrick   InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
38909467b48Spatrick                    FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,
39073471bf0Spatrick                    InlineAsm::AsmDialect AsmDialect, bool canThrow)
39109467b48Spatrick       : AsmString(AsmString), Constraints(Constraints), FTy(FTy),
39209467b48Spatrick         HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
39373471bf0Spatrick         AsmDialect(AsmDialect), CanThrow(canThrow) {}
39409467b48Spatrick 
39509467b48Spatrick   InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
39609467b48Spatrick       : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
39709467b48Spatrick         FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),
39873471bf0Spatrick         IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),
39973471bf0Spatrick         CanThrow(Asm->canThrow()) {}
40009467b48Spatrick 
40109467b48Spatrick   bool operator==(const InlineAsmKeyType &X) const {
40209467b48Spatrick     return HasSideEffects == X.HasSideEffects &&
40309467b48Spatrick            IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
40409467b48Spatrick            AsmString == X.AsmString && Constraints == X.Constraints &&
40573471bf0Spatrick            FTy == X.FTy && CanThrow == X.CanThrow;
40609467b48Spatrick   }
40709467b48Spatrick 
40809467b48Spatrick   bool operator==(const InlineAsm *Asm) const {
40909467b48Spatrick     return HasSideEffects == Asm->hasSideEffects() &&
41009467b48Spatrick            IsAlignStack == Asm->isAlignStack() &&
41109467b48Spatrick            AsmDialect == Asm->getDialect() &&
41209467b48Spatrick            AsmString == Asm->getAsmString() &&
41309467b48Spatrick            Constraints == Asm->getConstraintString() &&
41473471bf0Spatrick            FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();
41509467b48Spatrick   }
41609467b48Spatrick 
41709467b48Spatrick   unsigned getHash() const {
41809467b48Spatrick     return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
41973471bf0Spatrick                         AsmDialect, FTy, CanThrow);
42009467b48Spatrick   }
42109467b48Spatrick 
42209467b48Spatrick   using TypeClass = ConstantInfo<InlineAsm>::TypeClass;
42309467b48Spatrick 
42409467b48Spatrick   InlineAsm *create(TypeClass *Ty) const {
42509467b48Spatrick     assert(PointerType::getUnqual(FTy) == Ty);
426097a140dSpatrick     return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),
42773471bf0Spatrick                          HasSideEffects, IsAlignStack, AsmDialect, CanThrow);
42809467b48Spatrick   }
42909467b48Spatrick };
43009467b48Spatrick 
43109467b48Spatrick struct ConstantExprKeyType {
432097a140dSpatrick private:
43309467b48Spatrick   uint8_t Opcode;
43409467b48Spatrick   uint8_t SubclassOptionalData;
43509467b48Spatrick   uint16_t SubclassData;
43609467b48Spatrick   ArrayRef<Constant *> Ops;
437097a140dSpatrick   ArrayRef<int> ShuffleMask;
43809467b48Spatrick   Type *ExplicitTy;
43909467b48Spatrick 
440097a140dSpatrick   static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
441097a140dSpatrick     if (CE->getOpcode() == Instruction::ShuffleVector)
442097a140dSpatrick       return CE->getShuffleMask();
443*d415bd75Srobert     return std::nullopt;
444097a140dSpatrick   }
445097a140dSpatrick 
446097a140dSpatrick   static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {
447097a140dSpatrick     if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
448097a140dSpatrick       return GEPCE->getSourceElementType();
449097a140dSpatrick     return nullptr;
450097a140dSpatrick   }
451097a140dSpatrick 
452097a140dSpatrick public:
45309467b48Spatrick   ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
45409467b48Spatrick                       unsigned short SubclassData = 0,
45509467b48Spatrick                       unsigned short SubclassOptionalData = 0,
456*d415bd75Srobert                       ArrayRef<int> ShuffleMask = std::nullopt,
45709467b48Spatrick                       Type *ExplicitTy = nullptr)
45809467b48Spatrick       : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
459*d415bd75Srobert         SubclassData(SubclassData), Ops(Ops), ShuffleMask(ShuffleMask),
460*d415bd75Srobert         ExplicitTy(ExplicitTy) {}
46109467b48Spatrick 
46209467b48Spatrick   ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
46309467b48Spatrick       : Opcode(CE->getOpcode()),
46409467b48Spatrick         SubclassOptionalData(CE->getRawSubclassOptionalData()),
46509467b48Spatrick         SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands),
466*d415bd75Srobert         ShuffleMask(getShuffleMaskIfValid(CE)),
467097a140dSpatrick         ExplicitTy(getSourceElementTypeIfValid(CE)) {}
46809467b48Spatrick 
46909467b48Spatrick   ConstantExprKeyType(const ConstantExpr *CE,
47009467b48Spatrick                       SmallVectorImpl<Constant *> &Storage)
47109467b48Spatrick       : Opcode(CE->getOpcode()),
47209467b48Spatrick         SubclassOptionalData(CE->getRawSubclassOptionalData()),
47309467b48Spatrick         SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
474*d415bd75Srobert         ShuffleMask(getShuffleMaskIfValid(CE)),
475097a140dSpatrick         ExplicitTy(getSourceElementTypeIfValid(CE)) {
47609467b48Spatrick     assert(Storage.empty() && "Expected empty storage");
47709467b48Spatrick     for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
47809467b48Spatrick       Storage.push_back(CE->getOperand(I));
47909467b48Spatrick     Ops = Storage;
48009467b48Spatrick   }
48109467b48Spatrick 
48209467b48Spatrick   bool operator==(const ConstantExprKeyType &X) const {
48309467b48Spatrick     return Opcode == X.Opcode && SubclassData == X.SubclassData &&
48409467b48Spatrick            SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
485*d415bd75Srobert            ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy;
48609467b48Spatrick   }
48709467b48Spatrick 
48809467b48Spatrick   bool operator==(const ConstantExpr *CE) const {
48909467b48Spatrick     if (Opcode != CE->getOpcode())
49009467b48Spatrick       return false;
49109467b48Spatrick     if (SubclassOptionalData != CE->getRawSubclassOptionalData())
49209467b48Spatrick       return false;
49309467b48Spatrick     if (Ops.size() != CE->getNumOperands())
49409467b48Spatrick       return false;
49509467b48Spatrick     if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
49609467b48Spatrick       return false;
49709467b48Spatrick     for (unsigned I = 0, E = Ops.size(); I != E; ++I)
49809467b48Spatrick       if (Ops[I] != CE->getOperand(I))
49909467b48Spatrick         return false;
500097a140dSpatrick     if (ShuffleMask != getShuffleMaskIfValid(CE))
501097a140dSpatrick       return false;
502097a140dSpatrick     if (ExplicitTy != getSourceElementTypeIfValid(CE))
50309467b48Spatrick       return false;
50409467b48Spatrick     return true;
50509467b48Spatrick   }
50609467b48Spatrick 
50709467b48Spatrick   unsigned getHash() const {
508097a140dSpatrick     return hash_combine(
509097a140dSpatrick         Opcode, SubclassOptionalData, SubclassData,
51009467b48Spatrick         hash_combine_range(Ops.begin(), Ops.end()),
511097a140dSpatrick         hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy);
51209467b48Spatrick   }
51309467b48Spatrick 
51409467b48Spatrick   using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;
51509467b48Spatrick 
51609467b48Spatrick   ConstantExpr *create(TypeClass *Ty) const {
51709467b48Spatrick     switch (Opcode) {
51809467b48Spatrick     default:
519*d415bd75Srobert       if (Instruction::isCast(Opcode))
520*d415bd75Srobert         return new CastConstantExpr(Opcode, Ops[0], Ty);
52109467b48Spatrick       if ((Opcode >= Instruction::BinaryOpsBegin &&
52209467b48Spatrick            Opcode < Instruction::BinaryOpsEnd))
52309467b48Spatrick         return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
52409467b48Spatrick                                       SubclassOptionalData);
52509467b48Spatrick       llvm_unreachable("Invalid ConstantExpr!");
52609467b48Spatrick     case Instruction::Select:
52709467b48Spatrick       return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]);
52809467b48Spatrick     case Instruction::ExtractElement:
52909467b48Spatrick       return new ExtractElementConstantExpr(Ops[0], Ops[1]);
53009467b48Spatrick     case Instruction::InsertElement:
53109467b48Spatrick       return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
53209467b48Spatrick     case Instruction::ShuffleVector:
533097a140dSpatrick       return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
53409467b48Spatrick     case Instruction::GetElementPtr:
535097a140dSpatrick       return GetElementPtrConstantExpr::Create(ExplicitTy, Ops[0], Ops.slice(1),
536097a140dSpatrick                                                Ty, SubclassOptionalData);
53709467b48Spatrick     case Instruction::ICmp:
53809467b48Spatrick       return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
53909467b48Spatrick                                      Ops[0], Ops[1]);
54009467b48Spatrick     case Instruction::FCmp:
54109467b48Spatrick       return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
54209467b48Spatrick                                      Ops[0], Ops[1]);
54309467b48Spatrick     }
54409467b48Spatrick   }
54509467b48Spatrick };
54609467b48Spatrick 
547097a140dSpatrick // Free memory for a given constant.  Assumes the constant has already been
548097a140dSpatrick // removed from all relevant maps.
549097a140dSpatrick void deleteConstant(Constant *C);
550097a140dSpatrick 
55109467b48Spatrick template <class ConstantClass> class ConstantUniqueMap {
55209467b48Spatrick public:
55309467b48Spatrick   using ValType = typename ConstantInfo<ConstantClass>::ValType;
55409467b48Spatrick   using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
55509467b48Spatrick   using LookupKey = std::pair<TypeClass *, ValType>;
55609467b48Spatrick 
55709467b48Spatrick   /// Key and hash together, so that we compute the hash only once and reuse it.
55809467b48Spatrick   using LookupKeyHashed = std::pair<unsigned, LookupKey>;
55909467b48Spatrick 
56009467b48Spatrick private:
56109467b48Spatrick   struct MapInfo {
56209467b48Spatrick     using ConstantClassInfo = DenseMapInfo<ConstantClass *>;
56309467b48Spatrick 
56409467b48Spatrick     static inline ConstantClass *getEmptyKey() {
56509467b48Spatrick       return ConstantClassInfo::getEmptyKey();
56609467b48Spatrick     }
56709467b48Spatrick 
56809467b48Spatrick     static inline ConstantClass *getTombstoneKey() {
56909467b48Spatrick       return ConstantClassInfo::getTombstoneKey();
57009467b48Spatrick     }
57109467b48Spatrick 
57209467b48Spatrick     static unsigned getHashValue(const ConstantClass *CP) {
57309467b48Spatrick       SmallVector<Constant *, 32> Storage;
57409467b48Spatrick       return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
57509467b48Spatrick     }
57609467b48Spatrick 
57709467b48Spatrick     static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
57809467b48Spatrick       return LHS == RHS;
57909467b48Spatrick     }
58009467b48Spatrick 
58109467b48Spatrick     static unsigned getHashValue(const LookupKey &Val) {
58209467b48Spatrick       return hash_combine(Val.first, Val.second.getHash());
58309467b48Spatrick     }
58409467b48Spatrick 
58509467b48Spatrick     static unsigned getHashValue(const LookupKeyHashed &Val) {
58609467b48Spatrick       return Val.first;
58709467b48Spatrick     }
58809467b48Spatrick 
58909467b48Spatrick     static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
59009467b48Spatrick       if (RHS == getEmptyKey() || RHS == getTombstoneKey())
59109467b48Spatrick         return false;
59209467b48Spatrick       if (LHS.first != RHS->getType())
59309467b48Spatrick         return false;
59409467b48Spatrick       return LHS.second == RHS;
59509467b48Spatrick     }
59609467b48Spatrick 
59709467b48Spatrick     static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
59809467b48Spatrick       return isEqual(LHS.second, RHS);
59909467b48Spatrick     }
60009467b48Spatrick   };
60109467b48Spatrick 
60209467b48Spatrick public:
60309467b48Spatrick   using MapTy = DenseSet<ConstantClass *, MapInfo>;
60409467b48Spatrick 
60509467b48Spatrick private:
60609467b48Spatrick   MapTy Map;
60709467b48Spatrick 
60809467b48Spatrick public:
60909467b48Spatrick   typename MapTy::iterator begin() { return Map.begin(); }
61009467b48Spatrick   typename MapTy::iterator end() { return Map.end(); }
61109467b48Spatrick 
61209467b48Spatrick   void freeConstants() {
61309467b48Spatrick     for (auto &I : Map)
614097a140dSpatrick       deleteConstant(I);
61509467b48Spatrick   }
61609467b48Spatrick 
61709467b48Spatrick private:
61809467b48Spatrick   ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
61909467b48Spatrick     ConstantClass *Result = V.create(Ty);
62009467b48Spatrick 
62109467b48Spatrick     assert(Result->getType() == Ty && "Type specified is not correct!");
62209467b48Spatrick     Map.insert_as(Result, HashKey);
62309467b48Spatrick 
62409467b48Spatrick     return Result;
62509467b48Spatrick   }
62609467b48Spatrick 
62709467b48Spatrick public:
62809467b48Spatrick   /// Return the specified constant from the map, creating it if necessary.
62909467b48Spatrick   ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
63009467b48Spatrick     LookupKey Key(Ty, V);
63109467b48Spatrick     /// Hash once, and reuse it for the lookup and the insertion if needed.
63209467b48Spatrick     LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
63309467b48Spatrick 
63409467b48Spatrick     ConstantClass *Result = nullptr;
63509467b48Spatrick 
63609467b48Spatrick     auto I = Map.find_as(Lookup);
63709467b48Spatrick     if (I == Map.end())
63809467b48Spatrick       Result = create(Ty, V, Lookup);
63909467b48Spatrick     else
64009467b48Spatrick       Result = *I;
64109467b48Spatrick     assert(Result && "Unexpected nullptr");
64209467b48Spatrick 
64309467b48Spatrick     return Result;
64409467b48Spatrick   }
64509467b48Spatrick 
64609467b48Spatrick   /// Remove this constant from the map
64709467b48Spatrick   void remove(ConstantClass *CP) {
64809467b48Spatrick     typename MapTy::iterator I = Map.find(CP);
64909467b48Spatrick     assert(I != Map.end() && "Constant not found in constant table!");
65009467b48Spatrick     assert(*I == CP && "Didn't find correct element?");
65109467b48Spatrick     Map.erase(I);
65209467b48Spatrick   }
65309467b48Spatrick 
65409467b48Spatrick   ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
65509467b48Spatrick                                         ConstantClass *CP, Value *From,
65609467b48Spatrick                                         Constant *To, unsigned NumUpdated = 0,
65709467b48Spatrick                                         unsigned OperandNo = ~0u) {
65809467b48Spatrick     LookupKey Key(CP->getType(), ValType(Operands, CP));
65909467b48Spatrick     /// Hash once, and reuse it for the lookup and the insertion if needed.
66009467b48Spatrick     LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
66109467b48Spatrick 
66209467b48Spatrick     auto ItMap = Map.find_as(Lookup);
66309467b48Spatrick     if (ItMap != Map.end())
66409467b48Spatrick       return *ItMap;
66509467b48Spatrick 
66609467b48Spatrick     // Update to the new value.  Optimize for the case when we have a single
66709467b48Spatrick     // operand that we're changing, but handle bulk updates efficiently.
66809467b48Spatrick     remove(CP);
66909467b48Spatrick     if (NumUpdated == 1) {
67009467b48Spatrick       assert(OperandNo < CP->getNumOperands() && "Invalid index");
67109467b48Spatrick       assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
67209467b48Spatrick       CP->setOperand(OperandNo, To);
67309467b48Spatrick     } else {
67409467b48Spatrick       for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
67509467b48Spatrick         if (CP->getOperand(I) == From)
67609467b48Spatrick           CP->setOperand(I, To);
67709467b48Spatrick     }
67809467b48Spatrick     Map.insert_as(CP, Lookup);
67909467b48Spatrick     return nullptr;
68009467b48Spatrick   }
68109467b48Spatrick 
68209467b48Spatrick   void dump() const {
68309467b48Spatrick     LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
68409467b48Spatrick   }
68509467b48Spatrick };
68609467b48Spatrick 
687097a140dSpatrick template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {
688097a140dSpatrick   for (auto &I : Map)
689097a140dSpatrick     delete I;
690097a140dSpatrick }
691097a140dSpatrick 
69209467b48Spatrick } // end namespace llvm
69309467b48Spatrick 
69409467b48Spatrick #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H
695