diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/IR/Constants.cpp | 289 | ||||
-rw-r--r-- | llvm/lib/IR/ConstantsContext.h | 564 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/IR/LLVMContextImpl.h | 14 |
4 files changed, 482 insertions, 387 deletions
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index cb7c9e63059..45a71dc6230 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -803,11 +803,6 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) { - if (Constant *C = getImpl(Ty, V)) - return C; - return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V); -} -Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) { // Empty arrays are canonicalized to ConstantAggregateZero. if (V.empty()) return ConstantAggregateZero::get(Ty); @@ -816,6 +811,7 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) { assert(V[i]->getType() == Ty->getElementType() && "Wrong type in array element initializer"); } + LLVMContextImpl *pImpl = Ty->getContext().pImpl; // If this is an all-zero array, return a ConstantAggregateZero object. If // all undef, return an UndefValue, if "all simple", then return a @@ -897,7 +893,7 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) { } // Otherwise, we really do want to create a ConstantArray. - return nullptr; + return pImpl->ArrayConstants.getOrCreate(Ty, V); } /// getTypeForElements - Return an anonymous struct type to use for a constant @@ -985,14 +981,9 @@ ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V) // ConstantVector accessors. Constant *ConstantVector::get(ArrayRef<Constant*> V) { - if (Constant *C = getImpl(V)) - return C; - VectorType *Ty = VectorType::get(V.front()->getType(), V.size()); - return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V); -} -Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) { assert(!V.empty() && "Vectors can't be empty"); VectorType *T = VectorType::get(V.front()->getType(), V.size()); + LLVMContextImpl *pImpl = T->getContext().pImpl; // If this is an all-undef or all-zero vector, return a // ConstantAggregateZero or UndefValue. @@ -1084,7 +1075,7 @@ Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) { // Otherwise, the element type isn't compatible with ConstantDataVector, or // the operand list constants a ConstantExpr or something else strange. - return nullptr; + return pImpl->VectorConstants.getOrCreate(T, V); } Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) { @@ -1478,21 +1469,27 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { // and return early. BlockAddress *&NewBA = getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)]; - if (NewBA) { - replaceUsesOfWithOnConstantImpl(NewBA); + if (!NewBA) { + getBasicBlock()->AdjustBlockAddressRefCount(-1); + + // Remove the old entry, this can't cause the map to rehash (just a + // tombstone will get added). + getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), + getBasicBlock())); + NewBA = this; + setOperand(0, NewF); + setOperand(1, NewBB); + getBasicBlock()->AdjustBlockAddressRefCount(1); return; } - getBasicBlock()->AdjustBlockAddressRefCount(-1); + // Otherwise, I do need to replace this with an existing value. + assert(NewBA != this && "I didn't contain From!"); - // Remove the old entry, this can't cause the map to rehash (just a - // tombstone will get added). - getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(), - getBasicBlock())); - NewBA = this; - setOperand(0, NewF); - setOperand(1, NewBB); - getBasicBlock()->AdjustBlockAddressRefCount(1); + // Everyone using this now uses the replacement. + replaceAllUsesWith(NewBA); + + destroyConstant(); } //---- ConstantExpr::get() implementations. @@ -1510,7 +1507,7 @@ static inline Constant *getFoldedCast( LLVMContextImpl *pImpl = Ty->getContext().pImpl; // Look up the constant in the table first to ensure uniqueness. - ConstantExprKeyType Key(opc, C); + ExprMapKeyType Key(opc, C); return pImpl->ExprConstants.getOrCreate(Ty, Key); } @@ -1845,7 +1842,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, return FC; // Fold a few common cases. Constant *ArgVec[] = { C1, C2 }; - ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags); + ExprMapKeyType Key(Opcode, ArgVec, 0, Flags); LLVMContextImpl *pImpl = C1->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(C1->getType(), Key); @@ -1922,7 +1919,7 @@ Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) { return SC; // Fold common cases Constant *ArgVec[] = { C, V1, V2 }; - ConstantExprKeyType Key(Instruction::Select, ArgVec); + ExprMapKeyType Key(Instruction::Select, ArgVec); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(V1->getType(), Key); @@ -1957,8 +1954,8 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs, "getelementptr index type missmatch"); ArgVec.push_back(cast<Constant>(Idxs[i])); } - const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - InBounds ? GEPOperator::IsInBounds : 0); + const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, + InBounds ? GEPOperator::IsInBounds : 0); LLVMContextImpl *pImpl = C->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -1976,7 +1973,7 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) { // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred); + const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast<VectorType>(LHS->getType())) @@ -1997,7 +1994,7 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) { // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { LHS, RHS }; // Get the key type with both the opcode and predicate - const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred); + const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred); Type *ResultTy = Type::getInt1Ty(LHS->getContext()); if (VectorType *VT = dyn_cast<VectorType>(LHS->getType())) @@ -2018,7 +2015,7 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) { // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Idx }; - const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec); + const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; Type *ReqTy = Val->getType()->getVectorElementType(); @@ -2038,7 +2035,7 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt, return FC; // Fold a few common cases. // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { Val, Elt, Idx }; - const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec); + const ExprMapKeyType Key(Instruction::InsertElement, ArgVec); LLVMContextImpl *pImpl = Val->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(Val->getType(), Key); @@ -2058,7 +2055,7 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2, // Look up the constant in the table first to ensure uniqueness Constant *ArgVec[] = { V1, V2, Mask }; - const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec); + const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec); LLVMContextImpl *pImpl = ShufTy->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ShufTy, Key); @@ -2078,7 +2075,7 @@ Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val, return FC; Constant *ArgVec[] = { Agg, Val }; - const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); + const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2099,7 +2096,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, return FC; Constant *ArgVec[] = { Agg }; - const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); + const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs); LLVMContextImpl *pImpl = Agg->getContext().pImpl; return pImpl->ExprConstants.getOrCreate(ReqTy, Key); @@ -2655,17 +2652,6 @@ Constant *ConstantDataVector::getSplatValue() const { /// work, but would be really slow because it would have to unique each updated /// array instance. /// -void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) { - // I do need to replace this with an existing value. - assert(Replacement != this && "I didn't contain From!"); - - // Everyone using this now uses the replacement. - replaceAllUsesWith(Replacement); - - // Delete the old constant! - destroyConstant(); -} - void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); @@ -2692,51 +2678,52 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, AllSame &= Val == ToC; } + Constant *Replacement = nullptr; if (AllSame && ToC->isNullValue()) { - replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); - return; - } - if (AllSame && isa<UndefValue>(ToC)) { - replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); - return; - } - - // Check for any other type of constant-folding. - if (Constant *C = getImpl(getType(), Values)) { - replaceUsesOfWithOnConstantImpl(C); - return; + Replacement = ConstantAggregateZero::get(getType()); + } else if (AllSame && isa<UndefValue>(ToC)) { + Replacement = UndefValue::get(getType()); + } else { + // Check to see if we have this array type already. + LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup( + cast<ArrayType>(getType()), makeArrayRef(Values)); + LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I = + pImpl->ArrayConstants.find(Lookup); + + if (I != pImpl->ArrayConstants.map_end()) { + Replacement = I->first; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant array, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + pImpl->ArrayConstants.remove(this); + + // Update to the new value. Optimize for the case when we have a single + // operand that we're changing, but handle bulk updates efficiently. + if (NumUpdated == 1) { + unsigned OperandToUpdate = U - OperandList; + assert(getOperand(OperandToUpdate) == From && + "ReplaceAllUsesWith broken!"); + setOperand(OperandToUpdate, ToC); + } else { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (getOperand(i) == From) + setOperand(i, ToC); + } + pImpl->ArrayConstants.insert(this); + return; + } } - // Check to see if we have this array type already. - LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup( - cast<ArrayType>(getType()), makeArrayRef(Values)); - LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I = - pImpl->ArrayConstants.find(Lookup); + // Otherwise, I do need to replace this with an existing value. + assert(Replacement != this && "I didn't contain From!"); - if (I != pImpl->ArrayConstants.map_end()) { - replaceUsesOfWithOnConstantImpl(I->first); - return; - } + // Everyone using this now uses the replacement. + replaceAllUsesWith(Replacement); - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant array, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->ArrayConstants.remove(this); - - // Update to the new value. Optimize for the case when we have a single - // operand that we're changing, but handle bulk updates efficiently. - if (NumUpdated == 1) { - unsigned OperandToUpdate = U - OperandList; - assert(getOperand(OperandToUpdate) == From && - "ReplaceAllUsesWith broken!"); - setOperand(OperandToUpdate, ToC); - } else { - for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - if (getOperand(I) == From) - setOperand(I, ToC); - } - pImpl->ArrayConstants.insert(this); + // Delete the old constant! + destroyConstant(); } void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, @@ -2776,75 +2763,63 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, LLVMContextImpl *pImpl = getContext().pImpl; + Constant *Replacement = nullptr; if (isAllZeros) { - replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType())); - return; - } - if (isAllUndef) { - replaceUsesOfWithOnConstantImpl(UndefValue::get(getType())); - return; - } - - // Check to see if we have this struct type already. - LLVMContextImpl::StructConstantsTy::LookupKey Lookup( - cast<StructType>(getType()), makeArrayRef(Values)); - LLVMContextImpl::StructConstantsTy::MapTy::iterator I = + Replacement = ConstantAggregateZero::get(getType()); + } else if (isAllUndef) { + Replacement = UndefValue::get(getType()); + } else { + // Check to see if we have this struct type already. + LLVMContextImpl::StructConstantsTy::LookupKey Lookup( + cast<StructType>(getType()), makeArrayRef(Values)); + LLVMContextImpl::StructConstantsTy::MapTy::iterator I = pImpl->StructConstants.find(Lookup); - if (I != pImpl->StructConstants.map_end()) { - replaceUsesOfWithOnConstantImpl(I->first); - return; + if (I != pImpl->StructConstants.map_end()) { + Replacement = I->first; + } else { + // Okay, the new shape doesn't exist in the system yet. Instead of + // creating a new constant struct, inserting it, replaceallusesof'ing the + // old with the new, then deleting the old... just update the current one + // in place! + pImpl->StructConstants.remove(this); + + // Update to the new value. + setOperand(OperandToUpdate, ToC); + pImpl->StructConstants.insert(this); + return; + } } - // Okay, the new shape doesn't exist in the system yet. Instead of - // creating a new constant struct, inserting it, replaceallusesof'ing the - // old with the new, then deleting the old... just update the current one - // in place! - pImpl->StructConstants.remove(this); + assert(Replacement != this && "I didn't contain From!"); - // Update to the new value. - setOperand(OperandToUpdate, ToC); - pImpl->StructConstants.insert(this); + // Everyone using this now uses the replacement. + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); } void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!"); - Constant *ToC = cast<Constant>(To); SmallVector<Constant*, 8> Values; Values.reserve(getNumOperands()); // Build replacement array... - unsigned NumUpdated = 0; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { Constant *Val = getOperand(i); - if (Val == From) { - ++NumUpdated; - Val = ToC; - } + if (Val == From) Val = cast<Constant>(To); Values.push_back(Val); } - if (Constant *C = getImpl(Values)) { - replaceUsesOfWithOnConstantImpl(C); - return; - } - - // Update to the new value. Optimize for the case when we have a single - // operand that we're changing, but handle bulk updates efficiently. - auto &pImpl = getType()->getContext().pImpl; - pImpl->VectorConstants.remove(this); + Constant *Replacement = get(Values); + assert(Replacement != this && "I didn't contain From!"); - if (NumUpdated == 1) { - unsigned OperandToUpdate = U - OperandList; - assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); - setOperand(OperandToUpdate, ToC); - } else { - for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - if (getOperand(I) == From) - setOperand(I, ToC); - } + // Everyone using this now uses the replacement. + replaceAllUsesWith(Replacement); - pImpl->VectorConstants.insert(this); + // Delete the old constant! + destroyConstant(); } void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, @@ -2861,25 +2836,6 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *Replacement = getWithOperands(NewOps); assert(Replacement != this && "I didn't contain From!"); - // Check if Replacement has no users (and is the same type). Ideally, this - // check would be done *before* creating Replacement, but threading this - // through constant-folding isn't trivial. - if (canBecomeReplacement(Replacement)) { - // Avoid unnecessary RAUW traffic. - auto &ExprConstants = getType()->getContext().pImpl->ExprConstants; - ExprConstants.remove(this); - - auto *CE = cast<ConstantExpr>(Replacement); - for (unsigned I = 0, E = getNumOperands(); I != E; ++I) - // Only set the operands that have actually changed. - if (getOperand(I) != CE->getOperand(I)) - setOperand(I, CE->getOperand(I)); - - CE->destroyConstant(); - ExprConstants.insert(this); - return; - } - // Everyone using this now uses the replacement. replaceAllUsesWith(Replacement); @@ -2887,31 +2843,6 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, destroyConstant(); } -bool ConstantExpr::canBecomeReplacement(const Constant *Replacement) const { - // If Replacement already has users, use it regardless. - if (!Replacement->use_empty()) - return false; - - // Check for anything that could have changed during constant-folding. - if (getValueID() != Replacement->getValueID()) - return false; - const auto *CE = cast<ConstantExpr>(Replacement); - if (getOpcode() != CE->getOpcode()) - return false; - if (getNumOperands() != CE->getNumOperands()) - return false; - if (getRawSubclassOptionalData() != CE->getRawSubclassOptionalData()) - return false; - if (isCompare()) - if (getPredicate() != CE->getPredicate()) - return false; - if (hasIndices()) - if (getIndices() != CE->getIndices()) - return false; - - return true; -} - Instruction *ConstantExpr::getAsInstruction() { SmallVector<Value*,4> ValueOperands; for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) diff --git a/llvm/lib/IR/ConstantsContext.h b/llvm/lib/IR/ConstantsContext.h index 092de718776..c3aefb9ce2d 100644 --- a/llvm/lib/IR/ConstantsContext.h +++ b/llvm/lib/IR/ConstantsContext.h @@ -29,6 +29,8 @@ #define DEBUG_TYPE "ir" namespace llvm { +template<class ValType> +struct ConstantTraits; /// UnaryConstantExpr - This class is private to Constants.cpp, and is used /// behind the scenes to implement unary constant exprs. @@ -312,234 +314,379 @@ struct OperandTraits<CompareConstantExpr> : }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) -template <class ConstantClass> struct ConstantAggrKeyType; -struct InlineAsmKeyType; -struct ConstantExprKeyType; +struct ExprMapKeyType { + ExprMapKeyType(unsigned opc, + ArrayRef<Constant*> ops, + unsigned short flags = 0, + unsigned short optionalflags = 0, + ArrayRef<unsigned> inds = None) + : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), + operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {} + uint8_t opcode; + uint8_t subclassoptionaldata; + uint16_t subclassdata; + std::vector<Constant*> operands; + SmallVector<unsigned, 4> indices; + bool operator==(const ExprMapKeyType& that) const { + return this->opcode == that.opcode && + this->subclassdata == that.subclassdata && + this->subclassoptionaldata == that.subclassoptionaldata && + this->operands == that.operands && + this->indices == that.indices; + } + bool operator<(const ExprMapKeyType & that) const { + return std::tie(opcode, operands, subclassdata, subclassoptionaldata, + indices) < + std::tie(that.opcode, that.operands, that.subclassdata, + that.subclassoptionaldata, that.indices); + } + + bool operator!=(const ExprMapKeyType& that) const { + return !(*this == that); + } +}; -template <class ConstantClass> struct ConstantInfo; -template <> struct ConstantInfo<ConstantExpr> { - typedef ConstantExprKeyType ValType; - typedef Type TypeClass; +struct InlineAsmKeyType { + InlineAsmKeyType(StringRef AsmString, + StringRef Constraints, bool hasSideEffects, + bool isAlignStack, InlineAsm::AsmDialect asmDialect) + : asm_string(AsmString), constraints(Constraints), + has_side_effects(hasSideEffects), is_align_stack(isAlignStack), + asm_dialect(asmDialect) {} + std::string asm_string; + std::string constraints; + bool has_side_effects; + bool is_align_stack; + InlineAsm::AsmDialect asm_dialect; + bool operator==(const InlineAsmKeyType& that) const { + return this->asm_string == that.asm_string && + this->constraints == that.constraints && + this->has_side_effects == that.has_side_effects && + this->is_align_stack == that.is_align_stack && + this->asm_dialect == that.asm_dialect; + } + bool operator<(const InlineAsmKeyType& that) const { + return std::tie(asm_string, constraints, has_side_effects, is_align_stack, + asm_dialect) < + std::tie(that.asm_string, that.constraints, that.has_side_effects, + that.is_align_stack, that.asm_dialect); + } + + bool operator!=(const InlineAsmKeyType& that) const { + return !(*this == that); + } }; -template <> struct ConstantInfo<InlineAsm> { - typedef InlineAsmKeyType ValType; - typedef PointerType TypeClass; + +// The number of operands for each ConstantCreator::create method is +// determined by the ConstantTraits template. +// ConstantCreator - A class that is used to create constants by +// ConstantUniqueMap*. This class should be partially specialized if there is +// something strange that needs to be done to interface to the ctor for the +// constant. +// +template<typename T, typename Alloc> +struct ConstantTraits< std::vector<T, Alloc> > { + static unsigned uses(const std::vector<T, Alloc>& v) { + return v.size(); + } }; -template <> struct ConstantInfo<ConstantArray> { - typedef ConstantAggrKeyType<ConstantArray> ValType; - typedef ArrayType TypeClass; + +template<> +struct ConstantTraits<Constant *> { + static unsigned uses(Constant * const & v) { + return 1; + } }; -template <> struct ConstantInfo<ConstantStruct> { - typedef ConstantAggrKeyType<ConstantStruct> ValType; - typedef StructType TypeClass; + +template<class ConstantClass, class TypeClass, class ValType> +struct ConstantCreator { + static ConstantClass *create(TypeClass *Ty, const ValType &V) { + return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V); + } }; -template <> struct ConstantInfo<ConstantVector> { - typedef ConstantAggrKeyType<ConstantVector> ValType; - typedef VectorType TypeClass; + +template<class ConstantClass, class TypeClass> +struct ConstantArrayCreator { + static ConstantClass *create(TypeClass *Ty, ArrayRef<Constant*> V) { + return new(V.size()) ConstantClass(Ty, V); + } }; -template <class ConstantClass> struct ConstantAggrKeyType { - ArrayRef<Constant *> Operands; - ConstantAggrKeyType(ArrayRef<Constant *> Operands) : 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; +template<class ConstantClass> +struct ConstantKeyData { + typedef void ValType; + static ValType getValType(ConstantClass *C) { + llvm_unreachable("Unknown Constant type!"); } +}; - bool operator==(const ConstantAggrKeyType &X) const { - return Operands == X.Operands; +template<> +struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> { + static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V, + unsigned short pred = 0) { + if (Instruction::isCast(V.opcode)) + return new UnaryConstantExpr(V.opcode, V.operands[0], Ty); + if ((V.opcode >= Instruction::BinaryOpsBegin && + V.opcode < Instruction::BinaryOpsEnd)) + return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1], + V.subclassoptionaldata); + if (V.opcode == Instruction::Select) + return new SelectConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::ExtractElement) + return new ExtractElementConstantExpr(V.operands[0], V.operands[1]); + if (V.opcode == Instruction::InsertElement) + return new InsertElementConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::ShuffleVector) + return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1], + V.operands[2]); + if (V.opcode == Instruction::InsertValue) + return new InsertValueConstantExpr(V.operands[0], V.operands[1], + V.indices, Ty); + if (V.opcode == Instruction::ExtractValue) + return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty); + if (V.opcode == Instruction::GetElementPtr) { + std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end()); + return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty, + V.subclassoptionaldata); + } + + // The compare instructions are weird. We have to encode the predicate + // value and it is combined with the instruction opcode by multiplying + // the opcode by one hundred. We must decode this to get the predicate. + if (V.opcode == Instruction::ICmp) + return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata, + V.operands[0], V.operands[1]); + if (V.opcode == Instruction::FCmp) + return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata, + V.operands[0], V.operands[1]); + llvm_unreachable("Invalid ConstantExpr!"); } - 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; +}; + +template<> +struct ConstantKeyData<ConstantExpr> { + typedef ExprMapKeyType ValType; + static ValType getValType(ConstantExpr *CE) { + std::vector<Constant*> Operands; + Operands.reserve(CE->getNumOperands()); + for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) + Operands.push_back(cast<Constant>(CE->getOperand(i))); + return ExprMapKeyType(CE->getOpcode(), Operands, + CE->isCompare() ? CE->getPredicate() : 0, + CE->getRawSubclassOptionalData(), + CE->hasIndices() ? + CE->getIndices() : ArrayRef<unsigned>()); } - unsigned getHash() const { - return hash_combine_range(Operands.begin(), Operands.end()); +}; + +template<> +struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> { + static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) { + return new InlineAsm(Ty, Key.asm_string, Key.constraints, + Key.has_side_effects, Key.is_align_stack, + Key.asm_dialect); } +}; - typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass; - ConstantClass *create(TypeClass *Ty) const { - return new (Operands.size()) ConstantClass(Ty, Operands); +template<> +struct ConstantKeyData<InlineAsm> { + typedef InlineAsmKeyType ValType; + static ValType getValType(InlineAsm *Asm) { + return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(), + Asm->hasSideEffects(), Asm->isAlignStack(), + Asm->getDialect()); } }; -struct InlineAsmKeyType { - StringRef AsmString; - StringRef Constraints; - bool HasSideEffects; - bool IsAlignStack; - InlineAsm::AsmDialect AsmDialect; - - InlineAsmKeyType(StringRef AsmString, StringRef Constraints, - bool HasSideEffects, bool IsAlignStack, - InlineAsm::AsmDialect AsmDialect) - : AsmString(AsmString), Constraints(Constraints), - HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack), - AsmDialect(AsmDialect) {} - InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &) - : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()), - HasSideEffects(Asm->hasSideEffects()), - IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {} - - bool operator==(const InlineAsmKeyType &X) const { - return HasSideEffects == X.HasSideEffects && - IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect && - AsmString == X.AsmString && Constraints == X.Constraints; - } - bool operator==(const InlineAsm *Asm) const { - return HasSideEffects == Asm->hasSideEffects() && - IsAlignStack == Asm->isAlignStack() && - AsmDialect == Asm->getDialect() && - AsmString == Asm->getAsmString() && - Constraints == Asm->getConstraintString(); - } - unsigned getHash() const { - return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack, - AsmDialect); - } - - typedef ConstantInfo<InlineAsm>::TypeClass TypeClass; - InlineAsm *create(TypeClass *Ty) const { - return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects, - IsAlignStack, AsmDialect); - } -}; - -struct ConstantExprKeyType { - uint8_t Opcode; - uint8_t SubclassOptionalData; - uint16_t SubclassData; - ArrayRef<Constant *> Ops; - ArrayRef<unsigned> Indexes; - - ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops, - unsigned short SubclassData = 0, - unsigned short SubclassOptionalData = 0, - ArrayRef<unsigned> Indexes = None) - : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), - SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {} - ConstantExprKeyType(const ConstantExpr *CE, - SmallVectorImpl<Constant *> &Storage) - : Opcode(CE->getOpcode()), - SubclassOptionalData(CE->getRawSubclassOptionalData()), - SubclassData(CE->isCompare() ? CE->getPredicate() : 0), - Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) { - 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; - } - - 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 != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>())) - 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())); - } - - typedef ConstantInfo<ConstantExpr>::TypeClass TypeClass; - ConstantExpr *create(TypeClass *Ty) const { - switch (Opcode) { - default: - if (Instruction::isCast(Opcode)) - 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], Ops[2]); - 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(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]); +template<class ValType, class ValRefType, class TypeClass, class ConstantClass, + bool HasLargeKey = false /*true for arrays and structs*/ > +class ConstantUniqueMap { +public: + typedef std::pair<TypeClass*, ValType> MapKey; + typedef std::map<MapKey, ConstantClass *> MapTy; + typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy; +private: + /// Map - This is the main map from the element descriptor to the Constants. + /// This is the primary way we avoid creating two of the same shape + /// constant. + MapTy Map; + + /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping + /// from the constants to their element in Map. This is important for + /// removal of constants from the array, which would otherwise have to scan + /// through the map with very large keys. + InverseMapTy InverseMap; + +public: + typename MapTy::iterator map_begin() { return Map.begin(); } + typename MapTy::iterator map_end() { return Map.end(); } + + void freeConstants() { + for (typename MapTy::iterator I=Map.begin(), E=Map.end(); + I != E; ++I) { + // Asserts that use_empty(). + delete I->second; } } -}; + + /// InsertOrGetItem - Return an iterator for the specified element. + /// If the element exists in the map, the returned iterator points to the + /// entry and Exists=true. If not, the iterator points to the newly + /// inserted entry and returns Exists=false. Newly inserted entries have + /// I->second == 0, and should be filled in. + typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, ConstantClass *> + &InsertVal, + bool &Exists) { + std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal); + Exists = !IP.second; + return IP.first; + } + +private: + typename MapTy::iterator FindExistingElement(ConstantClass *CP) { + if (HasLargeKey) { + typename InverseMapTy::iterator IMI = InverseMap.find(CP); + assert(IMI != InverseMap.end() && IMI->second != Map.end() && + IMI->second->second == CP && + "InverseMap corrupt!"); + return IMI->second; + } + + typename MapTy::iterator I = + Map.find(MapKey(static_cast<TypeClass*>(CP->getType()), + ConstantKeyData<ConstantClass>::getValType(CP))); + if (I == Map.end() || I->second != CP) { + // FIXME: This should not use a linear scan. If this gets to be a + // performance problem, someone should look at this. + for (I = Map.begin(); I != Map.end() && I->second != CP; ++I) + /* empty */; + } + return I; + } + + ConstantClass *Create(TypeClass *Ty, ValRefType V, + typename MapTy::iterator I) { + ConstantClass* Result = + ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V); -template <class ConstantClass> class ConstantUniqueMap { + assert(Result->getType() == Ty && "Type specified is not correct!"); + I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result)); + + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.insert(std::make_pair(Result, I)); + + return Result; + } public: - typedef typename ConstantInfo<ConstantClass>::ValType ValType; - typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass; - typedef std::pair<TypeClass *, ValType> LookupKey; + + /// getOrCreate - Return the specified constant from the map, creating it if + /// necessary. + ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) { + MapKey Lookup(Ty, V); + ConstantClass* Result = nullptr; + + typename MapTy::iterator I = Map.find(Lookup); + // Is it in the map? + if (I != Map.end()) + Result = I->second; + + if (!Result) { + // If no preexisting value, create one now... + Result = Create(Ty, V, I); + } + + return Result; + } + void remove(ConstantClass *CP) { + typename MapTy::iterator I = FindExistingElement(CP); + assert(I != Map.end() && "Constant not found in constant table!"); + assert(I->second == CP && "Didn't find correct element?"); + + if (HasLargeKey) // Remember the reverse mapping if needed. + InverseMap.erase(CP); + + Map.erase(I); + } + + /// MoveConstantToNewSlot - If we are about to change C to be the element + /// specified by I, update our internal data structures to reflect this + /// fact. + void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) { + // First, remove the old location of the specified constant in the map. + typename MapTy::iterator OldI = FindExistingElement(C); + assert(OldI != Map.end() && "Constant not found in constant table!"); + assert(OldI->second == C && "Didn't find correct element?"); + + // Remove the old entry from the map. + Map.erase(OldI); + + // Update the inverse map so that we know that this constant is now + // located at descriptor I. + if (HasLargeKey) { + assert(I->second == C && "Bad inversemap entry!"); + InverseMap[C] = I; + } + } + + void dump() const { + DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); + } +}; + +// Unique map for aggregate constants +template<class TypeClass, class ConstantClass> +class ConstantAggrUniqueMap { +public: + typedef ArrayRef<Constant*> Operands; + typedef std::pair<TypeClass*, Operands> LookupKey; private: struct MapInfo { - typedef DenseMapInfo<ConstantClass *> ConstantClassInfo; - static inline ConstantClass *getEmptyKey() { + typedef DenseMapInfo<ConstantClass*> ConstantClassInfo; + typedef DenseMapInfo<Constant*> ConstantInfo; + typedef DenseMapInfo<TypeClass*> TypeClassInfo; + static inline ConstantClass* getEmptyKey() { return ConstantClassInfo::getEmptyKey(); } - static inline ConstantClass *getTombstoneKey() { + static inline ConstantClass* getTombstoneKey() { return ConstantClassInfo::getTombstoneKey(); } static unsigned getHashValue(const ConstantClass *CP) { - SmallVector<Constant *, 8> Storage; - return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage))); + SmallVector<Constant*, 8> CPOperands; + CPOperands.reserve(CP->getNumOperands()); + for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I) + CPOperands.push_back(CP->getOperand(I)); + return getHashValue(LookupKey(CP->getType(), CPOperands)); } 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()); + return hash_combine(Val.first, hash_combine_range(Val.second.begin(), + Val.second.end())); } static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) { if (RHS == getEmptyKey() || RHS == getTombstoneKey()) return false; - if (LHS.first != RHS->getType()) + if (LHS.first != RHS->getType() + || LHS.second.size() != RHS->getNumOperands()) return false; - return LHS.second == RHS; + for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) { + if (LHS.second[I] != RHS->getOperand(I)) + return false; + } + return true; } }; - public: typedef DenseMap<ConstantClass *, char, MapInfo> MapTy; private: + /// Map - This is the main map from the element descriptor to the Constants. + /// This is the primary way we avoid creating two of the same shape + /// constant. MapTy Map; public: @@ -547,33 +694,44 @@ public: typename MapTy::iterator map_end() { return Map.end(); } void freeConstants() { - for (auto &I : Map) + for (typename MapTy::iterator I=Map.begin(), E=Map.end(); + I != E; ++I) { // Asserts that use_empty(). - delete I.first; + delete I->first; + } } private: - ConstantClass *create(TypeClass *Ty, ValType V) { - ConstantClass *Result = V.create(Ty); + typename MapTy::iterator findExistingElement(ConstantClass *CP) { + return Map.find(CP); + } + + ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) { + ConstantClass* Result = + ConstantArrayCreator<ConstantClass,TypeClass>::create(Ty, V); assert(Result->getType() == Ty && "Type specified is not correct!"); - insert(Result); + Map[Result] = '\0'; return Result; } - public: - /// Return the specified constant from the map, creating it if necessary. - ConstantClass *getOrCreate(TypeClass *Ty, ValType V) { + + /// getOrCreate - Return the specified constant from the map, creating it if + /// necessary. + ConstantClass *getOrCreate(TypeClass *Ty, Operands V) { LookupKey Lookup(Ty, V); - ConstantClass *Result = nullptr; + ConstantClass* Result = nullptr; - auto I = find(Lookup); - if (I == Map.end()) - Result = create(Ty, V); - else + typename MapTy::iterator I = Map.find_as(Lookup); + // Is it in the map? + if (I != Map.end()) Result = I->first; - assert(Result && "Unexpected nullptr"); + + if (!Result) { + // If no preexisting value, create one now... + Result = Create(Ty, V, I); + } return Result; } @@ -584,17 +742,21 @@ public: } /// Insert the constant into its proper slot. - void insert(ConstantClass *CP) { Map[CP] = '\0'; } + void insert(ConstantClass *CP) { + Map[CP] = '\0'; + } /// Remove this constant from the map void remove(ConstantClass *CP) { - typename MapTy::iterator I = Map.find(CP); + typename MapTy::iterator I = findExistingElement(CP); assert(I != Map.end() && "Constant not found in constant table!"); assert(I->first == CP && "Didn't find correct element?"); Map.erase(I); } - void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); } + void dump() const { + DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); + } }; } // end namespace llvm diff --git a/llvm/lib/IR/LLVMContextImpl.cpp b/llvm/lib/IR/LLVMContextImpl.cpp index 6513965ae7a..4c2791f0a8d 100644 --- a/llvm/lib/IR/LLVMContextImpl.cpp +++ b/llvm/lib/IR/LLVMContextImpl.cpp @@ -75,7 +75,7 @@ LLVMContextImpl::~LLVMContextImpl() { // Free the constants. This is important to do here to ensure that they are // freed before the LeakDetector is torn down. std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(), - DropFirst()); + DropReferences()); std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(), DropFirst()); std::for_each(StructConstants.map_begin(), StructConstants.map_end(), diff --git a/llvm/lib/IR/LLVMContextImpl.h b/llvm/lib/IR/LLVMContextImpl.h index 412f36db06e..1eead4ad41d 100644 --- a/llvm/lib/IR/LLVMContextImpl.h +++ b/llvm/lib/IR/LLVMContextImpl.h @@ -272,13 +272,13 @@ public: DenseMap<Type*, ConstantAggregateZero*> CAZConstants; - typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy; + typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy; ArrayConstantsTy ArrayConstants; - typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy; + typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy; StructConstantsTy StructConstants; - typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy; + typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy; VectorConstantsTy VectorConstants; DenseMap<PointerType*, ConstantPointerNull*> CPNConstants; @@ -289,10 +289,12 @@ public: DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *> BlockAddresses; - ConstantUniqueMap<ConstantExpr> ExprConstants; - - ConstantUniqueMap<InlineAsm> InlineAsms; + ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr> + ExprConstants; + ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType, + InlineAsm> InlineAsms; + ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; |