mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-26 21:00:29 +00:00
Efficient Constant Uniquing.
llvm-svn: 149848
This commit is contained in:
parent
bad48a142a
commit
176069f81d
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user