123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785 |
- //===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines various helper methods and classes used by
- // LLVMContextImpl for creating and managing constants.
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
- #define LLVM_LIB_IR_CONSTANTSCONTEXT_H
- #include "llvm/ADT/ArrayRef.h"
- #include "llvm/ADT/DenseMapInfo.h"
- #include "llvm/ADT/DenseSet.h"
- #include "llvm/ADT/Hashing.h"
- #include "llvm/ADT/None.h"
- #include "llvm/ADT/SmallVector.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/IR/Constant.h"
- #include "llvm/IR/Constants.h"
- #include "llvm/IR/DerivedTypes.h"
- #include "llvm/IR/InlineAsm.h"
- #include "llvm/IR/Instruction.h"
- #include "llvm/IR/Instructions.h"
- #include "llvm/IR/OperandTraits.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/raw_ostream.h"
- #include <cassert>
- #include <cstddef>
- #include <cstdint>
- #include <utility>
- #define DEBUG_TYPE "ir"
- namespace llvm {
- /// UnaryConstantExpr - This class is private to Constants.cpp, and is used
- /// behind the scenes to implement unary constant exprs.
- class UnaryConstantExpr final : public ConstantExpr {
- public:
- UnaryConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
- : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
- Op<0>() = C;
- }
- // allocate space for exactly one operand
- void *operator new(size_t S) { return User::operator new(S, 1); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return Instruction::isCast(CE->getOpcode()) ||
- Instruction::isUnaryOp(CE->getOpcode());
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
- /// behind the scenes to implement binary constant exprs.
- class BinaryConstantExpr final : public ConstantExpr {
- public:
- BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags)
- : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
- Op<0>() = C1;
- Op<1>() = C2;
- SubclassOptionalData = Flags;
- }
- // allocate space for exactly two operands
- void *operator new(size_t S) { return User::operator new(S, 2); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return Instruction::isBinaryOp(CE->getOpcode());
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// SelectConstantExpr - This class is private to Constants.cpp, and is used
- /// behind the scenes to implement select constant exprs.
- class SelectConstantExpr final : public ConstantExpr {
- public:
- SelectConstantExpr(Constant *C1, Constant *C2, Constant *C3)
- : ConstantExpr(C2->getType(), Instruction::Select, &Op<0>(), 3) {
- Op<0>() = C1;
- Op<1>() = C2;
- Op<2>() = C3;
- }
- // allocate space for exactly three operands
- void *operator new(size_t S) { return User::operator new(S, 3); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::Select;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// ExtractElementConstantExpr - This class is private to
- /// Constants.cpp, and is used behind the scenes to implement
- /// extractelement constant exprs.
- class ExtractElementConstantExpr final : public ConstantExpr {
- public:
- ExtractElementConstantExpr(Constant *C1, Constant *C2)
- : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
- Instruction::ExtractElement, &Op<0>(), 2) {
- Op<0>() = C1;
- Op<1>() = C2;
- }
- // allocate space for exactly two operands
- void *operator new(size_t S) { return User::operator new(S, 2); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::ExtractElement;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// InsertElementConstantExpr - This class is private to
- /// Constants.cpp, and is used behind the scenes to implement
- /// insertelement constant exprs.
- class InsertElementConstantExpr final : public ConstantExpr {
- public:
- InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
- : ConstantExpr(C1->getType(), Instruction::InsertElement,
- &Op<0>(), 3) {
- Op<0>() = C1;
- Op<1>() = C2;
- Op<2>() = C3;
- }
- // allocate space for exactly three operands
- void *operator new(size_t S) { return User::operator new(S, 3); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::InsertElement;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// ShuffleVectorConstantExpr - This class is private to
- /// Constants.cpp, and is used behind the scenes to implement
- /// shufflevector constant exprs.
- class ShuffleVectorConstantExpr final : public ConstantExpr {
- public:
- ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)
- : ConstantExpr(VectorType::get(
- cast<VectorType>(C1->getType())->getElementType(),
- Mask.size(), isa<ScalableVectorType>(C1->getType())),
- Instruction::ShuffleVector, &Op<0>(), 2) {
- assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&
- "Invalid shuffle vector instruction operands!");
- Op<0>() = C1;
- Op<1>() = C2;
- ShuffleMask.assign(Mask.begin(), Mask.end());
- ShuffleMaskForBitcode =
- ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType());
- }
- SmallVector<int, 4> ShuffleMask;
- Constant *ShuffleMaskForBitcode;
- void *operator new(size_t S) { return User::operator new(S, 2); }
- void operator delete(void *Ptr) { return User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::ShuffleVector;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// ExtractValueConstantExpr - This class is private to
- /// Constants.cpp, and is used behind the scenes to implement
- /// extractvalue constant exprs.
- class ExtractValueConstantExpr final : public ConstantExpr {
- public:
- ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList,
- Type *DestTy)
- : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
- Indices(IdxList.begin(), IdxList.end()) {
- Op<0>() = Agg;
- }
- // allocate space for exactly one operand
- void *operator new(size_t S) { return User::operator new(S, 1); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Indices - These identify which value to extract.
- const SmallVector<unsigned, 4> Indices;
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::ExtractValue;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// InsertValueConstantExpr - This class is private to
- /// Constants.cpp, and is used behind the scenes to implement
- /// insertvalue constant exprs.
- class InsertValueConstantExpr final : public ConstantExpr {
- public:
- InsertValueConstantExpr(Constant *Agg, Constant *Val,
- ArrayRef<unsigned> IdxList, Type *DestTy)
- : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
- Indices(IdxList.begin(), IdxList.end()) {
- Op<0>() = Agg;
- Op<1>() = Val;
- }
- // allocate space for exactly one operand
- void *operator new(size_t S) { return User::operator new(S, 2); }
- void operator delete(void *Ptr) { User::operator delete(Ptr); }
- /// Indices - These identify the position for the insertion.
- const SmallVector<unsigned, 4> Indices;
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::InsertValue;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
- /// used behind the scenes to implement getelementpr constant exprs.
- class GetElementPtrConstantExpr final : public ConstantExpr {
- Type *SrcElementTy;
- Type *ResElementTy;
- GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
- ArrayRef<Constant *> IdxList, Type *DestTy);
- public:
- static GetElementPtrConstantExpr *Create(Type *SrcElementTy, Constant *C,
- ArrayRef<Constant *> IdxList,
- Type *DestTy, unsigned Flags) {
- GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)
- GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy);
- Result->SubclassOptionalData = Flags;
- return Result;
- }
- Type *getSourceElementType() const;
- Type *getResultElementType() const;
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::GetElementPtr;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- // CompareConstantExpr - This class is private to Constants.cpp, and is used
- // behind the scenes to implement ICmp and FCmp constant expressions. This is
- // needed in order to store the predicate value for these instructions.
- class CompareConstantExpr final : public ConstantExpr {
- public:
- unsigned short predicate;
- CompareConstantExpr(Type *ty, Instruction::OtherOps opc,
- unsigned short pred, Constant* LHS, Constant* RHS)
- : ConstantExpr(ty, opc, &Op<0>(), 2), predicate(pred) {
- Op<0>() = LHS;
- Op<1>() = RHS;
- }
- // allocate space for exactly two operands
- void *operator new(size_t S) { return User::operator new(S, 2); }
- void operator delete(void *Ptr) { return User::operator delete(Ptr); }
- /// Transparently provide more efficient getOperand methods.
- DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
- static bool classof(const ConstantExpr *CE) {
- return CE->getOpcode() == Instruction::ICmp ||
- CE->getOpcode() == Instruction::FCmp;
- }
- static bool classof(const Value *V) {
- return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
- }
- };
- template <>
- struct OperandTraits<UnaryConstantExpr>
- : public FixedNumOperandTraits<UnaryConstantExpr, 1> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(UnaryConstantExpr, Value)
- template <>
- struct OperandTraits<BinaryConstantExpr>
- : public FixedNumOperandTraits<BinaryConstantExpr, 2> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
- template <>
- struct OperandTraits<SelectConstantExpr>
- : public FixedNumOperandTraits<SelectConstantExpr, 3> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(SelectConstantExpr, Value)
- template <>
- struct OperandTraits<ExtractElementConstantExpr>
- : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
- template <>
- struct OperandTraits<InsertElementConstantExpr>
- : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
- template <>
- struct OperandTraits<ShuffleVectorConstantExpr>
- : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
- template <>
- struct OperandTraits<ExtractValueConstantExpr>
- : public FixedNumOperandTraits<ExtractValueConstantExpr, 1> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractValueConstantExpr, Value)
- template <>
- struct OperandTraits<InsertValueConstantExpr>
- : public FixedNumOperandTraits<InsertValueConstantExpr, 2> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertValueConstantExpr, Value)
- template <>
- struct OperandTraits<GetElementPtrConstantExpr>
- : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
- template <>
- struct OperandTraits<CompareConstantExpr>
- : public FixedNumOperandTraits<CompareConstantExpr, 2> {};
- DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
- template <class ConstantClass> struct ConstantAggrKeyType;
- struct InlineAsmKeyType;
- struct ConstantExprKeyType;
- template <class ConstantClass> struct ConstantInfo;
- template <> struct ConstantInfo<ConstantExpr> {
- using ValType = ConstantExprKeyType;
- using TypeClass = Type;
- };
- template <> struct ConstantInfo<InlineAsm> {
- using ValType = InlineAsmKeyType;
- using TypeClass = PointerType;
- };
- template <> struct ConstantInfo<ConstantArray> {
- using ValType = ConstantAggrKeyType<ConstantArray>;
- using TypeClass = ArrayType;
- };
- template <> struct ConstantInfo<ConstantStruct> {
- using ValType = ConstantAggrKeyType<ConstantStruct>;
- using TypeClass = StructType;
- };
- template <> struct ConstantInfo<ConstantVector> {
- using ValType = ConstantAggrKeyType<ConstantVector>;
- using TypeClass = VectorType;
- };
- template <class ConstantClass> struct ConstantAggrKeyType {
- ArrayRef<Constant *> Operands;
- ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
- ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
- : Operands(Operands) {}
- ConstantAggrKeyType(const ConstantClass *C,
- SmallVectorImpl<Constant *> &Storage) {
- assert(Storage.empty() && "Expected empty storage");
- for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
- Storage.push_back(C->getOperand(I));
- Operands = Storage;
- }
- bool operator==(const ConstantAggrKeyType &X) const {
- return Operands == X.Operands;
- }
- bool operator==(const ConstantClass *C) const {
- if (Operands.size() != C->getNumOperands())
- return false;
- for (unsigned I = 0, E = Operands.size(); I != E; ++I)
- if (Operands[I] != C->getOperand(I))
- return false;
- return true;
- }
- unsigned getHash() const {
- return hash_combine_range(Operands.begin(), Operands.end());
- }
- using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
- ConstantClass *create(TypeClass *Ty) const {
- return new (Operands.size()) ConstantClass(Ty, Operands);
- }
- };
- struct InlineAsmKeyType {
- StringRef AsmString;
- StringRef Constraints;
- FunctionType *FTy;
- bool HasSideEffects;
- bool IsAlignStack;
- InlineAsm::AsmDialect AsmDialect;
- bool CanThrow;
- InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
- FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,
- InlineAsm::AsmDialect AsmDialect, bool canThrow)
- : AsmString(AsmString), Constraints(Constraints), FTy(FTy),
- HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
- AsmDialect(AsmDialect), CanThrow(canThrow) {}
- InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
- : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
- FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),
- IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),
- CanThrow(Asm->canThrow()) {}
- bool operator==(const InlineAsmKeyType &X) const {
- return HasSideEffects == X.HasSideEffects &&
- IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
- AsmString == X.AsmString && Constraints == X.Constraints &&
- FTy == X.FTy && CanThrow == X.CanThrow;
- }
- bool operator==(const InlineAsm *Asm) const {
- return HasSideEffects == Asm->hasSideEffects() &&
- IsAlignStack == Asm->isAlignStack() &&
- AsmDialect == Asm->getDialect() &&
- AsmString == Asm->getAsmString() &&
- Constraints == Asm->getConstraintString() &&
- FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();
- }
- unsigned getHash() const {
- return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
- AsmDialect, FTy, CanThrow);
- }
- using TypeClass = ConstantInfo<InlineAsm>::TypeClass;
- InlineAsm *create(TypeClass *Ty) const {
- assert(PointerType::getUnqual(FTy) == Ty);
- return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),
- HasSideEffects, IsAlignStack, AsmDialect, CanThrow);
- }
- };
- struct ConstantExprKeyType {
- private:
- uint8_t Opcode;
- uint8_t SubclassOptionalData;
- uint16_t SubclassData;
- ArrayRef<Constant *> Ops;
- ArrayRef<unsigned> Indexes;
- ArrayRef<int> ShuffleMask;
- Type *ExplicitTy;
- static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
- if (CE->getOpcode() == Instruction::ShuffleVector)
- return CE->getShuffleMask();
- return None;
- }
- static ArrayRef<unsigned> getIndicesIfValid(const ConstantExpr *CE) {
- if (CE->hasIndices())
- return CE->getIndices();
- return None;
- }
- static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {
- if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
- return GEPCE->getSourceElementType();
- return nullptr;
- }
- public:
- ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
- unsigned short SubclassData = 0,
- unsigned short SubclassOptionalData = 0,
- ArrayRef<unsigned> Indexes = None,
- ArrayRef<int> ShuffleMask = None,
- Type *ExplicitTy = nullptr)
- : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
- SubclassData(SubclassData), Ops(Ops), Indexes(Indexes),
- ShuffleMask(ShuffleMask), ExplicitTy(ExplicitTy) {}
- ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
- : Opcode(CE->getOpcode()),
- SubclassOptionalData(CE->getRawSubclassOptionalData()),
- SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands),
- Indexes(getIndicesIfValid(CE)), ShuffleMask(getShuffleMaskIfValid(CE)),
- ExplicitTy(getSourceElementTypeIfValid(CE)) {}
- ConstantExprKeyType(const ConstantExpr *CE,
- SmallVectorImpl<Constant *> &Storage)
- : Opcode(CE->getOpcode()),
- SubclassOptionalData(CE->getRawSubclassOptionalData()),
- SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
- Indexes(getIndicesIfValid(CE)), ShuffleMask(getShuffleMaskIfValid(CE)),
- ExplicitTy(getSourceElementTypeIfValid(CE)) {
- assert(Storage.empty() && "Expected empty storage");
- for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
- Storage.push_back(CE->getOperand(I));
- Ops = Storage;
- }
- bool operator==(const ConstantExprKeyType &X) const {
- return Opcode == X.Opcode && SubclassData == X.SubclassData &&
- SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
- Indexes == X.Indexes && ShuffleMask == X.ShuffleMask &&
- ExplicitTy == X.ExplicitTy;
- }
- bool operator==(const ConstantExpr *CE) const {
- if (Opcode != CE->getOpcode())
- return false;
- if (SubclassOptionalData != CE->getRawSubclassOptionalData())
- return false;
- if (Ops.size() != CE->getNumOperands())
- return false;
- if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
- return false;
- for (unsigned I = 0, E = Ops.size(); I != E; ++I)
- if (Ops[I] != CE->getOperand(I))
- return false;
- if (Indexes != getIndicesIfValid(CE))
- return false;
- if (ShuffleMask != getShuffleMaskIfValid(CE))
- return false;
- if (ExplicitTy != getSourceElementTypeIfValid(CE))
- return false;
- return true;
- }
- unsigned getHash() const {
- return hash_combine(
- Opcode, SubclassOptionalData, SubclassData,
- hash_combine_range(Ops.begin(), Ops.end()),
- hash_combine_range(Indexes.begin(), Indexes.end()),
- hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy);
- }
- using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;
- ConstantExpr *create(TypeClass *Ty) const {
- switch (Opcode) {
- default:
- if (Instruction::isCast(Opcode) ||
- (Opcode >= Instruction::UnaryOpsBegin &&
- Opcode < Instruction::UnaryOpsEnd))
- return new UnaryConstantExpr(Opcode, Ops[0], Ty);
- if ((Opcode >= Instruction::BinaryOpsBegin &&
- Opcode < Instruction::BinaryOpsEnd))
- return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
- SubclassOptionalData);
- llvm_unreachable("Invalid ConstantExpr!");
- case Instruction::Select:
- return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]);
- case Instruction::ExtractElement:
- return new ExtractElementConstantExpr(Ops[0], Ops[1]);
- case Instruction::InsertElement:
- return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
- case Instruction::ShuffleVector:
- return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
- case Instruction::InsertValue:
- return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty);
- case Instruction::ExtractValue:
- return new ExtractValueConstantExpr(Ops[0], Indexes, Ty);
- case Instruction::GetElementPtr:
- return GetElementPtrConstantExpr::Create(ExplicitTy, Ops[0], Ops.slice(1),
- Ty, SubclassOptionalData);
- case Instruction::ICmp:
- return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
- Ops[0], Ops[1]);
- case Instruction::FCmp:
- return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
- Ops[0], Ops[1]);
- }
- }
- };
- // Free memory for a given constant. Assumes the constant has already been
- // removed from all relevant maps.
- void deleteConstant(Constant *C);
- template <class ConstantClass> class ConstantUniqueMap {
- public:
- using ValType = typename ConstantInfo<ConstantClass>::ValType;
- using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
- using LookupKey = std::pair<TypeClass *, ValType>;
- /// Key and hash together, so that we compute the hash only once and reuse it.
- using LookupKeyHashed = std::pair<unsigned, LookupKey>;
- private:
- struct MapInfo {
- using ConstantClassInfo = DenseMapInfo<ConstantClass *>;
- static inline ConstantClass *getEmptyKey() {
- return ConstantClassInfo::getEmptyKey();
- }
- static inline ConstantClass *getTombstoneKey() {
- return ConstantClassInfo::getTombstoneKey();
- }
- static unsigned getHashValue(const ConstantClass *CP) {
- SmallVector<Constant *, 32> Storage;
- return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
- }
- static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
- return LHS == RHS;
- }
- static unsigned getHashValue(const LookupKey &Val) {
- return hash_combine(Val.first, Val.second.getHash());
- }
- static unsigned getHashValue(const LookupKeyHashed &Val) {
- return Val.first;
- }
- static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
- if (RHS == getEmptyKey() || RHS == getTombstoneKey())
- return false;
- if (LHS.first != RHS->getType())
- return false;
- return LHS.second == RHS;
- }
- static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
- return isEqual(LHS.second, RHS);
- }
- };
- public:
- using MapTy = DenseSet<ConstantClass *, MapInfo>;
- private:
- MapTy Map;
- public:
- typename MapTy::iterator begin() { return Map.begin(); }
- typename MapTy::iterator end() { return Map.end(); }
- void freeConstants() {
- for (auto &I : Map)
- deleteConstant(I);
- }
- private:
- ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
- ConstantClass *Result = V.create(Ty);
- assert(Result->getType() == Ty && "Type specified is not correct!");
- Map.insert_as(Result, HashKey);
- return Result;
- }
- public:
- /// Return the specified constant from the map, creating it if necessary.
- ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
- LookupKey Key(Ty, V);
- /// Hash once, and reuse it for the lookup and the insertion if needed.
- LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
- ConstantClass *Result = nullptr;
- auto I = Map.find_as(Lookup);
- if (I == Map.end())
- Result = create(Ty, V, Lookup);
- else
- Result = *I;
- assert(Result && "Unexpected nullptr");
- return Result;
- }
- /// Remove this constant from the map
- void remove(ConstantClass *CP) {
- typename MapTy::iterator I = Map.find(CP);
- assert(I != Map.end() && "Constant not found in constant table!");
- assert(*I == CP && "Didn't find correct element?");
- Map.erase(I);
- }
- ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
- ConstantClass *CP, Value *From,
- Constant *To, unsigned NumUpdated = 0,
- unsigned OperandNo = ~0u) {
- LookupKey Key(CP->getType(), ValType(Operands, CP));
- /// Hash once, and reuse it for the lookup and the insertion if needed.
- LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
- auto ItMap = Map.find_as(Lookup);
- if (ItMap != Map.end())
- return *ItMap;
- // Update to the new value. Optimize for the case when we have a single
- // operand that we're changing, but handle bulk updates efficiently.
- remove(CP);
- if (NumUpdated == 1) {
- assert(OperandNo < CP->getNumOperands() && "Invalid index");
- assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
- CP->setOperand(OperandNo, To);
- } else {
- for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
- if (CP->getOperand(I) == From)
- CP->setOperand(I, To);
- }
- Map.insert_as(CP, Lookup);
- return nullptr;
- }
- void dump() const {
- LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
- }
- };
- template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {
- for (auto &I : Map)
- delete I;
- }
- } // end namespace llvm
- #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H
|