[llvm-branch-commits] [llvm-branch] r96491 - in /llvm/branches/Apple/Hermes: include/llvm/Analysis/MemoryDependenceAnalysis.h include/llvm/Transforms/Utils/BasicBlockUtils.h lib/Analysis/MemoryDependenceAnalysis.cpp lib/Transforms/Scalar/GVN.cpp lib/Transforms/Utils/BasicBlockUtils.cpp test/Transforms/GVN/pre-load.ll
Bob Wilson
bob.wilson at apple.com
Wed Feb 17 10:44:31 PST 2010
Author: bwilson
Date: Wed Feb 17 12:44:30 2010
New Revision: 96491
URL: http://llvm.org/viewvc/llvm-project?rev=96491&view=rev
Log:
--- Merging r96377 into '.':
U include/llvm/Transforms/Utils/BasicBlockUtils.h
U lib/Transforms/Utils/BasicBlockUtils.cpp
U lib/Transforms/Scalar/GVN.cpp
--- Merging r96378 into '.':
U include/llvm/Analysis/MemoryDependenceAnalysis.h
U lib/Analysis/MemoryDependenceAnalysis.cpp
G lib/Transforms/Scalar/GVN.cpp
--- Merging r96385 into '.':
U test/Transforms/GVN/pre-load.ll
--- Merging r96387 into '.':
G include/llvm/Transforms/Utils/BasicBlockUtils.h
G lib/Transforms/Utils/BasicBlockUtils.cpp
G lib/Transforms/Scalar/GVN.cpp
Modified:
llvm/branches/Apple/Hermes/include/llvm/Analysis/MemoryDependenceAnalysis.h
llvm/branches/Apple/Hermes/include/llvm/Transforms/Utils/BasicBlockUtils.h
llvm/branches/Apple/Hermes/lib/Analysis/MemoryDependenceAnalysis.cpp
llvm/branches/Apple/Hermes/lib/Transforms/Scalar/GVN.cpp
llvm/branches/Apple/Hermes/lib/Transforms/Utils/BasicBlockUtils.cpp
llvm/branches/Apple/Hermes/test/Transforms/GVN/pre-load.ll
Modified: llvm/branches/Apple/Hermes/include/llvm/Analysis/MemoryDependenceAnalysis.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/include/llvm/Analysis/MemoryDependenceAnalysis.h?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/include/llvm/Analysis/MemoryDependenceAnalysis.h (original)
+++ llvm/branches/Apple/Hermes/include/llvm/Analysis/MemoryDependenceAnalysis.h Wed Feb 17 12:44:30 2010
@@ -249,7 +249,7 @@
SmallPtrSet<Instruction*, 4> > ReverseDepMapType;
ReverseDepMapType ReverseLocalDeps;
- // A reverse mapping form dependencies to the non-local dependees.
+ // A reverse mapping from dependencies to the non-local dependees.
ReverseDepMapType ReverseNonLocalDeps;
/// Current AA implementation, just a cache.
@@ -312,6 +312,11 @@
/// value and replaces the other value with ptr. This can make Ptr available
/// in more places that cached info does not necessarily keep.
void invalidateCachedPointerInfo(Value *Ptr);
+
+ /// invalidateCachedPredecessors - Clear the PredIteratorCache info.
+ /// This needs to be done when the CFG changes, e.g., due to splitting
+ /// critical edges.
+ void invalidateCachedPredecessors();
private:
MemDepResult getPointerDependencyFrom(Value *Pointer, uint64_t MemSize,
Modified: llvm/branches/Apple/Hermes/include/llvm/Transforms/Utils/BasicBlockUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/include/llvm/Transforms/Utils/BasicBlockUtils.h?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/include/llvm/Transforms/Utils/BasicBlockUtils.h (original)
+++ llvm/branches/Apple/Hermes/include/llvm/Transforms/Utils/BasicBlockUtils.h Wed Feb 17 12:44:30 2010
@@ -102,6 +102,12 @@
//
void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum);
+/// GetSuccessorNumber - Search for the specified successor of basic block BB
+/// and return its position in the terminator instruction's list of
+/// successors. It is an error to call this with a block that is not a
+/// successor.
+unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ);
+
/// isCriticalEdge - Return true if the specified edge is a critical edge.
/// Critical edges are edges from a block with multiple successors to a block
/// with multiple predecessors.
Modified: llvm/branches/Apple/Hermes/lib/Analysis/MemoryDependenceAnalysis.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/Analysis/MemoryDependenceAnalysis.cpp?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/Analysis/MemoryDependenceAnalysis.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/Analysis/MemoryDependenceAnalysis.cpp Wed Feb 17 12:44:30 2010
@@ -1016,6 +1016,13 @@
RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair(Ptr, true));
}
+/// invalidateCachedPredecessors - Clear the PredIteratorCache info.
+/// This needs to be done when the CFG changes, e.g., due to splitting
+/// critical edges.
+void MemoryDependenceAnalysis::invalidateCachedPredecessors() {
+ PredCache->clear();
+}
+
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
/// This method attempts to keep the cache coherent using the reverse map.
Modified: llvm/branches/Apple/Hermes/lib/Transforms/Scalar/GVN.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/Transforms/Scalar/GVN.cpp?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/Transforms/Scalar/GVN.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/Transforms/Scalar/GVN.cpp Wed Feb 17 12:44:30 2010
@@ -674,6 +674,9 @@
ValueTable VN;
DenseMap<BasicBlock*, ValueNumberScope*> localAvail;
+ // List of critical edges to be split between iterations.
+ SmallVector<std::pair<TerminatorInst*, unsigned>, 4> toSplit;
+
// This transformation requires dominator postdominator info
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<DominatorTree>();
@@ -701,6 +704,7 @@
Value *lookupNumber(BasicBlock *BB, uint32_t num);
void cleanupGlobalSets();
void verifyRemoved(const Instruction *I) const;
+ bool splitCriticalEdges();
};
char GVN::ID = 0;
@@ -1583,10 +1587,15 @@
continue;
}
PredLoads[Pred] = 0;
- // We don't currently handle critical edges :(
+
if (Pred->getTerminator()->getNumSuccessors() != 1) {
- DEBUG(dbgs() << "COULD NOT PRE LOAD BECAUSE OF CRITICAL EDGE '"
- << Pred->getName() << "': " << *LI << '\n');
+ if (isa<IndirectBrInst>(Pred->getTerminator())) {
+ DEBUG(dbgs() << "COULD NOT PRE LOAD BECAUSE OF INDBR CRITICAL EDGE '"
+ << Pred->getName() << "': " << *LI << '\n');
+ return false;
+ }
+ unsigned SuccNum = GetSuccessorNumber(Pred, LoadBB);
+ toSplit.push_back(std::make_pair(Pred->getTerminator(), SuccNum));
return false;
}
}
@@ -2004,6 +2013,8 @@
while (ShouldContinue) {
DEBUG(dbgs() << "GVN iteration: " << Iteration << "\n");
ShouldContinue = iterateOnFunction(F);
+ if (splitCriticalEdges())
+ ShouldContinue = true;
Changed |= ShouldContinue;
++Iteration;
}
@@ -2070,7 +2081,6 @@
/// control flow patterns and attempts to perform simple PRE at the join point.
bool GVN::performPRE(Function &F) {
bool Changed = false;
- SmallVector<std::pair<TerminatorInst*, unsigned>, 4> toSplit;
DenseMap<BasicBlock*, Value*> predMap;
for (df_iterator<BasicBlock*> DI = df_begin(&F.getEntryBlock()),
DE = df_end(&F.getEntryBlock()); DI != DE; ++DI) {
@@ -2141,14 +2151,7 @@
// We can't do PRE safely on a critical edge, so instead we schedule
// the edge to be split and perform the PRE the next time we iterate
// on the function.
- unsigned SuccNum = 0;
- for (unsigned i = 0, e = PREPred->getTerminator()->getNumSuccessors();
- i != e; ++i)
- if (PREPred->getTerminator()->getSuccessor(i) == CurrentBlock) {
- SuccNum = i;
- break;
- }
-
+ unsigned SuccNum = GetSuccessorNumber(PREPred, CurrentBlock);
if (isCriticalEdge(PREPred->getTerminator(), SuccNum)) {
toSplit.push_back(std::make_pair(PREPred->getTerminator(), SuccNum));
continue;
@@ -2216,11 +2219,23 @@
}
}
- for (SmallVector<std::pair<TerminatorInst*, unsigned>, 4>::iterator
- I = toSplit.begin(), E = toSplit.end(); I != E; ++I)
- SplitCriticalEdge(I->first, I->second, this);
+ if (splitCriticalEdges())
+ Changed = true;
- return Changed || toSplit.size();
+ return Changed;
+}
+
+/// splitCriticalEdges - Split critical edges found during the previous
+/// iteration that may enable further optimization.
+bool GVN::splitCriticalEdges() {
+ if (toSplit.empty())
+ return false;
+ do {
+ std::pair<TerminatorInst*, unsigned> Edge = toSplit.pop_back_val();
+ SplitCriticalEdge(Edge.first, Edge.second, this);
+ } while (!toSplit.empty());
+ MD->invalidateCachedPredecessors();
+ return true;
}
/// iterateOnFunction - Executes one iteration of GVN
Modified: llvm/branches/Apple/Hermes/lib/Transforms/Utils/BasicBlockUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/lib/Transforms/Utils/BasicBlockUtils.cpp?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/lib/Transforms/Utils/BasicBlockUtils.cpp (original)
+++ llvm/branches/Apple/Hermes/lib/Transforms/Utils/BasicBlockUtils.cpp Wed Feb 17 12:44:30 2010
@@ -274,24 +274,31 @@
ReplaceInstWithInst(TI, NewTI);
}
-/// SplitEdge - Split the edge connecting specified block. Pass P must
-/// not be NULL.
-BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) {
- TerminatorInst *LatchTerm = BB->getTerminator();
- unsigned SuccNum = 0;
+/// GetSuccessorNumber - Search for the specified successor of basic block BB
+/// and return its position in the terminator instruction's list of
+/// successors. It is an error to call this with a block that is not a
+/// successor.
+unsigned llvm::GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ) {
+ TerminatorInst *Term = BB->getTerminator();
#ifndef NDEBUG
- unsigned e = LatchTerm->getNumSuccessors();
+ unsigned e = Term->getNumSuccessors();
#endif
for (unsigned i = 0; ; ++i) {
assert(i != e && "Didn't find edge?");
- if (LatchTerm->getSuccessor(i) == Succ) {
- SuccNum = i;
- break;
- }
+ if (Term->getSuccessor(i) == Succ)
+ return i;
}
+ return 0;
+}
+
+/// SplitEdge - Split the edge connecting specified block. Pass P must
+/// not be NULL.
+BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, Pass *P) {
+ unsigned SuccNum = GetSuccessorNumber(BB, Succ);
// If this is a critical edge, let SplitCriticalEdge do it.
- if (SplitCriticalEdge(BB->getTerminator(), SuccNum, P))
+ TerminatorInst *LatchTerm = BB->getTerminator();
+ if (SplitCriticalEdge(LatchTerm, SuccNum, P))
return LatchTerm->getSuccessor(SuccNum);
// If the edge isn't critical, then BB has a single successor or Succ has a
Modified: llvm/branches/Apple/Hermes/test/Transforms/GVN/pre-load.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Hermes/test/Transforms/GVN/pre-load.ll?rev=96491&r1=96490&r2=96491&view=diff
==============================================================================
--- llvm/branches/Apple/Hermes/test/Transforms/GVN/pre-load.ll (original)
+++ llvm/branches/Apple/Hermes/test/Transforms/GVN/pre-load.ll Wed Feb 17 12:44:30 2010
@@ -362,3 +362,30 @@
return:
ret void
}
+
+; Test critical edge splitting.
+define i32 @test11(i32* %p, i1 %C, i32 %N) {
+; CHECK: @test11
+block1:
+ br i1 %C, label %block2, label %block3
+
+block2:
+ %cond = icmp sgt i32 %N, 1
+ br i1 %cond, label %block4, label %block5
+; CHECK: load i32* %p
+; CHECK-NEXT: br label %block4
+
+block3:
+ store i32 0, i32* %p
+ br label %block4
+
+block4:
+ %PRE = load i32* %p
+ br label %block5
+
+block5:
+ %ret = phi i32 [ 0, %block2 ], [ %PRE, %block4 ]
+ ret i32 %ret
+; CHECK: block4:
+; CHECK-NEXT: phi i32
+}
More information about the llvm-branch-commits
mailing list