diff options
Diffstat (limited to 'include/llvm/Analysis/LoopInfo.h')
-rw-r--r-- | include/llvm/Analysis/LoopInfo.h | 74 |
1 files changed, 28 insertions, 46 deletions
diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 12cb6c5..91feaaa 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -23,7 +23,6 @@ // * whether or not a particular block branches out of the loop // * the successor blocks of the loop // * the loop depth -// * the trip count // * etc... // //===----------------------------------------------------------------------===// @@ -416,14 +415,26 @@ public: #ifndef NDEBUG assert(!Blocks.empty() && "Loop header is missing"); + // Setup for using a depth-first iterator to visit every block in the loop. + SmallVector<BlockT*, 8> ExitBBs; + getExitBlocks(ExitBBs); + llvm::SmallPtrSet<BlockT*, 8> VisitSet; + VisitSet.insert(ExitBBs.begin(), ExitBBs.end()); + df_ext_iterator<BlockT*, llvm::SmallPtrSet<BlockT*, 8> > + BI = df_ext_begin(getHeader(), VisitSet), + BE = df_ext_end(getHeader(), VisitSet); + + // Keep track of the number of BBs visited. + unsigned NumVisited = 0; + // Sort the blocks vector so that we can use binary search to do quick // lookups. SmallVector<BlockT*, 128> LoopBBs(block_begin(), block_end()); std::sort(LoopBBs.begin(), LoopBBs.end()); // Check the individual blocks. - for (block_iterator I = block_begin(), E = block_end(); I != E; ++I) { - BlockT *BB = *I; + for ( ; BI != BE; ++BI) { + BlockT *BB = *BI; bool HasInsideLoopSuccs = false; bool HasInsideLoopPreds = false; SmallVector<BlockT *, 2> OutsideLoopPreds; @@ -440,7 +451,7 @@ public: for (typename InvBlockTraits::ChildIteratorType PI = InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB); PI != PE; ++PI) { - typename InvBlockTraits::NodeType *N = *PI; + BlockT *N = *PI; if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N)) HasInsideLoopPreds = true; else @@ -464,8 +475,12 @@ public: assert(HasInsideLoopSuccs && "Loop block has no in-loop successors!"); assert(BB != getHeader()->getParent()->begin() && "Loop contains function entry block!"); + + NumVisited++; } + assert(NumVisited == getNumBlocks() && "Unreachable block in loop"); + // Check the subloops. for (iterator I = begin(), E = end(); I != E; ++I) // Each block in each subloop should be contained within this loop. @@ -571,37 +586,6 @@ public: /// PHINode *getCanonicalInductionVariable() const; - /// getTripCount - Return a loop-invariant LLVM value indicating the number of - /// times the loop will be executed. Note that this means that the backedge - /// of the loop executes N-1 times. If the trip-count cannot be determined, - /// this returns null. - /// - /// The IndVarSimplify pass transforms loops to have a form that this - /// function easily understands. - /// - Value *getTripCount() const; - - /// getSmallConstantTripCount - Returns the trip count of this loop as a - /// normal unsigned value, if possible. Returns 0 if the trip count is unknown - /// of not constant. Will also return 0 if the trip count is very large - /// (>= 2^32) - /// - /// The IndVarSimplify pass transforms loops to have a form that this - /// function easily understands. - /// - unsigned getSmallConstantTripCount() const; - - /// getSmallConstantTripMultiple - Returns the largest constant divisor of the - /// trip count of this loop as a normal unsigned value, if possible. This - /// means that the actual trip count is always a multiple of the returned - /// value (don't forget the trip count could very well be zero as well!). - /// - /// Returns 1 if the trip count is unknown or not guaranteed to be the - /// multiple of a constant (which is also the case if the trip count is simply - /// constant, use getSmallConstantTripCount for that case), Will also return 1 - /// if the trip count is very large (>= 2^32). - unsigned getSmallConstantTripMultiple() const; - /// isLCSSAForm - Return true if the Loop is in LCSSA form bool isLCSSAForm(DominatorTree &DT) const; @@ -610,6 +594,9 @@ public: /// normal form. bool isLoopSimplifyForm() const; + /// isSafeToClone - Return true if the loop body is safe to clone in practice. + bool isSafeToClone() const; + /// hasDedicatedExits - Return true if no exit block for the loop /// has a predecessor that is outside the loop. bool hasDedicatedExits() const; @@ -671,9 +658,7 @@ public: /// block is in no loop (for example the entry node), null is returned. /// LoopT *getLoopFor(const BlockT *BB) const { - typename DenseMap<BlockT *, LoopT *>::const_iterator I= - BBMap.find(const_cast<BlockT*>(BB)); - return I != BBMap.end() ? I->second : 0; + return BBMap.lookup(const_cast<BlockT*>(BB)); } /// operator[] - same as getLoopFor... @@ -712,9 +697,7 @@ public: /// the loop hierarchy tree. void changeLoopFor(BlockT *BB, LoopT *L) { if (!L) { - typename DenseMap<BlockT *, LoopT *>::iterator I = BBMap.find(BB); - if (I != BBMap.end()) - BBMap.erase(I); + BBMap.erase(BB); return; } BBMap[BB] = L; @@ -771,7 +754,7 @@ public: } LoopT *ConsiderForLoop(BlockT *BB, DominatorTreeBase<BlockT> &DT) { - if (BBMap.find(BB) != BBMap.end()) return 0;// Haven't processed this node? + if (BBMap.count(BB)) return 0; // Haven't processed this node? std::vector<BlockT *> TodoStack; @@ -782,7 +765,8 @@ public: InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB); I != E; ++I) { typename InvBlockTraits::NodeType *N = *I; - if (DT.dominates(BB, N)) // If BB dominates its predecessor... + // If BB dominates its predecessor... + if (DT.dominates(BB, N) && DT.isReachableFromEntry(N)) TodoStack.push_back(N); } @@ -792,14 +776,12 @@ public: LoopT *L = new LoopT(BB); BBMap[BB] = L; - BlockT *EntryBlock = BB->getParent()->begin(); - while (!TodoStack.empty()) { // Process all the nodes in the loop BlockT *X = TodoStack.back(); TodoStack.pop_back(); if (!L->contains(X) && // As of yet unprocessed?? - DT.dominates(EntryBlock, X)) { // X is reachable from entry block? + DT.isReachableFromEntry(X)) { // Check to see if this block already belongs to a loop. If this occurs // then we have a case where a loop that is supposed to be a child of // the current loop was processed before the current loop. When this |