Efficient Constant Uniquing.

llvm-svn: 149848
This commit is contained in:
Talin 2012-02-05 20:54:10 +00:00
parent bad48a142a
commit 176069f81d
5 changed files with 201 additions and 74 deletions

View File

@ -39,6 +39,8 @@ class SequentialType;
template<class ConstantClass, class TypeClass, class ValType>
struct ConstantCreator;
template<class ConstantClass, class TypeClass>
struct ConstantArrayCreator;
template<class ConstantClass, class TypeClass>
struct ConvertConstantType;
//===----------------------------------------------------------------------===//
@ -343,8 +345,7 @@ public:
/// ConstantArray - Constant Array Declarations
///
class ConstantArray : public Constant {
friend struct ConstantCreator<ConstantArray, ArrayType,
std::vector<Constant*> >;
friend struct ConstantArrayCreator<ConstantArray, ArrayType>;
ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT
protected:
ConstantArray(ArrayType *T, ArrayRef<Constant *> Val);
@ -383,8 +384,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantArray, Constant)
// ConstantStruct - Constant Struct Declarations
//
class ConstantStruct : public Constant {
friend struct ConstantCreator<ConstantStruct, StructType,
std::vector<Constant*> >;
friend struct ConstantArrayCreator<ConstantStruct, StructType>;
ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT
protected:
ConstantStruct(StructType *T, ArrayRef<Constant *> Val);
@ -444,8 +444,7 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantStruct, Constant)
/// ConstantVector - Constant Vector Declarations
///
class ConstantVector : public Constant {
friend struct ConstantCreator<ConstantVector, VectorType,
std::vector<Constant*> >;
friend struct ConstantArrayCreator<ConstantVector, VectorType>;
ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT
protected:
ConstantVector(VectorType *T, ArrayRef<Constant *> Val);

View File

@ -2388,11 +2388,9 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
LLVMContextImpl *pImpl = getType()->getContext().pImpl;
std::pair<LLVMContextImpl::ArrayConstantsTy::MapKey, ConstantArray*> Lookup;
Lookup.first.first = cast<ArrayType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
SmallVector<Constant*, 8> Values;
LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup;
Lookup.first = cast<ArrayType>(getType());
Values.reserve(getNumOperands()); // Build replacement array.
// Fill values with the modified operands of the constant array. Also,
@ -2408,7 +2406,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
++NumUpdated;
}
Values.push_back(Val);
AllSame = Val == ToC;
AllSame &= Val == ToC;
}
Constant *Replacement = 0;
@ -2418,18 +2416,18 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Replacement = UndefValue::get(getType());
} else {
// Check to see if we have this array type already.
bool Exists;
Lookup.second = makeArrayRef(Values);
LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
pImpl->ArrayConstants.InsertOrGetItem(Lookup, Exists);
pImpl->ArrayConstants.find(Lookup);
if (Exists) {
Replacement = I->second;
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.MoveConstantToNewSlot(this, I);
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.
@ -2443,6 +2441,7 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
if (getOperand(i) == From)
setOperand(i, ToC);
}
pImpl->ArrayConstants.insert(this);
return;
}
}
@ -2465,13 +2464,11 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
unsigned OperandToUpdate = U-OperandList;
assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
std::pair<LLVMContextImpl::StructConstantsTy::MapKey, ConstantStruct*> Lookup;
Lookup.first.first = cast<StructType>(getType());
Lookup.second = this;
std::vector<Constant*> &Values = Lookup.first.second;
SmallVector<Constant*, 8> Values;
LLVMContextImpl::StructConstantsTy::LookupKey Lookup;
Lookup.first = cast<StructType>(getType());
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;
@ -2505,21 +2502,22 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
Replacement = UndefValue::get(getType());
} else {
// Check to see if we have this struct type already.
bool Exists;
Lookup.second = makeArrayRef(Values);
LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
pImpl->StructConstants.InsertOrGetItem(Lookup, Exists);
pImpl->StructConstants.find(Lookup);
if (Exists) {
Replacement = I->second;
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.MoveConstantToNewSlot(this, I);
pImpl->StructConstants.remove(this);
// Update to the new value.
setOperand(OperandToUpdate, ToC);
pImpl->StructConstants.insert(this);
return;
}
}

View File

