aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/LoopInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/LoopInfo.cpp')
-rw-r--r--lib/Analysis/LoopInfo.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp
index aa5da0859805..dbab5db7dbc2 100644
--- a/lib/Analysis/LoopInfo.cpp
+++ b/lib/Analysis/LoopInfo.cpp
@@ -359,6 +359,45 @@ bool Loop::isAuxiliaryInductionVariable(PHINode &AuxIndVar,
return SE.isLoopInvariant(IndDesc.getStep(), this);
}
+BranchInst *Loop::getLoopGuardBranch() const {
+ if (!isLoopSimplifyForm())
+ return nullptr;
+
+ BasicBlock *Preheader = getLoopPreheader();
+ BasicBlock *Latch = getLoopLatch();
+ assert(Preheader && Latch &&
+ "Expecting a loop with valid preheader and latch");
+
+ // Loop should be in rotate form.
+ if (!isLoopExiting(Latch))
+ return nullptr;
+
+ // Disallow loops with more than one unique exit block, as we do not verify
+ // that GuardOtherSucc post dominates all exit blocks.
+ BasicBlock *ExitFromLatch = getUniqueExitBlock();
+ if (!ExitFromLatch)
+ return nullptr;
+
+ BasicBlock *ExitFromLatchSucc = ExitFromLatch->getUniqueSuccessor();
+ if (!ExitFromLatchSucc)
+ return nullptr;
+
+ BasicBlock *GuardBB = Preheader->getUniquePredecessor();
+ if (!GuardBB)
+ return nullptr;
+
+ assert(GuardBB->getTerminator() && "Expecting valid guard terminator");
+
+ BranchInst *GuardBI = dyn_cast<BranchInst>(GuardBB->getTerminator());
+ if (!GuardBI || GuardBI->isUnconditional())
+ return nullptr;
+
+ BasicBlock *GuardOtherSucc = (GuardBI->getSuccessor(0) == Preheader)
+ ? GuardBI->getSuccessor(1)
+ : GuardBI->getSuccessor(0);
+ return (GuardOtherSucc == ExitFromLatchSucc) ? GuardBI : nullptr;
+}
+
bool Loop::isCanonical(ScalarEvolution &SE) const {
InductionDescriptor IndDesc;
if (!getInductionDescriptor(SE, IndDesc))