From 40bbeb5d077b1bc2b933d8c8628024dfa9b428c3 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sun, 15 Feb 2004 05:53:04 +0000 Subject: [PATCH] Add a new ConstantAggregateZero class, to fix PR239. This makes zero initializers for constant structs and arrays take constant space, instead of space proportinal to the number of elements. This reduces the memory usage of the LLVM compiler by hundreds of megabytes when compiling some nasty SPEC95 benchmarks. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11470 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Constants.h | 56 +++++++++++++-------- lib/VMCore/Constants.cpp | 106 ++++++++++++++++++++++++++------------- 2 files changed, 106 insertions(+), 56 deletions(-) diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 0921cbb21bb..6a02c5df215 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -309,6 +309,36 @@ public: } }; +//===--------------------------------------------------------------------------- +/// ConstantAggregateZero - All zero aggregate value +/// +class ConstantAggregateZero : public Constant { + friend struct ConstantCreator; + ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT +protected: + ConstantAggregateZero(const Type *Ty) : Constant(Ty) {} +public: + /// get() - static factory method for creating a null aggregate. It is + /// illegal to call this method with a non-aggregate type. + static Constant *get(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, + bool DisableChecking = false); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static inline bool classof(const ConstantAggregateZero *) { return true; } + static bool classof(const Constant *CPV); + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + //===--------------------------------------------------------------------------- /// ConstantArray - Constant Array Declarations @@ -345,19 +375,9 @@ public: inline const std::vector &getValues() const { return Operands; } /// isNullValue - Return true if this is the value that would be returned by - /// getNullValue. - virtual bool isNullValue() const { - // FIXME: This should be made to be MUCH faster. Just check against well - // known null value! - if (getNumOperands()) { - const Constant *First = cast(getOperand(0)); - if (!First->isNullValue()) return false; - for (unsigned i = 1, e = getNumOperands(); i != e; ++i) - if (cast(getOperand(i)) != First) - return false; - } - return true; - } + /// getNullValue. This always returns false because zero arrays are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } virtual void destroyConstant(); virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, @@ -395,14 +415,10 @@ public: inline const std::vector &getValues() const { return Operands; } /// isNullValue - Return true if this is the value that would be returned by - /// getNullValue. + /// getNullValue. This always returns false because zero structs are always + /// created as ConstantAggregateZero objects. virtual bool isNullValue() const { - // FIXME: This should be made to be MUCH faster. Just check against well - // known null value! - for (unsigned i = 0, e = getNumOperands(); i != e; ++i) - if (!cast(getOperand(i))->isNullValue()) - return false; - return true; + return false; } virtual void destroyConstant(); diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index e13a1daad52..dac23aea55c 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -64,8 +64,6 @@ void Constant::destroyConstantImpl() { delete this; } -static std::map NullValues; - // Static constructor to create a '0' constant of arbitrary type... Constant *Constant::getNullValue(const Type *Ty) { switch (Ty->getPrimitiveID()) { @@ -118,35 +116,9 @@ Constant *Constant::getNullValue(const Type *Ty) { case Type::PointerTyID: return ConstantPointerNull::get(cast(Ty)); - case Type::StructTyID: { - if (!Ty->isAbstract()) - if (Constant *V = NullValues[Ty]) - return V; - - const StructType *ST = cast(Ty); - std::vector Elements; - Elements.resize(ST->getNumElements()); - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) - Elements[i] = Constant::getNullValue(ST->getElementType(i)); - Constant *Ret = ConstantStruct::get(ST, Elements); - if (!Ty->isAbstract()) - NullValues[Ty] = Ret; - return Ret; - } - case Type::ArrayTyID: { - if (!Ty->isAbstract()) - if (Constant *V = NullValues[Ty]) - return V; - - const ArrayType *AT = cast(Ty); - Constant *El = Constant::getNullValue(AT->getElementType()); - unsigned NumElements = AT->getNumElements(); - Constant *Ret = ConstantArray::get(AT, - std::vector(NumElements, El)); - if (!Ty->isAbstract()) - NullValues[Ty] = Ret; - return Ret; - } + case Type::StructTyID: + case Type::ArrayTyID: + return ConstantAggregateZero::get(Ty); default: // Function, Type, Label, or Opaque type? assert(0 && "Cannot create a null constant of that type!"); @@ -347,11 +319,15 @@ bool ConstantFP::classof(const Constant *CPV) { return ((Ty == Type::FloatTy || Ty == Type::DoubleTy) && !isa(CPV)); } +bool ConstantAggregateZero::classof(const Constant *CPV) { + return (isa(CPV->getType()) || isa(CPV->getType())) && + CPV->isNullValue(); +} bool ConstantArray::classof(const Constant *CPV) { - return isa(CPV->getType()) && !isa(CPV); + return isa(CPV->getType()) && !CPV->isNullValue(); } bool ConstantStruct::classof(const Constant *CPV) { - return isa(CPV->getType()) && !isa(CPV); + return isa(CPV->getType()) && !CPV->isNullValue(); } bool ConstantPointerNull::classof(const Constant *CPV) { @@ -765,6 +741,50 @@ ConstantFP *ConstantFP::get(const Type *Ty, double V) { } } +//---- ConstantAggregateZero::get() implementation... +// +namespace llvm { + // ConstantAggregateZero does not take extra "value" argument... + template + struct ConstantCreator { + static ConstantAggregateZero *create(const Type *Ty, const ValType &V){ + return new ConstantAggregateZero(Ty); + } + }; + + template<> + struct ConvertConstantType { + static void convert(ConstantAggregateZero *OldC, const Type *NewTy) { + // Make everyone now use a constant of the new type... + Constant *New = ConstantAggregateZero::get(NewTy); + assert(New != OldC && "Didn't replace constant??"); + OldC->uncheckedReplaceAllUsesWith(New); + OldC->destroyConstant(); // This constant is now dead, destroy it. + } + }; +} + +static ValueMap AggZeroConstants; + +Constant *ConstantAggregateZero::get(const Type *Ty) { + return AggZeroConstants.getOrCreate(Ty, 0); +} + +// destroyConstant - Remove the constant from the constant table... +// +void ConstantAggregateZero::destroyConstant() { + AggZeroConstants.remove(this); + destroyConstantImpl(); +} + +void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To, + bool DisableChecking) { + assert(0 && "No uses!"); + abort(); +} + + + //---- ConstantArray::get() implementation... // namespace llvm { @@ -787,8 +807,17 @@ static ValueMap, ArrayType, ConstantArray> ArrayConstants; Constant *ConstantArray::get(const ArrayType *Ty, - const std::vector &V) { - return ArrayConstants.getOrCreate(Ty, V); + const std::vector &V) { + // If this is an all-zero array, return a ConstantAggregateZero object + if (!V.empty()) { + Constant *C = V[0]; + if (!C->isNullValue()) + return ArrayConstants.getOrCreate(Ty, V); + for (unsigned i = 1, e = V.size(); i != e; ++i) + if (V[i] != C) + return ArrayConstants.getOrCreate(Ty, V); + } + return ConstantAggregateZero::get(Ty); } // destroyConstant - Remove the constant from the constant table... @@ -868,7 +897,12 @@ static ValueMap, StructType, Constant *ConstantStruct::get(const StructType *Ty, const std::vector &V) { - return StructConstants.getOrCreate(Ty, V); + // Create a ConstantAggregateZero value if all elements are zeros... + for (unsigned i = 0, e = V.size(); i != e; ++i) + if (!V[i]->isNullValue()) + return StructConstants.getOrCreate(Ty, V); + + return ConstantAggregateZero::get(Ty); } // destroyConstant - Remove the constant from the constant table... -- 2.34.1