Switch FnSet to containing the ComparableFunction instead of a pointer to one.

This reduces malloc traffic (yay!) and removes MergeFunctionsEqualityInfo.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@113105 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Nick Lewycky
2010-09-05 09:00:32 +00:00
parent b0104e1bb5
commit b0e17779ba

View File

@@ -86,27 +86,57 @@ static unsigned ProfileFunction(const Function *F) {
class ComparableFunction { class ComparableFunction {
public: public:
static const ComparableFunction EmptyKey;
static const ComparableFunction TombstoneKey;
ComparableFunction(Function *Func, TargetData *TD) ComparableFunction(Function *Func, TargetData *TD)
: Func(Func), Hash(ProfileFunction(Func)), TD(TD) {} : Func(Func), Hash(ProfileFunction(Func)), TD(TD) {}
AssertingVH<Function> const Func; Function *getFunc() const { return Func; }
const unsigned Hash; unsigned getHash() const { return Hash; }
TargetData * const TD; TargetData *getTD() const { return TD; }
// Drops AssertingVH reference to the function. Outside of debug mode, this
// does nothing.
void release() {
assert(Func &&
"Attempted to release function twice, or release empty/tombstone!");
Func = NULL;
}
private:
explicit ComparableFunction(unsigned Hash)
: Func(NULL), Hash(Hash), TD(NULL) {}
AssertingVH<Function> Func;
unsigned Hash;
TargetData *TD;
}; };
struct MergeFunctionsEqualityInfo { const ComparableFunction ComparableFunction::EmptyKey = ComparableFunction(0);
static ComparableFunction *getEmptyKey() { const ComparableFunction ComparableFunction::TombstoneKey =
return reinterpret_cast<ComparableFunction*>(0); ComparableFunction(1);
}
static ComparableFunction *getTombstoneKey() { } // anonymous namespace
return reinterpret_cast<ComparableFunction*>(-1);
} namespace llvm {
static unsigned getHashValue(const ComparableFunction *CF) { template <>
return CF->Hash; struct DenseMapInfo<ComparableFunction> {
} static ComparableFunction getEmptyKey() {
static bool isEqual(const ComparableFunction *LHS, return ComparableFunction::EmptyKey;
const ComparableFunction *RHS); }
}; static ComparableFunction getTombstoneKey() {
return ComparableFunction::TombstoneKey;
}
static unsigned getHashValue(const ComparableFunction &CF) {
return CF.getHash();
}
static bool isEqual(const ComparableFunction &LHS,
const ComparableFunction &RHS);
};
}
namespace {
/// MergeFunctions finds functions which will generate identical machine code, /// MergeFunctions finds functions which will generate identical machine code,
/// by considering all pointer types to be equivalent. Once identified, /// by considering all pointer types to be equivalent. Once identified,
@@ -121,12 +151,12 @@ public:
bool runOnModule(Module &M); bool runOnModule(Module &M);
private: private:
typedef DenseSet<ComparableFunction *, MergeFunctionsEqualityInfo> FnSetType; typedef DenseSet<ComparableFunction> FnSetType;
/// Insert a ComparableFunction into the FnSet, or merge it away if it's /// Insert a ComparableFunction into the FnSet, or merge it away if it's
/// equal to one that's already present. /// equal to one that's already present.
bool Insert(FnSetType &FnSet, ComparableFunction *NewF); bool Insert(FnSetType &FnSet, ComparableFunction &NewF);
/// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G /// MergeTwoFunctions - Merge two equivalent functions. Upon completion, G
/// may be deleted, or may be converted into a thunk. In either case, it /// may be deleted, or may be converted into a thunk. In either case, it
@@ -602,23 +632,23 @@ void MergeFunctions::MergeTwoFunctions(Function *F, Function *G) const {
// Insert - Insert a ComparableFunction into the FnSet, or merge it away if // Insert - Insert a ComparableFunction into the FnSet, or merge it away if
// equal to one that's already inserted. // equal to one that's already inserted.
bool MergeFunctions::Insert(FnSetType &FnSet, ComparableFunction *NewF) { bool MergeFunctions::Insert(FnSetType &FnSet, ComparableFunction &NewF) {
std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF); std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF);
if (Result.second) if (Result.second)
return false; return false;
ComparableFunction *OldF = *Result.first; const ComparableFunction &OldF = *Result.first;
assert(OldF && "Expected a hash collision");
// Never thunk a strong function to a weak function. // Never thunk a strong function to a weak function.
assert(!OldF->Func->isWeakForLinker() || NewF->Func->isWeakForLinker()); assert(!OldF.getFunc()->isWeakForLinker() ||
NewF.getFunc()->isWeakForLinker());
DEBUG(dbgs() << " " << OldF->Func->getName() << " == " DEBUG(dbgs() << " " << OldF.getFunc()->getName() << " == "
<< NewF->Func->getName() << '\n'); << NewF.getFunc()->getName() << '\n');
Function *DeleteF = NewF->Func; Function *DeleteF = NewF.getFunc();
delete NewF; NewF.release();
MergeTwoFunctions(OldF->Func, DeleteF); MergeTwoFunctions(OldF.getFunc(), DeleteF);
return true; return true;
} }
@@ -701,7 +731,7 @@ bool MergeFunctions::runOnModule(Module &M) {
Function *F = I++; Function *F = I++;
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() && if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
!F->isWeakForLinker() && !IsThunk(F)) { !F->isWeakForLinker() && !IsThunk(F)) {
ComparableFunction *CF = new ComparableFunction(F, TD); ComparableFunction CF = ComparableFunction(F, TD);
LocalChanged |= Insert(FnSet, CF); LocalChanged |= Insert(FnSet, CF);
} }
} }
@@ -714,24 +744,25 @@ bool MergeFunctions::runOnModule(Module &M) {
Function *F = I++; Function *F = I++;
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() && if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
F->isWeakForLinker() && !IsThunk(F)) { F->isWeakForLinker() && !IsThunk(F)) {
ComparableFunction *CF = new ComparableFunction(F, TD); ComparableFunction CF = ComparableFunction(F, TD);
LocalChanged |= Insert(FnSet, CF); LocalChanged |= Insert(FnSet, CF);
} }
} }
DeleteContainerPointers(FnSet);
Changed |= LocalChanged; Changed |= LocalChanged;
} while (LocalChanged); } while (LocalChanged);
return Changed; return Changed;
} }
bool MergeFunctionsEqualityInfo::isEqual(const ComparableFunction *LHS, bool DenseMapInfo<ComparableFunction>::isEqual(const ComparableFunction &LHS,
const ComparableFunction *RHS) { const ComparableFunction &RHS) {
if (LHS == RHS) if (LHS.getFunc() == RHS.getFunc() &&
LHS.getHash() == RHS.getHash())
return true; return true;
if (LHS == getEmptyKey() || LHS == getTombstoneKey() || if (!LHS.getFunc() || !RHS.getFunc())
RHS == getEmptyKey() || RHS == getTombstoneKey())
return false; return false;
assert(LHS->TD == RHS->TD && "Comparing functions for different targets"); assert(LHS.getTD() == RHS.getTD() &&
return FunctionComparator(LHS->TD, LHS->Func, RHS->Func).Compare(); "Comparing functions for different targets");
return FunctionComparator(LHS.getTD(),
LHS.getFunc(), RHS.getFunc()).Compare();
} }