@ -15,6 +15,7 @@
#ifndef LLVM_CONSTANTSCONTEXT_H
#define LLVM_CONSTANTSCONTEXT_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/InlineAsm.h"
#include "llvm/Instructions.h"
#include "llvm/Operator.h"
@ -408,6 +409,13 @@ struct ConstantCreator {
}
};
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 ConstantKeyData {
typedef void ValType;
@ -477,44 +485,6 @@ struct ConstantKeyData<ConstantExpr> {
}
};
template<>
struct ConstantKeyData<ConstantVector> {
typedef std::vector<Constant*> ValType;
static ValType getValType(ConstantVector *CP) {
std::vector<Constant*> Elements;
Elements.reserve(CP->getNumOperands());
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
Elements.push_back(CP->getOperand(i));
return Elements;
}
};
template<>
struct ConstantKeyData<ConstantArray> {
typedef std::vector<Constant*> ValType;
static ValType getValType(ConstantArray *CA) {
std::vector<Constant*> Elements;
Elements.reserve(CA->getNumOperands());
for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
Elements.push_back(cast<Constant>(CA->getOperand(i)));
return Elements;
}
};
template<>
struct ConstantKeyData<ConstantStruct> {
typedef std::vector<Constant*> ValType;
static ValType getValType(ConstantStruct *CS) {
std::vector<Constant*> Elements;
Elements.reserve(CS->getNumOperands());
for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
Elements.push_back(cast<Constant>(CS->getOperand(i)));
return Elements;
}
};
template<>
struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> {
static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) {
@ -668,6 +638,159 @@ public:
}
};
// 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;
typedef DenseMapInfo<Constant*> ConstantInfo;
typedef DenseMapInfo<TypeClass*> TypeClassInfo;
static inline ConstantClass* getEmptyKey() {
return ConstantClassInfo::getEmptyKey();
}
static inline ConstantClass* getTombstoneKey() {
return ConstantClassInfo::getTombstoneKey();
}
static unsigned getHashValue(const ConstantClass *CP) {
// This is adapted from SuperFastHash by Paul Hsieh.
unsigned Hash = TypeClassInfo::getHashValue(CP->getType());
for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I) {
unsigned Data = ConstantInfo::getHashValue(CP->getOperand(I));
Hash += Data & 0xFFFF;
unsigned Tmp = ((Data >> 16) << 11) ^ Hash;
Hash = (Hash << 16) ^ Tmp;
Hash += Hash >> 11;
}
// Force "avalanching" of final 127 bits.
Hash ^= Hash << 3;
Hash += Hash >> 5;
Hash ^= Hash << 4;
Hash += Hash >> 17;
Hash ^= Hash << 25;
Hash += Hash >> 6;
return Hash;
}
static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
return LHS == RHS;
}
static unsigned getHashValue(const LookupKey &Val) {
// This is adapted from SuperFastHash by Paul Hsieh.
unsigned Hash = TypeClassInfo::getHashValue(Val.first);
for (Operands::const_iterator
I = Val.second.begin(), E = Val.second.end(); I != E; ++I) {
unsigned Data = ConstantInfo::getHashValue(*I);
Hash += Data & 0xFFFF;
unsigned Tmp = ((Data >> 16) << 11) ^ Hash;
Hash = (Hash << 16) ^ Tmp;
Hash += Hash >> 11;
}
// Force "avalanching" of final 127 bits.
Hash ^= Hash << 3;
Hash += Hash >> 5;
Hash ^= Hash << 4;
Hash += Hash >> 17;
Hash ^= Hash << 25;
Hash += Hash >> 6;
return Hash;
}
static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false;
if (LHS.first != RHS->getType()
|| LHS.second.size() != RHS->getNumOperands())
return false;
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:
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->first;
}
}
private:
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!");
Map[Result] = '\0';
return Result;
}
public:
/// getOrCreate - Return the specified constant from the map, creating it if
/// necessary.
ConstantClass *getOrCreate(TypeClass *Ty, Operands V) {
LookupKey Lookup(Ty, V);
ConstantClass* Result = 0;
typename MapTy::iterator I = Map.find_as(Lookup);
// Is it in the map?
if (I != Map.end())
Result = I->first;
if (!Result) {
// If no preexisting value, create one now...
Result = Create(Ty, V, I);
}
return Result;
}
/// Find the constant by lookup key.
typename MapTy::iterator find(LookupKey Lookup) {
return Map.find_as(Lookup);
}
/// Insert the constant into its proper slot.
void insert(ConstantClass *CP) {
Map[CP] = '\0';
}
/// Remove this constant from the map
void remove(ConstantClass *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");
}
};
}
#endif

View File

@ -48,6 +48,16 @@ struct DropReferences {
P.second->dropAllReferences();
}
};
// Temporary - drops pair.first instead of second.
struct DropFirst {
// Takes the value_type of a ConstantUniqueMap's internal map, whose 'second'
// is a Constant*.
template<typename PairT>
void operator()(const PairT &P) {
P.first->dropAllReferences();
}
};
}
LLVMContextImpl::~LLVMContextImpl() {
@ -63,11 +73,11 @@ LLVMContextImpl::~LLVMContextImpl() {
std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
DropReferences());
std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(),
DropReferences());
DropFirst());
std::for_each(StructConstants.map_begin(), StructConstants.map_end(),
DropReferences());
DropFirst());
std::for_each(VectorConstants.map_begin(), VectorConstants.map_end(),
DropReferences());
DropFirst());
ExprConstants.freeConstants();
ArrayConstants.freeConstants();
StructConstants.freeConstants();

View File

@ -140,16 +140,13 @@ public:
DenseMap<Type*, ConstantAggregateZero*> CAZConstants;
typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
ArrayType, ConstantArray, true /*largekey*/> ArrayConstantsTy;
typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy;
ArrayConstantsTy ArrayConstants;
typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
StructType, ConstantStruct, true /*largekey*/> StructConstantsTy;
typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy;
StructConstantsTy StructConstants;
typedef ConstantUniqueMap<std::vector<Constant*>, ArrayRef<Constant*>,
VectorType, ConstantVector> VectorConstantsTy;
typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy;
VectorConstantsTy VectorConstants;
DenseMap<PointerType*, ConstantPointerNull*> CPNConstants;