From 006c77df8cc7f6a9dac575600b797b8ba32b29eb Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Thu, 23 Jul 2009 23:25:33 +0000 Subject: [PATCH] Privatize the ConstantStruct table. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@76912 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Constants.h | 5 +- include/llvm/LLVMContext.h | 3 + lib/VMCore/Constants.cpp | 96 ++---------------------------- lib/VMCore/LLVMContext.cpp | 11 +++- lib/VMCore/LLVMContextImpl.cpp | 104 +++++++++++++++++++++++++++++++++ lib/VMCore/LLVMContextImpl.h | 11 ++++ 6 files changed, 133 insertions(+), 97 deletions(-) diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index a9a18d7930f..12f97857421 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -344,13 +344,10 @@ class ConstantStruct : public Constant { friend struct ConstantCreator >; ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT + friend class LLVMContextImpl; protected: ConstantStruct(const StructType *T, const std::vector &Val); public: - /// get() - Static factory methods - Return objects of the specified value - /// - static Constant *get(const StructType *T, const std::vector &V); - /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); diff --git a/include/llvm/LLVMContext.h b/include/llvm/LLVMContext.h index 0751ccd83a7..53b0868ec26 100644 --- a/include/llvm/LLVMContext.h +++ b/include/llvm/LLVMContext.h @@ -275,10 +275,13 @@ public: void erase(MDNode *M); void erase(ConstantAggregateZero *Z); void erase(ConstantArray *Z); + void erase(ConstantStruct *S); // RAUW helpers Constant *replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U); + Constant *replaceUsesOfWithOnConstant(ConstantStruct *CS, Value *From, + Value *To, Use *U); }; /// FOR BACKWARDS COMPATIBILITY - Returns a global context. diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index 065ebcd5dc9..40034df81bd 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1096,50 +1096,14 @@ std::string ConstantArray::getAsString() const { // namespace llvm { - template<> - struct ConvertConstantType { - static void convert(ConstantStruct *OldC, const StructType *NewTy) { - // Make everyone now use a constant of the new type... - std::vector C; - for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) - C.push_back(cast(OldC->getOperand(i))); - Constant *New = ConstantStruct::get(NewTy, C); - assert(New != OldC && "Didn't replace constant??"); - OldC->uncheckedReplaceAllUsesWith(New); - OldC->destroyConstant(); // This constant is now dead, destroy it. - } - }; -} - -typedef ValueMap, StructType, - ConstantStruct, true /*largekey*/> StructConstantsTy; -static ManagedStatic StructConstants; - -static std::vector getValType(ConstantStruct *CS) { - std::vector Elements; - Elements.reserve(CS->getNumOperands()); - for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) - Elements.push_back(cast(CS->getOperand(i))); - return Elements; -} - -Constant *ConstantStruct::get(const StructType *Ty, - const std::vector &V) { - // Create a ConstantAggregateZero value if all elements are zeros... - for (unsigned i = 0, e = V.size(); i != e; ++i) - if (!V[i]->isNullValue()) - // Implicitly locked. - return StructConstants->getOrCreate(Ty, V); - - return Ty->getContext().getConstantAggregateZero(Ty); } // destroyConstant - Remove the constant from the constant table... // void ConstantStruct::destroyConstant() { // Implicitly locked. - StructConstants->remove(this); + getType()->getContext().erase(this); destroyConstantImpl(); } @@ -2112,61 +2076,9 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To, void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) { - assert(isa(To) && "Cannot make Constant refer to non-constant!"); - Constant *ToC = cast(To); - - unsigned OperandToUpdate = U-OperandList; - assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!"); - - std::pair Lookup; - Lookup.first.first = getType(); - Lookup.second = this; - std::vector &Values = Lookup.first.second; - Values.reserve(getNumOperands()); // Build replacement struct. - - - // Fill values with the modified operands of the constant struct. Also, - // compute whether this turns into an all-zeros struct. - bool isAllZeros = false; - if (!ToC->isNullValue()) { - for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) - Values.push_back(cast(O->get())); - } else { - isAllZeros = true; - for (Use *O = OperandList, *E = OperandList+getNumOperands(); O != E; ++O) { - Constant *Val = cast(O->get()); - Values.push_back(Val); - if (isAllZeros) isAllZeros = Val->isNullValue(); - } - } - Values[OperandToUpdate] = ToC; - - Constant *Replacement = 0; - if (isAllZeros) { - Replacement = getType()->getContext().getConstantAggregateZero(getType()); - } else { - // Check to see if we have this array type already. - sys::SmartScopedWriter Writer(*ConstantsLock); - bool Exists; - StructConstantsTy::MapTy::iterator I = - StructConstants->InsertOrGetItem(Lookup, Exists); - - if (Exists) { - Replacement = I->second; - } 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! - StructConstants->MoveConstantToNewSlot(this, I); - - // Update to the new value. - setOperand(OperandToUpdate, ToC); - return; - } - } - - assert(Replacement != this && "I didn't contain From!"); + Constant* Replacement = + getType()->getContext().replaceUsesOfWithOnConstant(this, From, To, U); + if (!Replacement) return; // Everyone using this now uses the replacement. uncheckedReplaceAllUsesWith(Replacement); diff --git a/lib/VMCore/LLVMContext.cpp b/lib/VMCore/LLVMContext.cpp index d0abb2df626..5a4cf2027da 100644 --- a/lib/VMCore/LLVMContext.cpp +++ b/lib/VMCore/LLVMContext.cpp @@ -146,7 +146,7 @@ ConstantPointerNull* LLVMContext::getConstantPointerNull(const PointerType* T) { // ConstantStruct accessors. Constant* LLVMContext::getConstantStruct(const StructType* T, const std::vector& V) { - return ConstantStruct::get(T, V); + return pImpl->getConstantStruct(T, V); } Constant* LLVMContext::getConstantStruct(const std::vector& V, @@ -658,7 +658,16 @@ void LLVMContext::erase(ConstantArray *C) { pImpl->erase(C); } +void LLVMContext::erase(ConstantStruct *S) { + pImpl->erase(S); +} + Constant *LLVMContext::replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U) { return pImpl->replaceUsesOfWithOnConstant(CA, From, To, U); } + +Constant *LLVMContext::replaceUsesOfWithOnConstant(ConstantStruct *CS, + Value *From, Value *To, Use *U) { + return pImpl->replaceUsesOfWithOnConstant(CS, From, To, U); +} diff --git a/lib/VMCore/LLVMContextImpl.cpp b/lib/VMCore/LLVMContextImpl.cpp index 1c5af77c1cb..156d4cacd15 100644 --- a/lib/VMCore/LLVMContextImpl.cpp +++ b/lib/VMCore/LLVMContextImpl.cpp @@ -29,6 +29,14 @@ static std::vector getValType(ConstantArray *CA) { return Elements; } +static std::vector getValType(ConstantStruct *CS) { + std::vector Elements; + Elements.reserve(CS->getNumOperands()); + for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) + Elements.push_back(cast(CS->getOperand(i))); + return Elements; +} + namespace llvm { template struct VISIBILITY_HIDDEN ConstantTraits< std::vector > { @@ -83,6 +91,21 @@ struct ConvertConstantType { OldC->destroyConstant(); // This constant is now dead, destroy it. } }; + +template<> +struct ConvertConstantType { + static void convert(ConstantStruct *OldC, const StructType *NewTy) { + // Make everyone now use a constant of the new type... + std::vector C; + for (unsigned i = 0, e = OldC->getNumOperands(); i != e; ++i) + C.push_back(cast(OldC->getOperand(i))); + Constant *New = NewTy->getContext().getConstantStruct(NewTy, C); + assert(New != OldC && "Didn't replace constant??"); + + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } +}; } template(); ArrayConstants = new ArrayConstantsTy(); + StructConstants = new StructConstantsTy(); } LLVMContextImpl::~LLVMContextImpl() { delete AggZeroConstants; delete ArrayConstants; + delete StructConstants; } // Get a ConstantInt from an APInt. Note that the value stored in the DenseMap @@ -456,6 +481,17 @@ Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty, return Context.getConstantAggregateZero(Ty); } +Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty, + const std::vector &V) { + // Create a ConstantAggregateZero value if all elements are zeros... + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (!V[i]->isNullValue()) + // Implicitly locked. + return StructConstants->getOrCreate(Ty, V); + + return Context.getConstantAggregateZero(Ty); +} + // *** erase methods *** void LLVMContextImpl::erase(MDString *M) { @@ -477,7 +513,12 @@ void LLVMContextImpl::erase(ConstantArray *C) { ArrayConstants->remove(C); } +void LLVMContextImpl::erase(ConstantStruct *S) { + StructConstants->remove(S); +} + // *** RAUW helpers *** + Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); @@ -556,3 +597,66 @@ Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA, return Replacement; } +Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS, + Value *From, Value *To, Use *U) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + Constant *ToC = cast(To); + + unsigned OperandToUpdate = U - CS->OperandList; + assert(CS->getOperand(OperandToUpdate) == From && + "ReplaceAllUsesWith broken!"); + + std::pair Lookup; + Lookup.first.first = CS->getType(); + Lookup.second = CS; + std::vector &Values = Lookup.first.second; + Values.reserve(CS->getNumOperands()); // Build replacement struct. + + + // Fill values with the modified operands of the constant struct. Also, + // compute whether this turns into an all-zeros struct. + bool isAllZeros = false; + if (!ToC->isNullValue()) { + for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); + O != E; ++O) + Values.push_back(cast(O->get())); + } else { + isAllZeros = true; + for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); + O != E; ++O) { + Constant *Val = cast(O->get()); + Values.push_back(Val); + if (isAllZeros) isAllZeros = Val->isNullValue(); + } + } + Values[OperandToUpdate] = ToC; + + Constant *Replacement = 0; + if (isAllZeros) { + Replacement = Context.getConstantAggregateZero(CS->getType()); + } else { + // Check to see if we have this array type already. + sys::SmartScopedWriter Writer(ConstantsLock); + bool Exists; + StructConstantsTy::MapTy::iterator I = + StructConstants->InsertOrGetItem(Lookup, Exists); + + if (Exists) { + Replacement = I->second; + } 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! + StructConstants->MoveConstantToNewSlot(CS, I); + + // Update to the new value. + CS->setOperand(OperandToUpdate, ToC); + return 0; + } + } + + assert(Replacement != CS && "I didn't contain From!"); + + return Replacement; +} \ No newline at end of file diff --git a/lib/VMCore/LLVMContextImpl.h b/lib/VMCore/LLVMContextImpl.h index 392e500f128..f313ed62078 100644 --- a/lib/VMCore/LLVMContextImpl.h +++ b/lib/VMCore/LLVMContextImpl.h @@ -27,6 +27,7 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/StringMap.h" #include +#include template @@ -117,6 +118,10 @@ class LLVMContextImpl { ConstantArray, true /*largekey*/> ArrayConstantsTy; ArrayConstantsTy *ArrayConstants; + typedef ValueMap, StructType, + ConstantStruct, true /*largekey*/> StructConstantsTy; + StructConstantsTy *StructConstants; + LLVMContext &Context; ConstantInt *TheTrueVal; ConstantInt *TheFalseVal; @@ -142,6 +147,9 @@ public: Constant *getConstantArray(const ArrayType *Ty, const std::vector &V); + Constant *getConstantStruct(const StructType *Ty, + const std::vector &V); + ConstantInt *getTrue() { if (TheTrueVal) return TheTrueVal; @@ -160,11 +168,14 @@ public: void erase(MDNode *M); void erase(ConstantAggregateZero *Z); void erase(ConstantArray *C); + void erase(ConstantStruct *S); // RAUW helpers Constant *replaceUsesOfWithOnConstant(ConstantArray *CA, Value *From, Value *To, Use *U); + Constant *replaceUsesOfWithOnConstant(ConstantStruct *CS, Value *From, + Value *To, Use *U); }; }