aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp92
1 files changed, 67 insertions, 25 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp
index 1be1082002fc..e8f585b4a94d 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/Utils/LoopUnroll.cpp
@@ -17,7 +17,6 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
@@ -66,6 +65,7 @@
#include "llvm/Transforms/Utils/ValueMapper.h"
#include <algorithm>
#include <assert.h>
+#include <numeric>
#include <type_traits>
#include <vector>
@@ -321,6 +321,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
unsigned TripMultiple;
unsigned BreakoutTrip;
bool ExitOnTrue;
+ BasicBlock *FirstExitingBlock = nullptr;
SmallVector<BasicBlock *> ExitingBlocks;
};
DenseMap<BasicBlock *, ExitInfo> ExitInfos;
@@ -341,7 +342,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
Info.TripMultiple = 0;
} else {
Info.BreakoutTrip = Info.TripMultiple =
- (unsigned)GreatestCommonDivisor64(ULO.Count, Info.TripMultiple);
+ (unsigned)std::gcd(ULO.Count, Info.TripMultiple);
}
Info.ExitOnTrue = !L->contains(BI->getSuccessor(0));
Info.ExitingBlocks.push_back(ExitingBlock);
@@ -464,8 +465,10 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
if (SE) {
if (ULO.ForgetAllSCEV)
SE->forgetAllLoops();
- else
+ else {
SE->forgetTopmostLoop(L);
+ SE->forgetBlockAndLoopDispositions();
+ }
}
if (!LatchIsExiting)
@@ -506,7 +509,8 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
// When a FSDiscriminator is enabled, we don't need to add the multiply
// factors to the discriminators.
- if (Header->getParent()->isDebugInfoForProfiling() && !EnableFSDiscriminator)
+ if (Header->getParent()->shouldEmitDebugInfoForProfiling() &&
+ !EnableFSDiscriminator)
for (BasicBlock *BB : L->getBlocks())
for (Instruction &I : *BB)
if (!isa<DbgInfoIntrinsic>(&I))
@@ -537,7 +541,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) {
ValueToValueMapTy VMap;
BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It));
- Header->getParent()->getBasicBlockList().insert(BlockInsertPt, New);
+ Header->getParent()->insert(BlockInsertPt, New);
assert((*BB != Header || LI->getLoopFor(*BB) == L) &&
"Header should not be in a sub-loop");
@@ -556,7 +560,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
if (It > 1 && L->contains(InValI))
InVal = LastValueMap[InValI];
VMap[OrigPHI] = InVal;
- New->getInstList().erase(NewPHI);
+ NewPHI->eraseFromParent();
}
// Update our running map of newest clones
@@ -575,6 +579,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
if (It != LastValueMap.end())
Incoming = It->second;
PHI.addIncoming(Incoming, New);
+ SE->forgetValue(&PHI);
}
}
// Keep track of new headers and latches as we create them, so that
@@ -629,7 +634,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
for (PHINode *PN : OrigPHINode) {
if (CompletelyUnroll) {
PN->replaceAllUsesWith(PN->getIncomingValueForBlock(Preheader));
- Header->getInstList().erase(PN);
+ PN->eraseFromParent();
} else if (ULO.Count > 1) {
Value *InVal = PN->removeIncomingValue(LatchBlock, false);
// If this value was defined in the loop, take the value defined by the
@@ -676,8 +681,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
assert(!UnrollVerifyDomtree ||
DT->verify(DominatorTree::VerificationLevel::Fast));
- DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
-
+ SmallVector<DominatorTree::UpdateType> DTUpdates;
auto SetDest = [&](BasicBlock *Src, bool WillExit, bool ExitOnTrue) {
auto *Term = cast<BranchInst>(Src->getTerminator());
const unsigned Idx = ExitOnTrue ^ WillExit;
@@ -691,15 +695,15 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
BranchInst::Create(Dest, Term);
Term->eraseFromParent();
- DTU.applyUpdates({{DominatorTree::Delete, Src, DeadSucc}});
+ DTUpdates.emplace_back(DominatorTree::Delete, Src, DeadSucc);
};
auto WillExit = [&](const ExitInfo &Info, unsigned i, unsigned j,
- bool IsLatch) -> Optional<bool> {
+ bool IsLatch) -> std::optional<bool> {
if (CompletelyUnroll) {
if (PreserveOnlyFirst) {
if (i == 0)
- return None;
+ return std::nullopt;
return j == 0;
}
// Complete (but possibly inexact) unrolling
@@ -707,7 +711,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
return true;
if (Info.TripCount && j != Info.TripCount)
return false;
- return None;
+ return std::nullopt;
}
if (ULO.Runtime) {
@@ -715,7 +719,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
// exits may be stale.
if (IsLatch && j != 0)
return false;
- return None;
+ return std::nullopt;
}
if (j != Info.BreakoutTrip &&
@@ -724,36 +728,69 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
// unconditional branch for some iterations.
return false;
}
- return None;
+ return std::nullopt;
};
// Fold branches for iterations where we know that they will exit or not
// exit.
- for (const auto &Pair : ExitInfos) {
- const ExitInfo &Info = Pair.second;
+ for (auto &Pair : ExitInfos) {
+ ExitInfo &Info = Pair.second;
for (unsigned i = 0, e = Info.ExitingBlocks.size(); i != e; ++i) {
// The branch destination.
unsigned j = (i + 1) % e;
bool IsLatch = Pair.first == LatchBlock;
- Optional<bool> KnownWillExit = WillExit(Info, i, j, IsLatch);
- if (!KnownWillExit)
+ std::optional<bool> KnownWillExit = WillExit(Info, i, j, IsLatch);
+ if (!KnownWillExit) {
+ if (!Info.FirstExitingBlock)
+ Info.FirstExitingBlock = Info.ExitingBlocks[i];
continue;
+ }
// We don't fold known-exiting branches for non-latch exits here,
// because this ensures that both all loop blocks and all exit blocks
// remain reachable in the CFG.
// TODO: We could fold these branches, but it would require much more
// sophisticated updates to LoopInfo.
- if (*KnownWillExit && !IsLatch)
+ if (*KnownWillExit && !IsLatch) {
+ if (!Info.FirstExitingBlock)
+ Info.FirstExitingBlock = Info.ExitingBlocks[i];
continue;
+ }
SetDest(Info.ExitingBlocks[i], *KnownWillExit, Info.ExitOnTrue);
}
}
+ DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
+ DomTreeUpdater *DTUToUse = &DTU;
+ if (ExitingBlocks.size() == 1 && ExitInfos.size() == 1) {
+ // Manually update the DT if there's a single exiting node. In that case
+ // there's a single exit node and it is sufficient to update the nodes
+ // immediately dominated by the original exiting block. They will become
+ // dominated by the first exiting block that leaves the loop after
+ // unrolling. Note that the CFG inside the loop does not change, so there's
+ // no need to update the DT inside the unrolled loop.
+ DTUToUse = nullptr;
+ auto &[OriginalExit, Info] = *ExitInfos.begin();
+ if (!Info.FirstExitingBlock)
+ Info.FirstExitingBlock = Info.ExitingBlocks.back();
+ for (auto *C : to_vector(DT->getNode(OriginalExit)->children())) {
+ if (L->contains(C->getBlock()))
+ continue;
+ C->setIDom(DT->getNode(Info.FirstExitingBlock));
+ }
+ } else {
+ DTU.applyUpdates(DTUpdates);
+ }
+
// When completely unrolling, the last latch becomes unreachable.
- if (!LatchIsExiting && CompletelyUnroll)
- changeToUnreachable(Latches.back()->getTerminator(), PreserveLCSSA, &DTU);
+ if (!LatchIsExiting && CompletelyUnroll) {
+ // There is no need to update the DT here, because there must be a unique
+ // latch. Hence if the latch is not exiting it must directly branch back to
+ // the original loop header and does not dominate any nodes.
+ assert(LatchBlock->getSingleSuccessor() && "Loop with multiple latches?");
+ changeToUnreachable(Latches.back()->getTerminator(), PreserveLCSSA);
+ }
// Merge adjacent basic blocks, if possible.
for (BasicBlock *Latch : Latches) {
@@ -765,16 +802,21 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI,
if (Term && Term->isUnconditional()) {
BasicBlock *Dest = Term->getSuccessor(0);
BasicBlock *Fold = Dest->getUniquePredecessor();
- if (MergeBlockIntoPredecessor(Dest, &DTU, LI)) {
+ if (MergeBlockIntoPredecessor(Dest, /*DTU=*/DTUToUse, LI,
+ /*MSSAU=*/nullptr, /*MemDep=*/nullptr,
+ /*PredecessorWithTwoSuccessors=*/false,
+ DTUToUse ? nullptr : DT)) {
// Dest has been folded into Fold. Update our worklists accordingly.
std::replace(Latches.begin(), Latches.end(), Dest, Fold);
llvm::erase_value(UnrolledLoopBlocks, Dest);
}
}
}
- // Apply updates to the DomTree.
- DT = &DTU.getDomTree();
+ if (DTUToUse) {
+ // Apply updates to the DomTree.
+ DT = &DTU.getDomTree();
+ }
assert(!UnrollVerifyDomtree ||
DT->verify(DominatorTree::VerificationLevel::Fast));