Skip to content

Commit fa16329

Browse files
committed
[NFC] [LoopPeel] Change the way DT is updated for loop exits
When peeling a loop, we assume that the latch has a `br` terminator and that all loop exits are either terminated with an `unreachable` or have a terminating deoptimize call. So when we peel off the 1st iteration, we change the IDom of all loop exits to the peeled copy of `NCD(IDom(Exit), Latch)`. This works now, but if we add logic to support loops with exits that are followed by a block with an `unreachable` or a terminating deoptimize call, changing the exit's idom wouldn't be enough and DT would be broken. For example, let `Exit1` and `Exit2` are loop exits, and each of them unconditionally branches to the same `unreachable` terminated block. So neither of the exits dominates this unreachable block. If we change the IDoms of the exits to some peeled loop block, we don't update the dominators of the unreachable block. Currently we just don't get to the peeling logic, saying that we can't peel such loops. With this NFC we just insert edges from cloned exiting blocks to their exits after peeling each iteration (we accumulate the insertion updates and then after peeling apply the updates to DT). This patch was a part of D110922. Patch by Dmitry Makogon! Differential Revision: https://reviews.llvm.org/D111611 Reviewed By: mkazantsev
1 parent c900b0a commit fa16329

File tree

1 file changed

+34
-56
lines changed

1 file changed

+34
-56
lines changed

llvm/lib/Transforms/Utils/LoopPeel.cpp

