mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-09 10:31:14 +00:00
MergeFunctions Pass, introduced total ordering among top-level comparison
methods. Patch changes return type of FunctionComparator::compare() and FunctionComparator::compare(const BasicBlock*, const BasicBlock*) methods from bool (equal or not) to {-1, 0, 1} (less, equal, great). 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@211437 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6b7ff6be9c
commit
23a7bfce97
@ -167,14 +167,14 @@ class FunctionComparator {
|
|||||||
public:
|
public:
|
||||||
FunctionComparator(const DataLayout *DL, const Function *F1,
|
FunctionComparator(const DataLayout *DL, const Function *F1,
|
||||||
const Function *F2)
|
const Function *F2)
|
||||||
: F1(F1), F2(F2), DL(DL) {}
|
: FnL(F1), FnR(F2), DL(DL) {}
|
||||||
|
|
||||||
/// Test whether the two functions have equivalent behaviour.
|
/// Test whether the two functions have equivalent behaviour.
|
||||||
bool compare();
|
int compare();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Test whether two basic blocks have equivalent behaviour.
|
/// Test whether two basic blocks have equivalent behaviour.
|
||||||
bool compare(const BasicBlock *BB1, const BasicBlock *BB2);
|
int compare(const BasicBlock *BBL, const BasicBlock *BBR);
|
||||||
|
|
||||||
/// Constants comparison.
|
/// Constants comparison.
|
||||||
/// Its analog to lexicographical comparison between hypothetical numbers
|
/// Its analog to lexicographical comparison between hypothetical numbers
|
||||||
@ -411,7 +411,7 @@ private:
|
|||||||
int cmpAttrs(const AttributeSet L, const AttributeSet R) const;
|
int cmpAttrs(const AttributeSet L, const AttributeSet R) const;
|
||||||
|
|
||||||
// The two functions undergoing comparison.
|
// The two functions undergoing comparison.
|
||||||
const Function *F1, *F2;
|
const Function *FnL, *FnR;
|
||||||
|
|
||||||
const DataLayout *DL;
|
const DataLayout *DL;
|
||||||
|
|
||||||
@ -922,13 +922,13 @@ int FunctionComparator::cmpGEP(const GEPOperator *GEPL,
|
|||||||
/// See comments in declaration for more details.
|
/// See comments in declaration for more details.
|
||||||
int FunctionComparator::cmpValues(const Value *L, const Value *R) {
|
int FunctionComparator::cmpValues(const Value *L, const Value *R) {
|
||||||
// Catch self-reference case.
|
// Catch self-reference case.
|
||||||
if (L == F1) {
|
if (L == FnL) {
|
||||||
if (R == F2)
|
if (R == FnR)
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (R == F2) {
|
if (R == FnR) {
|
||||||
if (L == F1)
|
if (L == FnL)
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -962,90 +962,102 @@ int FunctionComparator::cmpValues(const Value *L, const Value *R) {
|
|||||||
return cmpNumbers(LeftSN.first->second, RightSN.first->second);
|
return cmpNumbers(LeftSN.first->second, RightSN.first->second);
|
||||||
}
|
}
|
||||||
// Test whether two basic blocks have equivalent behaviour.
|
// Test whether two basic blocks have equivalent behaviour.
|
||||||
bool FunctionComparator::compare(const BasicBlock *BB1, const BasicBlock *BB2) {
|
int FunctionComparator::compare(const BasicBlock *BBL, const BasicBlock *BBR) {
|
||||||
BasicBlock::const_iterator F1I = BB1->begin(), F1E = BB1->end();
|
BasicBlock::const_iterator InstL = BBL->begin(), InstLE = BBL->end();
|
||||||
BasicBlock::const_iterator F2I = BB2->begin(), F2E = BB2->end();
|
BasicBlock::const_iterator InstR = BBR->begin(), InstRE = BBR->end();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!enumerate(F1I, F2I))
|
if (int Res = cmpValues(InstL, InstR))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
if (const GetElementPtrInst *GEP1 = dyn_cast<GetElementPtrInst>(F1I)) {
|
const GetElementPtrInst *GEPL = dyn_cast<GetElementPtrInst>(InstL);
|
||||||
const GetElementPtrInst *GEP2 = dyn_cast<GetElementPtrInst>(F2I);
|
const GetElementPtrInst *GEPR = dyn_cast<GetElementPtrInst>(InstR);
|
||||||
if (!GEP2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!enumerate(GEP1->getPointerOperand(), GEP2->getPointerOperand()))
|
if (GEPL && !GEPR)
|
||||||
return false;
|
return 1;
|
||||||
|
if (GEPR && !GEPL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (!isEquivalentGEP(GEP1, GEP2))
|
if (GEPL && GEPR) {
|
||||||
return false;
|
if (int Res =
|
||||||
|
cmpValues(GEPL->getPointerOperand(), GEPR->getPointerOperand()))
|
||||||
|
return Res;
|
||||||
|
if (int Res = cmpGEP(GEPL, GEPR))
|
||||||
|
return Res;
|
||||||
} else {
|
} else {
|
||||||
if (!isEquivalentOperation(F1I, F2I))
|
if (int Res = cmpOperation(InstL, InstR))
|
||||||
return false;
|
return Res;
|
||||||
|
assert(InstL->getNumOperands() == InstR->getNumOperands());
|
||||||
|
|
||||||
assert(F1I->getNumOperands() == F2I->getNumOperands());
|
for (unsigned i = 0, e = InstL->getNumOperands(); i != e; ++i) {
|
||||||
for (unsigned i = 0, e = F1I->getNumOperands(); i != e; ++i) {
|
Value *OpL = InstL->getOperand(i);
|
||||||
Value *OpF1 = F1I->getOperand(i);
|
Value *OpR = InstR->getOperand(i);
|
||||||
Value *OpF2 = F2I->getOperand(i);
|
if (int Res = cmpValues(OpL, OpR))
|
||||||
|
return Res;
|
||||||
if (!enumerate(OpF1, OpF2))
|
if (int Res = cmpNumbers(OpL->getValueID(), OpR->getValueID()))
|
||||||
return false;
|
return Res;
|
||||||
|
// TODO: Already checked in cmpOperation
|
||||||
if (OpF1->getValueID() != OpF2->getValueID() ||
|
if (int Res = cmpType(OpL->getType(), OpR->getType()))
|
||||||
!isEquivalentType(OpF1->getType(), OpF2->getType()))
|
return Res;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++F1I, ++F2I;
|
++InstL, ++InstR;
|
||||||
} while (F1I != F1E && F2I != F2E);
|
} while (InstL != InstLE && InstR != InstRE);
|
||||||
|
|
||||||
return F1I == F1E && F2I == F2E;
|
if (InstL != InstLE && InstR == InstRE)
|
||||||
|
return 1;
|
||||||
|
if (InstL == InstLE && InstR != InstRE)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test whether the two functions have equivalent behaviour.
|
// Test whether the two functions have equivalent behaviour.
|
||||||
bool FunctionComparator::compare() {
|
int FunctionComparator::compare() {
|
||||||
// We need to recheck everything, but check the things that weren't included
|
|
||||||
// in the hash first.
|
|
||||||
|
|
||||||
sn_mapL.clear();
|
sn_mapL.clear();
|
||||||
sn_mapR.clear();
|
sn_mapR.clear();
|
||||||
|
|
||||||
if (F1->getAttributes() != F2->getAttributes())
|
if (int Res = cmpAttrs(FnL->getAttributes(), FnR->getAttributes()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
if (F1->hasGC() != F2->hasGC())
|
if (int Res = cmpNumbers(FnL->hasGC(), FnR->hasGC()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
if (F1->hasGC() && F1->getGC() != F2->getGC())
|
if (FnL->hasGC()) {
|
||||||
return false;
|
if (int Res = cmpNumbers((uint64_t)FnL->getGC(), (uint64_t)FnR->getGC()))
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
if (F1->hasSection() != F2->hasSection())
|
if (int Res = cmpNumbers(FnL->hasSection(), FnR->hasSection()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
if (F1->hasSection() && F1->getSection() != F2->getSection())
|
if (FnL->hasSection()) {
|
||||||
return false;
|
if (int Res = cmpStrings(FnL->getSection(), FnR->getSection()))
|
||||||
|
return Res;
|
||||||
|
}
|
||||||
|
|
||||||
if (F1->isVarArg() != F2->isVarArg())
|
if (int Res = cmpNumbers(FnL->isVarArg(), FnR->isVarArg()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
// TODO: if it's internal and only used in direct calls, we could handle this
|
// TODO: if it's internal and only used in direct calls, we could handle this
|
||||||
// case too.
|
// case too.
|
||||||
if (F1->getCallingConv() != F2->getCallingConv())
|
if (int Res = cmpNumbers(FnL->getCallingConv(), FnR->getCallingConv()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
if (!isEquivalentType(F1->getFunctionType(), F2->getFunctionType()))
|
if (int Res = cmpType(FnL->getFunctionType(), FnR->getFunctionType()))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
assert(F1->arg_size() == F2->arg_size() &&
|
assert(FnL->arg_size() == FnR->arg_size() &&
|
||||||
"Identically typed functions have different numbers of args!");
|
"Identically typed functions have different numbers of args!");
|
||||||
|
|
||||||
// Visit the arguments so that they get enumerated in the order they're
|
// Visit the arguments so that they get enumerated in the order they're
|
||||||
// passed in.
|
// passed in.
|
||||||
for (Function::const_arg_iterator f1i = F1->arg_begin(),
|
for (Function::const_arg_iterator ArgLI = FnL->arg_begin(),
|
||||||
f2i = F2->arg_begin(), f1e = F1->arg_end(); f1i != f1e; ++f1i, ++f2i) {
|
ArgRI = FnR->arg_begin(),
|
||||||
if (!enumerate(f1i, f2i))
|
ArgLE = FnL->arg_end();
|
||||||
|
ArgLI != ArgLE; ++ArgLI, ++ArgRI) {
|
||||||
|
if (cmpValues(ArgLI, ArgRI) != 0)
|
||||||
llvm_unreachable("Arguments repeat!");
|
llvm_unreachable("Arguments repeat!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,33 +1065,36 @@ bool FunctionComparator::compare() {
|
|||||||
// linked list is immaterial. Our walk starts at the entry block for both
|
// linked list is immaterial. Our walk starts at the entry block for both
|
||||||
// functions, then takes each block from each terminator in order. As an
|
// functions, then takes each block from each terminator in order. As an
|
||||||
// artifact, this also means that unreachable blocks are ignored.
|
// artifact, this also means that unreachable blocks are ignored.
|
||||||
SmallVector<const BasicBlock *, 8> F1BBs, F2BBs;
|
SmallVector<const BasicBlock *, 8> FnLBBs, FnRBBs;
|
||||||
SmallSet<const BasicBlock *, 128> VisitedBBs; // in terms of F1.
|
SmallSet<const BasicBlock *, 128> VisitedBBs; // in terms of F1.
|
||||||
|
|
||||||
F1BBs.push_back(&F1->getEntryBlock());
|
FnLBBs.push_back(&FnL->getEntryBlock());
|
||||||
F2BBs.push_back(&F2->getEntryBlock());
|
FnRBBs.push_back(&FnR->getEntryBlock());
|
||||||
|
|
||||||
VisitedBBs.insert(F1BBs[0]);
|
VisitedBBs.insert(FnLBBs[0]);
|
||||||
while (!F1BBs.empty()) {
|
while (!FnLBBs.empty()) {
|
||||||
const BasicBlock *F1BB = F1BBs.pop_back_val();
|
const BasicBlock *BBL = FnLBBs.pop_back_val();
|
||||||
const BasicBlock *F2BB = F2BBs.pop_back_val();
|
const BasicBlock *BBR = FnRBBs.pop_back_val();
|
||||||
|
|
||||||
if (!enumerate(F1BB, F2BB) || !compare(F1BB, F2BB))
|
if (int Res = cmpValues(BBL, BBR))
|
||||||
return false;
|
return Res;
|
||||||
|
|
||||||
const TerminatorInst *F1TI = F1BB->getTerminator();
|
if (int Res = compare(BBL, BBR))
|
||||||
const TerminatorInst *F2TI = F2BB->getTerminator();
|
return Res;
|
||||||
|
|
||||||
assert(F1TI->getNumSuccessors() == F2TI->getNumSuccessors());
|
const TerminatorInst *TermL = BBL->getTerminator();
|
||||||
for (unsigned i = 0, e = F1TI->getNumSuccessors(); i != e; ++i) {
|
const TerminatorInst *TermR = BBR->getTerminator();
|
||||||
if (!VisitedBBs.insert(F1TI->getSuccessor(i)))
|
|
||||||
|
assert(TermL->getNumSuccessors() == TermR->getNumSuccessors());
|
||||||
|
for (unsigned i = 0, e = TermL->getNumSuccessors(); i != e; ++i) {
|
||||||
|
if (!VisitedBBs.insert(TermL->getSuccessor(i)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
F1BBs.push_back(F1TI->getSuccessor(i));
|
FnLBBs.push_back(TermL->getSuccessor(i));
|
||||||
F2BBs.push_back(F2TI->getSuccessor(i));
|
FnRBBs.push_back(TermR->getSuccessor(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -1226,8 +1241,8 @@ bool DenseMapInfo<ComparableFunction>::isEqual(const ComparableFunction &LHS,
|
|||||||
assert(LHS.getDataLayout() == RHS.getDataLayout() &&
|
assert(LHS.getDataLayout() == RHS.getDataLayout() &&
|
||||||
"Comparing functions for different targets");
|
"Comparing functions for different targets");
|
||||||
|
|
||||||
return FunctionComparator(LHS.getDataLayout(), LHS.getFunc(),
|
return FunctionComparator(LHS.getDataLayout(), LHS.getFunc(), RHS.getFunc())
|
||||||
RHS.getFunc()).compare();
|
.compare() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace direct callers of Old with New.
|
// Replace direct callers of Old with New.
|
||||||
|
Loading…
Reference in New Issue
Block a user