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
This commit is contained in:
Chris Lattner 2004-02-15 05:53:04 +00:00
parent 46ccf6d382
commit 40bbeb5d07
2 changed files with 106 additions and 56 deletions

View File

@ -309,6 +309,36 @@ public:
}
};
//===---------------------------------------------------------------------------
/// ConstantAggregateZero - All zero aggregate value
///
class ConstantAggregateZero : public Constant {
friend struct ConstantCreator<ConstantAggregateZero, Type, char>;
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<Constant>(V) && classof(cast<Constant>(V));
}
};
//===---------------------------------------------------------------------------
/// ConstantArray - Constant Array Declarations
@ -345,19 +375,9 @@ public:
inline const std::vector<Use> &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<Constant>(getOperand(0));
if (!First->isNullValue()) return false;
for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
if (cast<Constant>(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<Use> &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<Constant>(getOperand(i))->isNullValue())
return false;
return true;
return false;
}
virtual void destroyConstant();

View File

@ -64,8 +64,6 @@ void Constant::destroyConstantImpl() {
delete this;
}
static std::map<const Type *, Constant*> 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<PointerType>(Ty));
case Type::StructTyID: {
if (!Ty->isAbstract())
if (Constant *V = NullValues[Ty])
return V;
const StructType *ST = cast<StructType>(Ty);
std::vector<Constant*> 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<ArrayType>(Ty);
Constant *El = Constant::getNullValue(AT->getElementType());
unsigned NumElements = AT->getNumElements();
Constant *Ret = ConstantArray::get(AT,
std::vector<Constant*>(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<ConstantExpr>(CPV));
}
bool ConstantAggregateZero::classof(const Constant *CPV) {
return (isa<ArrayType>(CPV->getType()) || isa<StructType>(CPV->getType())) &&
CPV->isNullValue();
}
bool ConstantArray::classof(const Constant *CPV) {
return isa<ArrayType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
return isa<ArrayType>(CPV->getType()) && !CPV->isNullValue();
}
bool ConstantStruct::classof(const Constant *CPV) {
return isa<StructType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
return isa<StructType>(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<class ValType>
struct ConstantCreator<ConstantAggregateZero, Type, ValType> {
static ConstantAggregateZero *create(const Type *Ty, const ValType &V){
return new ConstantAggregateZero(Ty);
}
};
template<>
struct ConvertConstantType<ConstantAggregateZero, Type> {
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<char, Type, ConstantAggregateZero> 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<std::vector<Constant*>, ArrayType,
ConstantArray> ArrayConstants;
Constant *ConstantArray::get(const ArrayType *Ty,
const std::vector<Constant*> &V) {
return ArrayConstants.getOrCreate(Ty, V);
const std::vector<Constant*> &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<std::vector<Constant*>, StructType,
Constant *ConstantStruct::get(const StructType *Ty,
const std::vector<Constant*> &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...