Lines changed: 34 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
#include "llvm/Transforms/Utils/LoopPeel.h"
1313
#include "llvm/ADT/DenseMap.h"
14+
#include "llvm/ADT/DenseSet.h"
1415
#include "llvm/ADT/Optional.h"
1516
#include "llvm/ADT/SmallVector.h"
1617
#include "llvm/ADT/Statistic.h"
18+
#include "llvm/Analysis/DomTreeUpdater.h"
1719
#include "llvm/Analysis/Loads.h"
1820
#include "llvm/Analysis/LoopInfo.h"
1921
#include "llvm/Analysis/LoopIterator.h"
@@ -555,11 +557,13 @@ static void fixupBranchWeights(BasicBlock *Header, BranchInst *LatchBR,
555557
/// \param LoopBlocks A helper for DFS-traversal of the loop.
556558
/// \param LVMap A value-map that maps instructions from the original loop to
557559
/// instructions in the last peeled-off iteration.
560+
/// \param LoopBlocksIDoms Immediate dominators of the original loop blocks.
558561
static void cloneLoopBlocks(
559562
Loop *L, unsigned IterNumber, BasicBlock *InsertTop, BasicBlock *InsertBot,
560563
SmallVectorImpl<std::pair<BasicBlock *, BasicBlock *>> &ExitEdges,
561564
SmallVectorImpl<BasicBlock *> &NewBlocks, LoopBlocksDFS &LoopBlocks,
562-
ValueToValueMapTy &VMap, ValueToValueMapTy &LVMap, DominatorTree *DT,
565+
ValueToValueMapTy &VMap, ValueToValueMapTy &LVMap, DomTreeUpdater &DTU,
566+
const SmallDenseMap<BasicBlock *, BasicBlock *> &LoopBlocksIDoms,
563567
LoopInfo *LI, ArrayRef<MDNode *> LoopLocalNoAliasDeclScopes) {
564568
BasicBlock *Header = L->getHeader();
565569
BasicBlock *Latch = L->getLoopLatch();
@@ -585,14 +589,13 @@ static void cloneLoopBlocks(
585589
VMap[*BB] = NewBB;
586590

587591
// If dominator tree is available, insert nodes to represent cloned blocks.
588-
if (DT) {
589-
if (Header == *BB)
590-
DT->addNewBlock(NewBB, InsertTop);
591-
else {
592-
DomTreeNode *IDom = DT->getNode(*BB)->getIDom();
593-
// VMap must contain entry for IDom, as the iteration order is RPO.
594-
DT->addNewBlock(NewBB, cast<BasicBlock>(VMap[IDom->getBlock()]));
595-
}
592+
if (Header == *BB)
593+
DTU.applyUpdates({{DominatorTree::Insert, InsertTop, NewBB}});
594+
else {
595+
BasicBlock *IDom = LoopBlocksIDoms.lookup(*BB);
596+
// VMap must contain entry for IDom, as the iteration order is RPO.
597+
DTU.applyUpdates(
598+
{{DominatorTree::Insert, cast<BasicBlock>(VMap[IDom]), NewBB}});
596599
}
597600
}
598601

@@ -629,8 +632,8 @@ static void cloneLoopBlocks(
629632
LatchBR->setSuccessor(idx, InsertBot);
630633
break;
631634
}
632-
if (DT)
633-
DT->changeImmediateDominator(InsertBot, NewLatch);
635+
DTU.applyUpdates({{DominatorTree::Insert, NewLatch, InsertBot},
636+
{DominatorTree::Delete, InsertTop, InsertBot}});
634637

635638
// The new copy of the loop body starts with a bunch of PHI nodes
636639
// that pick an incoming value from either the preheader, or the previous
@@ -732,36 +735,8 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
732735
SmallVector<std::pair<BasicBlock *, BasicBlock *>, 4> ExitEdges;
733736
L->getExitEdges(ExitEdges);
734737

735-
DenseMap<BasicBlock *, BasicBlock *> ExitIDom;
736-
if (DT) {
737-
// We'd like to determine the idom of exit block after peeling one
738-
// iteration.
739-
// Let Exit is exit block.
740-
// Let ExitingSet - is a set of predecessors of Exit block. They are exiting
741-
// blocks.
742-
// Let Latch' and ExitingSet' are copies after a peeling.
743-
// We'd like to find an idom'(Exit) - idom of Exit after peeling.
744-
// It is an evident that idom'(Exit) will be the nearest common dominator
745-
// of ExitingSet and ExitingSet'.
746-
// idom(Exit) is a nearest common dominator of ExitingSet.
747-
// idom(Exit)' is a nearest common dominator of ExitingSet'.
748-
// Taking into account that we have a single Latch, Latch' will dominate
749-
// Header and idom(Exit).
750-
// So the idom'(Exit) is nearest common dominator of idom(Exit)' and Latch'.
751-
// All these basic blocks are in the same loop, so what we find is
752-
// (nearest common dominator of idom(Exit) and Latch)'.
753-
// In the loop below we remember nearest common dominator of idom(Exit) and
754-
// Latch to update idom of Exit later.
755-
assert(L->hasDedicatedExits() && "No dedicated exits?");
756-
for (auto Edge : ExitEdges) {
757-
if (ExitIDom.count(Edge.second))
758-
continue;
759-
BasicBlock *BB = DT->findNearestCommonDominator(
760-
DT->getNode(Edge.second)->getIDom()->getBlock(), Latch);
761-
assert(L->contains(BB) && "IDom is not in a loop");
762-
ExitIDom[Edge.second] = BB;
763-
}
764-
}
738+
SmallDenseSet<std::pair<BasicBlock *, BasicBlock *>, 4> ExitEdgesSet(
739+
ExitEdges.begin(), ExitEdges.end());
765740

766741
Function *F = Header->getParent();
767742

@@ -834,31 +809,31 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
834809
SmallVector<MDNode *, 6> LoopLocalNoAliasDeclScopes;
835810
identifyNoAliasScopesToClone(L->getBlocks(), LoopLocalNoAliasDeclScopes);
836811

812+
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
813+
814+
// Fill map with the loop blocks IDoms to later update the DT when cloning the
815+
// loop blocks.
816+
SmallDenseMap<BasicBlock *, BasicBlock *> LoopBlocksIDoms;
817+
for (auto *BB : L->blocks())
818+
LoopBlocksIDoms[BB] = DT->getNode(BB)->getIDom()->getBlock();
819+
837820
// For each peeled-off iteration, make a copy of the loop.
838821
for (unsigned Iter = 0; Iter < PeelCount; ++Iter) {
839822
SmallVector<BasicBlock *, 8> NewBlocks;
840823
ValueToValueMapTy VMap;
841824

842825
cloneLoopBlocks(L, Iter, InsertTop, InsertBot, ExitEdges, NewBlocks,
843-
LoopBlocks, VMap, LVMap, DT, LI,
826+
LoopBlocks, VMap, LVMap, DTU, LoopBlocksIDoms, LI,
844827
LoopLocalNoAliasDeclScopes);
845828

846829
// Remap to use values from the current iteration instead of the
847830
// previous one.
848831
remapInstructionsInBlocks(NewBlocks, VMap);
849832

850-
if (DT) {
851-
// Latches of the cloned loops dominate over the loop exit, so idom of the
852-
// latter is the first cloned loop body, as original PreHeader dominates
853-
// the original loop body.
854-
if (Iter == 0)
855-
for (auto Exit : ExitIDom)
856-
DT->changeImmediateDominator(Exit.first,
857-
cast<BasicBlock>(LVMap[Exit.second]));
858-
#ifdef EXPENSIVE_CHECKS
859-
assert(DT->verify(DominatorTree::VerificationLevel::Fast));
860-
#endif
861-
}
833+
// If DT is available, insert edges from cloned exiting blocks to the exits
834+
for (auto Exit : ExitEdgesSet)
835+
DTU.applyUpdates({{DominatorTree::Insert,
836+
cast<BasicBlock>(LVMap[Exit.first]), Exit.second}});
862837

863838
auto *LatchBRCopy = cast<BranchInst>(VMap[LatchBR]);
864839
updateBranchWeights(InsertBot, LatchBRCopy, ExitWeight, FallThroughWeight);
@@ -867,7 +842,7 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
867842
LatchBRCopy->setMetadata(LLVMContext::MD_loop, nullptr);
868843

869844
InsertTop = InsertBot;
870-
InsertBot = SplitBlock(InsertBot, InsertBot->getTerminator(), DT, LI);
845+
InsertBot = SplitBlock(InsertBot, InsertBot->getTerminator(), &DTU, LI);
871846
InsertBot->setName(Header->getName() + ".peel.next");
872847

873848
F->getBasicBlockList().splice(InsertTop->getIterator(),
@@ -902,7 +877,10 @@ bool llvm::peelLoop(Loop *L, unsigned PeelCount, LoopInfo *LI,
902877
SE->forgetTopmostLoop(L);
903878

904879
// Finally DomtTree must be correct.
905-
assert(DT->verify(DominatorTree::VerificationLevel::Fast));
880+
if (DTU.hasDomTree()) {
881+
DTU.flush();
882+
assert(DT->verify(DominatorTree::VerificationLevel::Fast));
883+
}
906884

907885
// FIXME: Incrementally update loop-simplify
908886
simplifyLoop(L, DT, LI, SE, AC, nullptr, PreserveLCSSA);

0 commit comments

Comments
 (0)