Dan Gohman wrote: >>>Would it be too intrusive to ask ScalarEvolution to use a >>>PostDominanceFrontier for this? >> >>No, that's what I implemented at first. Unfortunately, it doesn't cover >>all the possible cases (specifically, it broke 2007-01-06-TripCount.ll). >> >>In 2007-01-06-TripCount.ll there's two "loops" sharing one loop header. >>The first runs from header -> exit -> A -> header and the other is >>header -> B -> A -> header. I was testing exit postdom header, which it >>does, but that didn't catch this case where the transform is still >>unsafe. >> >>If you think I merely had my test wrong, please let me know what you >>think it ought to be and I'll implement it and see. > > I do think you merely had the wrong test. The post-dominance frontiers > are needed here. > > Running -analyze -postdomfrontier on 2007-01-06-TripCount.ll gives this: > > Printing analysis 'Post-Dominance Frontier Construction' for function 'test': > DomFrontier for BB %bb is: %bb2 %cond_next > DomFrontier for BB %bb2 is: %bb2 %cond_next > DomFrontier for BB %cond_true is: %bb2 > DomFrontier for BB %cond_next is: %cond_next > DomFrontier for BB %bb6 is: > DomFrontier for BB %return is: > DomFrontier for BB %entry is: > > It looks like %bb2 is the loop header, and %cond_next is the block that > contains the exit branch. The frontier sets for these two blocks are > different, so they're not control-equivalent, and that disqualifies the > loop for what ScalarEvolution is doing here.
Cool! I've implemented that (patch attached) and it works for both treeadd and TripCount. Here's the numbers: Original: predicted: 4874 (21%) not predicted: 18361 (79%) PDF test only: predicted: 4865 (21%) not predicted: 18372 (79%) There was one other consequence of that change. PDF entries only exist for nodes that postdominate the exit. One could have a countable loop that preceeds an infinite loop, and it would no longer be analyzed. I was going to just have it refuse to analyze that case, but it occured to me that event loops and such work this way, and it could cause a real problem for real code. So I thought I'd try keeping it. Both tests: predicted: 4881 (21%) not predicted: 18354 (79%) I'm not sure why, but it doesn't seem as promising as the previous test I had. Could it be that when comparing the PDF I should ignore blocks that are not part of the loop? Nick
Index: lib/Analysis/ScalarEvolution.cpp =================================================================== --- lib/Analysis/ScalarEvolution.cpp (revision 40483) +++ lib/Analysis/ScalarEvolution.cpp (working copy) @@ -60,6 +60,7 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "scalar-evolution" +#include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" @@ -1111,6 +1112,9 @@ /// LoopInfo &LI; + /// PDF - The PostDominanceFrontier for the function are currently analyzing. + PostDominanceFrontier &PDF; + /// UnknownValue - This SCEV is used to represent unknown trip counts and /// things. SCEVHandle UnknownValue; @@ -1131,8 +1135,8 @@ std::map<PHINode*, Constant*> ConstantEvolutionLoopExitValue; public: - ScalarEvolutionsImpl(Function &f, LoopInfo &li) - : F(f), LI(li), UnknownValue(new SCEVCouldNotCompute()) {} + ScalarEvolutionsImpl(Function &f, LoopInfo &li, PostDominanceFrontier &pdf) + : F(f), LI(li), PDF(pdf), UnknownValue(new SCEVCouldNotCompute()) {} /// getSCEV - Return an existing SCEV if it exists, otherwise analyze the /// expression and create a new one. @@ -1600,15 +1604,30 @@ // time through the loop. If not, then the execution count of the branch will // not be equal to the trip count of the loop. // - // Currently we check for this by checking to see if the Exit branch goes to - // the loop header. If so, we know it will always execute the same number of - // times as the loop. We also handle the case where the exit block *is* the - // loop header. This is common for un-rotated loops. More extensive analysis - // could be done to handle more cases here. - if (ExitBr->getSuccessor(0) != L->getHeader() && - ExitBr->getSuccessor(1) != L->getHeader() && - ExitBr->getParent() != L->getHeader()) - return UnknownValue; + // If the entries in the PostDominanceFrontier are equivalent, then the blocks + // have the equivalent control flow. + + PostDominanceFrontier::iterator HeaderPDF = PDF.find(L->getHeader()); + PostDominanceFrontier::iterator ExitBrPDF = PDF.find(ExitBr->getParent()); + + if (HeaderPDF == PDF.end() || ExitBrPDF == PDF.end()) { + + // If the loop is followed by an infinite loop, the PDF won't have an entry + // for these blocks. We handle this by testing if the Exit branch goes to + // the loop header. If so, we know it will always execute the same number + // of times as the loop. We also handle the case where the exit block *is* + // the loop header. This is common for un-rotated loops. More extensive + // analysis could be done to handle more cases here. + + if (ExitBr->getSuccessor(0) != L->getHeader() && + ExitBr->getSuccessor(1) != L->getHeader() && + ExitBr->getParent() != L->getHeader()) + return UnknownValue; + + } else { + if (HeaderPDF->second != ExitBrPDF->second) + return UnknownValue; + } ICmpInst *ExitCond = dyn_cast<ICmpInst>(ExitBr->getCondition()); @@ -2546,7 +2565,8 @@ //===----------------------------------------------------------------------===// bool ScalarEvolution::runOnFunction(Function &F) { - Impl = new ScalarEvolutionsImpl(F, getAnalysis<LoopInfo>()); + Impl = new ScalarEvolutionsImpl(F, getAnalysis<LoopInfo>(), + getAnalysis<PostDominanceFrontier>()); return false; } @@ -2558,6 +2578,7 @@ void ScalarEvolution::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); AU.addRequiredTransitive<LoopInfo>(); + AU.addRequired<PostDominanceFrontier>(); } SCEVHandle ScalarEvolution::getSCEV(Value *V) const {
_______________________________________________ llvm-commits mailing list llvm-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits