From 93710f07f02b3961556d2344e1baab1f53e4b45e Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 19 Aug 2014 14:59:02 +0000 Subject: [PATCH] Reverting r215966, r215965, r215964, r215963, r215960, r215959, r215958, and r215957 (these commits all rely on previous commits) due to build breakage. These commits cause failed assertions when testing Clang using MSVC 2013. The asserts are triggered from the std::equal call within ArrayRef::equals due to being passed invalid input (ArrayRef.begin() is returning a nullptr which is problematic). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@215981 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Constant.h | 2 - include/llvm/IR/Constants.h | 32 +- include/llvm/IR/InlineAsm.h | 12 +- lib/IR/Constants.cpp | 289 +++++++---------- lib/IR/ConstantsContext.h | 564 +++++++++++++++++++++------------ lib/IR/LLVMContextImpl.cpp | 2 +- lib/IR/LLVMContextImpl.h | 14 +- unittests/IR/ConstantsTest.cpp | 25 -- 8 files changed, 502 insertions(+), 438 deletions(-) diff --git a/include/llvm/IR/Constant.h b/include/llvm/IR/Constant.h index 019e2b93380..d9d163b23ec 100644 --- a/include/llvm/IR/Constant.h +++ b/include/llvm/IR/Constant.h @@ -48,8 +48,6 @@ protected: : User(ty, vty, Ops, NumOps) {} void destroyConstantImpl(); - void replaceUsesOfWithOnConstantImpl(Constant *Replacement); - public: /// isNullValue - Return true if this is the value that would be returned by /// getNullValue. diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 4c99e74173f..0e72f040d3e 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -37,8 +37,12 @@ class PointerType; class VectorType; class SequentialType; -struct ConstantExprKeyType; -template struct ConstantAggrKeyType; +template +struct ConstantCreator; +template +struct ConstantArrayCreator; +template +struct ConvertConstantType; //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class @@ -334,7 +338,7 @@ public: /// ConstantArray - Constant Array Declarations /// class ConstantArray : public Constant { - friend struct ConstantAggrKeyType; + friend struct ConstantArrayCreator; ConstantArray(const ConstantArray &) LLVM_DELETED_FUNCTION; protected: ConstantArray(ArrayType *T, ArrayRef Val); @@ -342,10 +346,6 @@ public: // ConstantArray accessors static Constant *get(ArrayType *T, ArrayRef V); -private: - static Constant *getImpl(ArrayType *T, ArrayRef V); - -public: /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); @@ -376,7 +376,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant) // ConstantStruct - Constant Struct Declarations // class ConstantStruct : public Constant { - friend struct ConstantAggrKeyType; + friend struct ConstantArrayCreator; ConstantStruct(const ConstantStruct &) LLVM_DELETED_FUNCTION; protected: ConstantStruct(StructType *T, ArrayRef Val); @@ -435,7 +435,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant) /// ConstantVector - Constant Vector Declarations /// class ConstantVector : public Constant { - friend struct ConstantAggrKeyType; + friend struct ConstantArrayCreator; ConstantVector(const ConstantVector &) LLVM_DELETED_FUNCTION; protected: ConstantVector(VectorType *T, ArrayRef Val); @@ -443,10 +443,6 @@ public: // ConstantVector accessors static Constant *get(ArrayRef V); -private: - static Constant *getImpl(ArrayRef V); - -public: /// getSplat - Return a ConstantVector with the specified constant in each /// element. static Constant *getSplat(unsigned NumElts, Constant *Elt); @@ -798,7 +794,9 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BlockAddress, Value) /// constant expressions. The Opcode field for the ConstantExpr class is /// maintained in the Value::SubclassData field. class ConstantExpr : public Constant { - friend struct ConstantExprKeyType; + friend struct ConstantCreator > >; + friend struct ConvertConstantType; protected: ConstantExpr(Type *ty, unsigned Opcode, Use *Ops, unsigned NumOps) @@ -1115,12 +1113,6 @@ private: void setValueSubclassData(unsigned short D) { Value::setValueSubclassData(D); } - - /// \brief Check whether this can become its replacement. - /// - /// For use during \a replaceUsesOfWithOnConstant(), check whether we know - /// how to turn this into \a Replacement, thereby reducing RAUW traffic. - bool canBecomeReplacement(const Constant *Replacement) const; }; template <> diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index b2d79d0f0bf..ac190892bab 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -25,9 +25,12 @@ namespace llvm { class PointerType; class FunctionType; class Module; - struct InlineAsmKeyType; -template class ConstantUniqueMap; +template +class ConstantUniqueMap; +template +struct ConstantCreator; class InlineAsm : public Value { public: @@ -37,8 +40,9 @@ public: }; private: - friend struct InlineAsmKeyType; - friend class ConstantUniqueMap; + friend struct ConstantCreator; + friend class ConstantUniqueMap; InlineAsm(const InlineAsm &) LLVM_DELETED_FUNCTION; void operator=(const InlineAsm&) LLVM_DELETED_FUNCTION; diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index cb7c9e63059..45a71dc6230 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -803,11 +803,6 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef V) } Constant *ConstantArray::get(ArrayType *Ty, ArrayRef V) { - if (Constant *C = getImpl(Ty, V)) - return C; - return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V); -} -Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef V) { // Empty arrays are canonicalized to ConstantAggregateZero. if (V.empty()) return ConstantAggregateZero::get(Ty); @@ -816,6 +811,7 @@ Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef 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 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 V) // ConstantVector accessors. Constant *ConstantVector::get(ArrayRef 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 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 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 Idxs, "getelementptr index type missmatch"); ArgVec.push_back(cast(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(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(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(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(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(ToC)) { + Replacement = UndefValue::get(getType()); + } else { + // Check to see if we have this array type already. + LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup( + cast(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(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(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(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(To) && "Cannot make Constant refer to non-constant!"); - Constant *ToC = cast(To); SmallVector 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(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(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(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 ValueOperands; for (op_iterator I = op_begin(), E = op_end(); I != E; ++I) diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h index 092de718776..c3aefb9ce2d 100644 --- a/lib/IR/ConstantsContext.h +++ b/lib/IR/ConstantsContext.h @@ -29,6 +29,8 @@ #define DEBUG_TYPE "ir" namespace llvm { +template +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 : }; DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value) -template struct ConstantAggrKeyType; -struct InlineAsmKeyType; -struct ConstantExprKeyType; +struct ExprMapKeyType { + ExprMapKeyType(unsigned opc, + ArrayRef ops, + unsigned short flags = 0, + unsigned short optionalflags = 0, + ArrayRef 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 operands; + SmallVector 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 struct ConstantInfo; -template <> struct ConstantInfo { - 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 { - 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 +struct ConstantTraits< std::vector > { + static unsigned uses(const std::vector& v) { + return v.size(); + } }; -template <> struct ConstantInfo { - typedef ConstantAggrKeyType ValType; - typedef ArrayType TypeClass; + +template<> +struct ConstantTraits { + static unsigned uses(Constant * const & v) { + return 1; + } }; -template <> struct ConstantInfo { - typedef ConstantAggrKeyType ValType; - typedef StructType TypeClass; + +template +struct ConstantCreator { + static ConstantClass *create(TypeClass *Ty, const ValType &V) { + return new(ConstantTraits::uses(V)) ConstantClass(Ty, V); + } }; -template <> struct ConstantInfo { - typedef ConstantAggrKeyType ValType; - typedef VectorType TypeClass; + +template +struct ConstantArrayCreator { + static ConstantClass *create(TypeClass *Ty, ArrayRef V) { + return new(V.size()) ConstantClass(Ty, V); + } }; -template struct ConstantAggrKeyType { - ArrayRef Operands; - ConstantAggrKeyType(ArrayRef Operands) : Operands(Operands) {} - ConstantAggrKeyType(const ConstantClass *C, - SmallVectorImpl &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 +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 { + 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 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 { + typedef ExprMapKeyType ValType; + static ValType getValType(ConstantExpr *CE) { + std::vector Operands; + Operands.reserve(CE->getNumOperands()); + for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) + Operands.push_back(cast(CE->getOperand(i))); + return ExprMapKeyType(CE->getOpcode(), Operands, + CE->isCompare() ? CE->getPredicate() : 0, + CE->getRawSubclassOptionalData(), + CE->hasIndices() ? + CE->getIndices() : ArrayRef()); } - unsigned getHash() const { - return hash_combine_range(Operands.begin(), Operands.end()); +}; + +template<> +struct ConstantCreator { + 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::TypeClass TypeClass; - ConstantClass *create(TypeClass *Ty) const { - return new (Operands.size()) ConstantClass(Ty, Operands); +template<> +struct ConstantKeyData { + 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 &) - : 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::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 Ops; - ArrayRef Indexes; - - ConstantExprKeyType(unsigned Opcode, ArrayRef Ops, - unsigned short SubclassData = 0, - unsigned short SubclassOptionalData = 0, - ArrayRef Indexes = None) - : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), - SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {} - ConstantExprKeyType(const ConstantExpr *CE, - SmallVectorImpl &Storage) - : Opcode(CE->getOpcode()), - SubclassOptionalData(CE->getRawSubclassOptionalData()), - SubclassData(CE->isCompare() ? CE->getPredicate() : 0), - Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef()) { - 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())) - 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::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 ConstantUniqueMap { +public: + typedef std::pair MapKey; + typedef std::map MapTy; + typedef std::map 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 + &InsertVal, + bool &Exists) { + std::pair 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(CP->getType()), + ConstantKeyData::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::create(Ty, V); -template 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::ValType ValType; - typedef typename ConstantInfo::TypeClass TypeClass; - typedef std::pair 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 ConstantAggrUniqueMap { +public: + typedef ArrayRef Operands; + typedef std::pair LookupKey; private: struct MapInfo { - typedef DenseMapInfo ConstantClassInfo; - static inline ConstantClass *getEmptyKey() { + typedef DenseMapInfo ConstantClassInfo; + typedef DenseMapInfo ConstantInfo; + typedef DenseMapInfo 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 Storage; - return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage))); + SmallVector 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 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::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/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 6513965ae7a..4c2791f0a8d 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/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/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index 412f36db06e..1eead4ad41d 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -272,13 +272,13 @@ public: DenseMap CAZConstants; - typedef ConstantUniqueMap ArrayConstantsTy; + typedef ConstantAggrUniqueMap ArrayConstantsTy; ArrayConstantsTy ArrayConstants; - typedef ConstantUniqueMap StructConstantsTy; + typedef ConstantAggrUniqueMap StructConstantsTy; StructConstantsTy StructConstants; - typedef ConstantUniqueMap VectorConstantsTy; + typedef ConstantAggrUniqueMap VectorConstantsTy; VectorConstantsTy VectorConstants; DenseMap CPNConstants; @@ -289,10 +289,12 @@ public: DenseMap, BlockAddress *> BlockAddresses; - ConstantUniqueMap ExprConstants; - - ConstantUniqueMap InlineAsms; + ConstantUniqueMap + ExprConstants; + ConstantUniqueMap InlineAsms; + ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; diff --git a/unittests/IR/ConstantsTest.cpp b/unittests/IR/ConstantsTest.cpp index 52f098e969e..0cd85499828 100644 --- a/unittests/IR/ConstantsTest.cpp +++ b/unittests/IR/ConstantsTest.cpp @@ -274,30 +274,5 @@ TEST(ConstantsTest, ReplaceWithConstantTest) { #undef CHECK -TEST(ConstantsTest, ConstantArrayReplaceWithConstant) { - LLVMContext Context; - std::unique_ptr M(new Module("MyModule", Context)); - - Type *IntTy = Type::getInt8Ty(Context); - ArrayType *ArrayTy = ArrayType::get(IntTy, 2); - Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0), - ConstantInt::get(IntTy, 1)}; - Constant *A01 = ConstantArray::get(ArrayTy, A01Vals); - - Constant *Global = new GlobalVariable(*M, IntTy, false, - GlobalValue::ExternalLinkage, nullptr); - Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy); - Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt}; - Constant *A0G = ConstantArray::get(ArrayTy, A0GVals); - ASSERT_NE(A01, A0G); - - GlobalVariable *RefArray = - new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G); - ASSERT_EQ(A0G, RefArray->getInitializer()); - - GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1)); - ASSERT_EQ(A01, RefArray->getInitializer()); -} - } // end anonymous namespace } // end namespace llvm -- 2.34.1