1
0
mirror of https://github.com/c64scene-ar/llvm-6502.git synced 2025-03-25 16:30:05 +00:00

Implement optimizations for handling large basic blocks.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11126 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2004-02-05 00:36:43 +00:00
parent 14be64018f
commit adf9b90411

@ -212,47 +212,95 @@ static bool CheckForInvalidatingInst(BasicBlock *BB, BasicBlock *DestBB,
bool LoadVN::haveEqualValueNumber(LoadInst *L1, LoadInst *L2,
AliasAnalysis &AA,
DominatorSet &DomSetInfo) const {
// Figure out which load dominates the other one. If neither dominates the
// other we cannot eliminate them.
//
// FIXME: This could be enhanced to some cases with a shared dominator!
//
if (DomSetInfo.dominates(L2, L1))
std::swap(L1, L2); // Make L1 dominate L2
else if (!DomSetInfo.dominates(L1, L2))
return false; // Neither instruction dominates the other one...
BasicBlock *BB1 = L1->getParent(), *BB2 = L2->getParent();
Value *LoadAddress = L1->getOperand(0);
assert(L1 != L2 && "haveEqualValueNumber assumes differing loads!");
assert(L1->getType() == L2->getType() &&
"How could the same source pointer return different types?");
Value *LoadAddress = L1->getOperand(0);
// Find out how many bytes of memory are loaded by the load instruction...
unsigned LoadSize = getAnalysis<TargetData>().getTypeSize(L1->getType());
// L1 now dominates L2. Check to see if the intervening instructions between
// the two loads include a store or call...
//
if (BB1 == BB2) { // In same basic block?
// In this degenerate case, no checking of global basic blocks has to occur
// just check the instructions BETWEEN L1 & L2...
//
if (AA.canInstructionRangeModify(*L1, *L2, LoadAddress, LoadSize))
return false; // Cannot eliminate load
// If the two loads are in the same basic block, just do a local analysis.
if (L1->getParent() == L2->getParent()) {
// It can be _very_ expensive to determine which instruction occurs first in
// the basic block if the block is large (see PR209). For this reason,
// instead of figuring out which block is first, then scanning all of the
// instructions, we scan the instructions both ways from L1 until we find
// L2. Along the way if we find a potentially modifying instruction, we
// kill the search. This helps in cases where we have large blocks the have
// potentially modifying instructions in them which stop the search.
// No instructions invalidate the loads, they produce the same value!
return true;
BasicBlock *BB = L1->getParent();
BasicBlock::iterator UpIt = L1, DownIt = L1; ++DownIt;
bool NoModifiesUp = true, NoModifiesDown = true;
// Scan up and down looking for L2, a modifying instruction, or the end of a
// basic block.
while (UpIt != BB->begin() && DownIt != BB->end()) {
// Scan up...
--UpIt;
if (&*UpIt == L2)
return NoModifiesUp; // No instructions invalidate the loads!
if (NoModifiesUp)
NoModifiesUp &=
!(AA.getModRefInfo(UpIt, LoadAddress, LoadSize) & AliasAnalysis::Mod);
if (&*DownIt == L2)
return NoModifiesDown;
if (NoModifiesDown)
NoModifiesDown &=
!(AA.getModRefInfo(DownIt, LoadAddress, LoadSize)
& AliasAnalysis::Mod);
++DownIt;
}
// If we got here, we ran into one end of the basic block or the other.
if (UpIt != BB->begin()) {
// If we know that the upward scan found a modifier, return false.
if (!NoModifiesUp) return false;
// Otherwise, continue the scan looking for a modifier or L2.
for (--UpIt; &*UpIt != L2; --UpIt)
if (AA.getModRefInfo(UpIt, LoadAddress, LoadSize) & AliasAnalysis::Mod)
return false;
return true;
} else {
// If we know that the downward scan found a modifier, return false.
assert(DownIt != B->end() && "Didn't find instructions??");
if (!NoModifiesDown) return false;
// Otherwise, continue the scan looking for a modifier or L2.
for (; &*DownIt != L2; ++DownIt) {
if (AA.getModRefInfo(DownIt, LoadAddress, LoadSize) &AliasAnalysis::Mod)
return false;
}
return true;
}
} else {
// Make sure that there are no store instructions between L1 and the end of
// its basic block...
// Figure out which load dominates the other one. If neither dominates the
// other we cannot eliminate them.
//
// FIXME: This could be enhanced greatly!
//
if (DomSetInfo.dominates(L2, L1))
std::swap(L1, L2); // Make L1 dominate L2
else if (!DomSetInfo.dominates(L1, L2))
return false; // Neither instruction dominates the other one...
BasicBlock *BB1 = L1->getParent(), *BB2 = L2->getParent();
// L1 now dominates L2. Check to see if the intervening instructions
// between the two loads might modify the loaded location.
// Make sure that there are no modifying instructions between L1 and the end
// of its basic block.
//
if (AA.canInstructionRangeModify(*L1, *BB1->getTerminator(), LoadAddress,
LoadSize))
return false; // Cannot eliminate load
// Make sure that there are no store instructions between the start of BB2
// and the second load instruction...
// Make sure that there are no modifying instructions between the start of
// BB2 and the second load instruction.
//
if (AA.canInstructionRangeModify(BB2->front(), *L2, LoadAddress, LoadSize))
return false; // Cannot eliminate load
@ -266,7 +314,7 @@ bool LoadVN::haveEqualValueNumber(LoadInst *L1, LoadInst *L2,
if (CheckForInvalidatingInst(*PI, BB1, LoadAddress, LoadSize, AA,
VisitedSet))
return false;
// If we passed all of these checks then we are sure that the two loads
// produce the same value.
return true;