mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-10 02:36:06 +00:00
MergeFunctions Pass, FnSet has been replaced with FnTree.
Patch activates new implementation. So from now, merging process should take time O(N*log(N)). Where N size of module (we are free to measure it in functions or in instructions). Internally FnTree represents binary tree. So every lookup operation takes O(log(N)) time. It is still not the last patch in series, we also have to clean-up pass from old code, and update pass comments. This patch belongs to patch series that improves MergeFunctions performance time from O(N*N) to O(N*log(N)). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211445 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
83ac8b35e9
commit
427afb91d3
@ -438,6 +438,18 @@ private:
|
|||||||
DenseMap<const Value*, int> sn_mapL, sn_mapR;
|
DenseMap<const Value*, int> sn_mapL, sn_mapR;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FunctionPtr {
|
||||||
|
AssertingVH<Function> F;
|
||||||
|
const DataLayout *DL;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FunctionPtr(Function *F, const DataLayout *DL) : F(F), DL(DL) {}
|
||||||
|
Function *getFunc() const { return F; }
|
||||||
|
void release() { F = 0; }
|
||||||
|
bool operator<(const FunctionPtr &RHS) const {
|
||||||
|
return (FunctionComparator(DL, F, RHS.getFunc()).compare()) == -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
int FunctionComparator::cmpNumbers(uint64_t L, uint64_t R) const {
|
int FunctionComparator::cmpNumbers(uint64_t L, uint64_t R) const {
|
||||||
@ -1102,7 +1114,7 @@ public:
|
|||||||
bool runOnModule(Module &M) override;
|
bool runOnModule(Module &M) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef DenseSet<ComparableFunction> FnSetType;
|
typedef std::set<FunctionPtr> FnTreeType;
|
||||||
|
|
||||||
/// A work queue of functions that may have been modified and should be
|
/// A work queue of functions that may have been modified and should be
|
||||||
/// analyzed again.
|
/// analyzed again.
|
||||||
@ -1112,15 +1124,15 @@ private:
|
|||||||
/// Returns true, if sanity check has been passed, and false if failed.
|
/// Returns true, if sanity check has been passed, and false if failed.
|
||||||
bool doSanityCheck(std::vector<WeakVH> &Worklist);
|
bool doSanityCheck(std::vector<WeakVH> &Worklist);
|
||||||
|
|
||||||
/// Insert a ComparableFunction into the FnSet, or merge it away if it's
|
/// Insert a ComparableFunction into the FnTree, or merge it away if it's
|
||||||
/// equal to one that's already present.
|
/// equal to one that's already present.
|
||||||
bool insert(ComparableFunction &NewF);
|
bool insert(Function *NewFunction);
|
||||||
|
|
||||||
/// Remove a Function from the FnSet and queue it up for a second sweep of
|
/// Remove a Function from the FnTree and queue it up for a second sweep of
|
||||||
/// analysis.
|
/// analysis.
|
||||||
void remove(Function *F);
|
void remove(Function *F);
|
||||||
|
|
||||||
/// Find the functions that use this Value and remove them from FnSet and
|
/// Find the functions that use this Value and remove them from FnTree and
|
||||||
/// queue the functions.
|
/// queue the functions.
|
||||||
void removeUsers(Value *V);
|
void removeUsers(Value *V);
|
||||||
|
|
||||||
@ -1145,7 +1157,7 @@ private:
|
|||||||
|
|
||||||
/// The set of all distinct functions. Use the insert() and remove() methods
|
/// The set of all distinct functions. Use the insert() and remove() methods
|
||||||
/// to modify it.
|
/// to modify it.
|
||||||
FnSetType FnSet;
|
FnTreeType FnTree;
|
||||||
|
|
||||||
/// DataLayout for more accurate GEP comparisons. May be NULL.
|
/// DataLayout for more accurate GEP comparisons. May be NULL.
|
||||||
const DataLayout *DL;
|
const DataLayout *DL;
|
||||||
@ -1244,7 +1256,6 @@ bool MergeFunctions::runOnModule(Module &M) {
|
|||||||
if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage())
|
if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage())
|
||||||
Deferred.push_back(WeakVH(I));
|
Deferred.push_back(WeakVH(I));
|
||||||
}
|
}
|
||||||
FnSet.resize(Deferred.size());
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
std::vector<WeakVH> Worklist;
|
std::vector<WeakVH> Worklist;
|
||||||
@ -1263,8 +1274,7 @@ bool MergeFunctions::runOnModule(Module &M) {
|
|||||||
Function *F = cast<Function>(*I);
|
Function *F = cast<Function>(*I);
|
||||||
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
|
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
|
||||||
!F->mayBeOverridden()) {
|
!F->mayBeOverridden()) {
|
||||||
ComparableFunction CF = ComparableFunction(F, DL);
|
Changed |= insert(F);
|
||||||
Changed |= insert(CF);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1278,14 +1288,13 @@ bool MergeFunctions::runOnModule(Module &M) {
|
|||||||
Function *F = cast<Function>(*I);
|
Function *F = cast<Function>(*I);
|
||||||
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
|
if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage() &&
|
||||||
F->mayBeOverridden()) {
|
F->mayBeOverridden()) {
|
||||||
ComparableFunction CF = ComparableFunction(F, DL);
|
Changed |= insert(F);
|
||||||
Changed |= insert(CF);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DEBUG(dbgs() << "size of FnSet: " << FnSet.size() << '\n');
|
DEBUG(dbgs() << "size of FnTree: " << FnTree.size() << '\n');
|
||||||
} while (!Deferred.empty());
|
} while (!Deferred.empty());
|
||||||
|
|
||||||
FnSet.clear();
|
FnTree.clear();
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
@ -1464,54 +1473,57 @@ void MergeFunctions::mergeTwoFunctions(Function *F, Function *G) {
|
|||||||
++NumFunctionsMerged;
|
++NumFunctionsMerged;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a ComparableFunction into the FnSet, or merge it away if equal to one
|
// Insert a ComparableFunction into the FnTree, or merge it away if equal to one
|
||||||
// that was already inserted.
|
// that was already inserted.
|
||||||
bool MergeFunctions::insert(ComparableFunction &NewF) {
|
bool MergeFunctions::insert(Function *NewFunction) {
|
||||||
std::pair<FnSetType::iterator, bool> Result = FnSet.insert(NewF);
|
std::pair<FnTreeType::iterator, bool> Result =
|
||||||
|
FnTree.insert(FunctionPtr(NewFunction, DL));
|
||||||
|
|
||||||
if (Result.second) {
|
if (Result.second) {
|
||||||
DEBUG(dbgs() << "Inserting as unique: " << NewF.getFunc()->getName() << '\n');
|
DEBUG(dbgs() << "Inserting as unique: " << NewFunction->getName() << '\n');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ComparableFunction &OldF = *Result.first;
|
const FunctionPtr &OldF = *Result.first;
|
||||||
|
|
||||||
// Don't merge tiny functions, since it can just end up making the function
|
// Don't merge tiny functions, since it can just end up making the function
|
||||||
// larger.
|
// larger.
|
||||||
// FIXME: Should still merge them if they are unnamed_addr and produce an
|
// FIXME: Should still merge them if they are unnamed_addr and produce an
|
||||||
// alias.
|
// alias.
|
||||||
if (NewF.getFunc()->size() == 1) {
|
if (NewFunction->size() == 1) {
|
||||||
if (NewF.getFunc()->front().size() <= 2) {
|
if (NewFunction->front().size() <= 2) {
|
||||||
DEBUG(dbgs() << NewF.getFunc()->getName()
|
DEBUG(dbgs() << NewFunction->getName()
|
||||||
<< " is to small to bother merging\n");
|
<< " is to small to bother merging\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Never thunk a strong function to a weak function.
|
// Never thunk a strong function to a weak function.
|
||||||
assert(!OldF.getFunc()->mayBeOverridden() ||
|
assert(!OldF.getFunc()->mayBeOverridden() || NewFunction->mayBeOverridden());
|
||||||
NewF.getFunc()->mayBeOverridden());
|
|
||||||
|
|
||||||
DEBUG(dbgs() << " " << OldF.getFunc()->getName() << " == "
|
DEBUG(dbgs() << " " << OldF.getFunc()->getName()
|
||||||
<< NewF.getFunc()->getName() << '\n');
|
<< " == " << NewFunction->getName() << '\n');
|
||||||
|
|
||||||
Function *DeleteF = NewF.getFunc();
|
Function *DeleteF = NewFunction;
|
||||||
NewF.release();
|
|
||||||
mergeTwoFunctions(OldF.getFunc(), DeleteF);
|
mergeTwoFunctions(OldF.getFunc(), DeleteF);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove a function from FnSet. If it was already in FnSet, add it to Deferred
|
// Remove a function from FnTree. If it was already in FnTree, add
|
||||||
// so that we'll look at it in the next round.
|
// it to Deferred so that we'll look at it in the next round.
|
||||||
void MergeFunctions::remove(Function *F) {
|
void MergeFunctions::remove(Function *F) {
|
||||||
// We need to make sure we remove F, not a function "equal" to F per the
|
// We need to make sure we remove F, not a function "equal" to F per the
|
||||||
// function equality comparator.
|
// function equality comparator.
|
||||||
//
|
FnTreeType::iterator found = FnTree.find(FunctionPtr(F, DL));
|
||||||
// The special "lookup only" ComparableFunction bypasses the expensive
|
size_t Erased = 0;
|
||||||
// function comparison in favour of a pointer comparison on the underlying
|
if (found != FnTree.end() && found->getFunc() == F) {
|
||||||
// Function*'s.
|
Erased = 1;
|
||||||
ComparableFunction CF = ComparableFunction(F, ComparableFunction::LookupOnly);
|
FnTree.erase(found);
|
||||||
if (FnSet.erase(CF)) {
|
}
|
||||||
DEBUG(dbgs() << "Removed " << F->getName() << " from set and deferred it.\n");
|
|
||||||
|
if (Erased) {
|
||||||
|
DEBUG(dbgs() << "Removed " << F->getName()
|
||||||
|
<< " from set and deferred it.\n");
|
||||||
Deferred.push_back(F);
|
Deferred.push_back(F);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user