[llvm-commits] CVS: llvm/lib/Analysis/LoadValueNumbering.cpp
Chris Lattner
lattner at cs.uiuc.edu
Wed Feb 4 18:37:08 PST 2004
Changes in directory llvm/lib/Analysis:
LoadValueNumbering.cpp updated: 1.10 -> 1.11
---
Log message:
Implement optimizations for handling large basic blocks.
---
Diffs of the changes: (+77 -29)
Index: llvm/lib/Analysis/LoadValueNumbering.cpp
diff -u llvm/lib/Analysis/LoadValueNumbering.cpp:1.10 llvm/lib/Analysis/LoadValueNumbering.cpp:1.11
--- llvm/lib/Analysis/LoadValueNumbering.cpp:1.10 Tue Nov 11 16:41:31 2003
+++ llvm/lib/Analysis/LoadValueNumbering.cpp Wed Feb 4 18:36:43 2004
@@ -212,47 +212,95 @@
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 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.
+
+ 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 {
+ // Figure out which load dominates the other one. If neither dominates the
+ // other we cannot eliminate them.
//
- if (AA.canInstructionRangeModify(*L1, *L2, LoadAddress, LoadSize))
- return false; // Cannot eliminate load
+ // 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.
- // No instructions invalidate the loads, they produce the same value!
- return true;
- } else {
- // Make sure that there are no store instructions between L1 and the end of
- // its basic block...
+ // 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 @@
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;
More information about the llvm-commits
mailing list