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