1c84532a7SWhitney Tsang //===- LoopNestAnalysis.cpp - Loop Nest Analysis --------------------------==//
2c84532a7SWhitney Tsang //
3c84532a7SWhitney Tsang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4c84532a7SWhitney Tsang // See https://llvm.org/LICENSE.txt for license information.
5c84532a7SWhitney Tsang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c84532a7SWhitney Tsang //
7c84532a7SWhitney Tsang //===----------------------------------------------------------------------===//
8c84532a7SWhitney Tsang ///
9c84532a7SWhitney Tsang /// \file
10c84532a7SWhitney Tsang /// The implementation for the loop nest analysis.
11c84532a7SWhitney Tsang ///
12c84532a7SWhitney Tsang //===----------------------------------------------------------------------===//
13c84532a7SWhitney Tsang
14c84532a7SWhitney Tsang #include "llvm/Analysis/LoopNestAnalysis.h"
15c84532a7SWhitney Tsang #include "llvm/ADT/BreadthFirstIterator.h"
16*71c3a551Sserge-sans-paille #include "llvm/ADT/DepthFirstIterator.h"
17c84532a7SWhitney Tsang #include "llvm/Analysis/ValueTracking.h"
18c84532a7SWhitney Tsang
19c84532a7SWhitney Tsang using namespace llvm;
20c84532a7SWhitney Tsang
21c84532a7SWhitney Tsang #define DEBUG_TYPE "loopnest"
22c84532a7SWhitney Tsang #ifndef NDEBUG
23c84532a7SWhitney Tsang static const char *VerboseDebug = DEBUG_TYPE "-verbose";
24c84532a7SWhitney Tsang #endif
25c84532a7SWhitney Tsang
267ff2768bSTa-Wei Tu /// Determine whether the loops structure violates basic requirements for
277ff2768bSTa-Wei Tu /// perfect nesting:
287ff2768bSTa-Wei Tu /// - the inner loop should be the outer loop's only child
297ff2768bSTa-Wei Tu /// - the outer loop header should 'flow' into the inner loop preheader
307ff2768bSTa-Wei Tu /// or jump around the inner loop to the outer loop latch
317ff2768bSTa-Wei Tu /// - if the inner loop latch exits the inner loop, it should 'flow' into
327ff2768bSTa-Wei Tu /// the outer loop latch.
337ff2768bSTa-Wei Tu /// Returns true if the loop structure satisfies the basic requirements and
347ff2768bSTa-Wei Tu /// false otherwise.
357ff2768bSTa-Wei Tu static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
367ff2768bSTa-Wei Tu ScalarEvolution &SE);
377ff2768bSTa-Wei Tu
38c84532a7SWhitney Tsang //===----------------------------------------------------------------------===//
39c84532a7SWhitney Tsang // LoopNest implementation
40c84532a7SWhitney Tsang //
41c84532a7SWhitney Tsang
LoopNest(Loop & Root,ScalarEvolution & SE)42c84532a7SWhitney Tsang LoopNest::LoopNest(Loop &Root, ScalarEvolution &SE)
43c84532a7SWhitney Tsang : MaxPerfectDepth(getMaxPerfectDepth(Root, SE)) {
44a3254904SKazu Hirata append_range(Loops, breadth_first(&Root));
45c84532a7SWhitney Tsang }
46c84532a7SWhitney Tsang
getLoopNest(Loop & Root,ScalarEvolution & SE)47c84532a7SWhitney Tsang std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root,
48c84532a7SWhitney Tsang ScalarEvolution &SE) {
49c84532a7SWhitney Tsang return std::make_unique<LoopNest>(Root, SE);
50c84532a7SWhitney Tsang }
51c84532a7SWhitney Tsang
getOuterLoopLatchCmp(const Loop & OuterLoop)524018d25dSMark Danial static CmpInst *getOuterLoopLatchCmp(const Loop &OuterLoop) {
534018d25dSMark Danial
544018d25dSMark Danial const BasicBlock *Latch = OuterLoop.getLoopLatch();
554018d25dSMark Danial assert(Latch && "Expecting a valid loop latch");
564018d25dSMark Danial
574018d25dSMark Danial const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
584018d25dSMark Danial assert(BI && BI->isConditional() &&
594018d25dSMark Danial "Expecting loop latch terminator to be a branch instruction");
604018d25dSMark Danial
614018d25dSMark Danial CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition());
624018d25dSMark Danial DEBUG_WITH_TYPE(
634018d25dSMark Danial VerboseDebug, if (OuterLoopLatchCmp) {
644018d25dSMark Danial dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmp
654018d25dSMark Danial << "\n";
664018d25dSMark Danial });
674018d25dSMark Danial return OuterLoopLatchCmp;
684018d25dSMark Danial }
694018d25dSMark Danial
getInnerLoopGuardCmp(const Loop & InnerLoop)704018d25dSMark Danial static CmpInst *getInnerLoopGuardCmp(const Loop &InnerLoop) {
714018d25dSMark Danial
724018d25dSMark Danial BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch();
734018d25dSMark Danial CmpInst *InnerLoopGuardCmp =
744018d25dSMark Danial (InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr;
754018d25dSMark Danial
764018d25dSMark Danial DEBUG_WITH_TYPE(
774018d25dSMark Danial VerboseDebug, if (InnerLoopGuardCmp) {
784018d25dSMark Danial dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmp
794018d25dSMark Danial << "\n";
804018d25dSMark Danial });
814018d25dSMark Danial return InnerLoopGuardCmp;
824018d25dSMark Danial }
834018d25dSMark Danial
checkSafeInstruction(const Instruction & I,const CmpInst * InnerLoopGuardCmp,const CmpInst * OuterLoopLatchCmp,Optional<Loop::LoopBounds> OuterLoopLB)844018d25dSMark Danial static bool checkSafeInstruction(const Instruction &I,
854018d25dSMark Danial const CmpInst *InnerLoopGuardCmp,
864018d25dSMark Danial const CmpInst *OuterLoopLatchCmp,
874018d25dSMark Danial Optional<Loop::LoopBounds> OuterLoopLB) {
884018d25dSMark Danial
894018d25dSMark Danial bool IsAllowed =
904018d25dSMark Danial isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) || isa<BranchInst>(I);
914018d25dSMark Danial if (!IsAllowed)
924018d25dSMark Danial return false;
934018d25dSMark Danial // The only binary instruction allowed is the outer loop step instruction,
944018d25dSMark Danial // the only comparison instructions allowed are the inner loop guard
954018d25dSMark Danial // compare instruction and the outer loop latch compare instruction.
964018d25dSMark Danial if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) ||
974018d25dSMark Danial (isa<CmpInst>(I) && &I != OuterLoopLatchCmp && &I != InnerLoopGuardCmp)) {
984018d25dSMark Danial return false;
994018d25dSMark Danial }
1004018d25dSMark Danial return true;
1014018d25dSMark Danial }
1024018d25dSMark Danial
arePerfectlyNested(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)103c84532a7SWhitney Tsang bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop,
104c84532a7SWhitney Tsang ScalarEvolution &SE) {
1054018d25dSMark Danial return (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE) ==
1064018d25dSMark Danial PerfectLoopNest);
1074018d25dSMark Danial }
1084018d25dSMark Danial
analyzeLoopNestForPerfectNest(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)1094018d25dSMark Danial LoopNest::LoopNestEnum LoopNest::analyzeLoopNestForPerfectNest(
1104018d25dSMark Danial const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) {
1114018d25dSMark Danial
11289c1e35fSStefanos Baziotis assert(!OuterLoop.isInnermost() && "Outer loop should have subloops");
11389c1e35fSStefanos Baziotis assert(!InnerLoop.isOutermost() && "Inner loop should have a parent");
114c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName()
115c84532a7SWhitney Tsang << "' and '" << InnerLoop.getName()
116c84532a7SWhitney Tsang << "' are perfectly nested.\n");
117c84532a7SWhitney Tsang
118c84532a7SWhitney Tsang // Determine whether the loops structure satisfies the following requirements:
119c84532a7SWhitney Tsang // - the inner loop should be the outer loop's only child
120c84532a7SWhitney Tsang // - the outer loop header should 'flow' into the inner loop preheader
121c84532a7SWhitney Tsang // or jump around the inner loop to the outer loop latch
122c84532a7SWhitney Tsang // - if the inner loop latch exits the inner loop, it should 'flow' into
123c84532a7SWhitney Tsang // the outer loop latch.
124c84532a7SWhitney Tsang if (!checkLoopsStructure(OuterLoop, InnerLoop, SE)) {
125c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure.\n");
1264018d25dSMark Danial return InvalidLoopStructure;
127c84532a7SWhitney Tsang }
128c84532a7SWhitney Tsang
129c84532a7SWhitney Tsang // Bail out if we cannot retrieve the outer loop bounds.
130c84532a7SWhitney Tsang auto OuterLoopLB = OuterLoop.getBounds(SE);
131c84532a7SWhitney Tsang if (OuterLoopLB == None) {
132c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "
133c84532a7SWhitney Tsang << OuterLoop << "\n";);
1344018d25dSMark Danial return OuterLoopLowerBoundUnknown;
135c84532a7SWhitney Tsang }
136c84532a7SWhitney Tsang
1374018d25dSMark Danial CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop);
1384018d25dSMark Danial CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop);
139c84532a7SWhitney Tsang
140c84532a7SWhitney Tsang // Determine whether instructions in a basic block are one of:
141c84532a7SWhitney Tsang // - the inner loop guard comparison
142c84532a7SWhitney Tsang // - the outer loop latch comparison
143c84532a7SWhitney Tsang // - the outer loop induction variable increment
144c84532a7SWhitney Tsang // - a phi node, a cast or a branch
145c84532a7SWhitney Tsang auto containsOnlySafeInstructions = [&](const BasicBlock &BB) {
146c84532a7SWhitney Tsang return llvm::all_of(BB, [&](const Instruction &I) {
1474018d25dSMark Danial bool IsSafeInstr = checkSafeInstruction(I, InnerLoopGuardCmp,
1484018d25dSMark Danial OuterLoopLatchCmp, OuterLoopLB);
1494018d25dSMark Danial if (IsSafeInstr) {
150c84532a7SWhitney Tsang DEBUG_WITH_TYPE(VerboseDebug, {
151c84532a7SWhitney Tsang dbgs() << "Instruction: " << I << "\nin basic block:" << BB
152c84532a7SWhitney Tsang << "is unsafe.\n";
153c84532a7SWhitney Tsang });
154c84532a7SWhitney Tsang }
1554018d25dSMark Danial return IsSafeInstr;
156c84532a7SWhitney Tsang });
157c84532a7SWhitney Tsang };
158c84532a7SWhitney Tsang
159c84532a7SWhitney Tsang // Check the code surrounding the inner loop for instructions that are deemed
160c84532a7SWhitney Tsang // unsafe.
161c84532a7SWhitney Tsang const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
162c84532a7SWhitney Tsang const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
163c84532a7SWhitney Tsang const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
164c84532a7SWhitney Tsang
165c84532a7SWhitney Tsang if (!containsOnlySafeInstructions(*OuterLoopHeader) ||
166c84532a7SWhitney Tsang !containsOnlySafeInstructions(*OuterLoopLatch) ||
167c84532a7SWhitney Tsang (InnerLoopPreHeader != OuterLoopHeader &&
168c84532a7SWhitney Tsang !containsOnlySafeInstructions(*InnerLoopPreHeader)) ||
169c84532a7SWhitney Tsang !containsOnlySafeInstructions(*InnerLoop.getExitBlock())) {
170c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Not perfectly nested: code surrounding inner loop is "
171c84532a7SWhitney Tsang "unsafe\n";);
1724018d25dSMark Danial return ImperfectLoopNest;
173c84532a7SWhitney Tsang }
174c84532a7SWhitney Tsang
175c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Loop '" << OuterLoop.getName() << "' and '"
176c84532a7SWhitney Tsang << InnerLoop.getName() << "' are perfectly nested.\n");
177c84532a7SWhitney Tsang
1784018d25dSMark Danial return PerfectLoopNest;
1794018d25dSMark Danial }
1804018d25dSMark Danial
getInterveningInstructions(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)1814018d25dSMark Danial LoopNest::InstrVectorTy LoopNest::getInterveningInstructions(
1824018d25dSMark Danial const Loop &OuterLoop, const Loop &InnerLoop, ScalarEvolution &SE) {
1834018d25dSMark Danial InstrVectorTy Instr;
1844018d25dSMark Danial switch (analyzeLoopNestForPerfectNest(OuterLoop, InnerLoop, SE)) {
1854018d25dSMark Danial case PerfectLoopNest:
1864018d25dSMark Danial LLVM_DEBUG(dbgs() << "The loop Nest is Perfect, returning empty "
1874018d25dSMark Danial "instruction vector. \n";);
1884018d25dSMark Danial return Instr;
1894018d25dSMark Danial
1904018d25dSMark Danial case InvalidLoopStructure:
1914018d25dSMark Danial LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure. "
1924018d25dSMark Danial "Instruction vector is empty.\n";);
1934018d25dSMark Danial return Instr;
1944018d25dSMark Danial
1954018d25dSMark Danial case OuterLoopLowerBoundUnknown:
1964018d25dSMark Danial LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "
1974018d25dSMark Danial << OuterLoop << "\nInstruction vector is empty.\n";);
1984018d25dSMark Danial return Instr;
1994018d25dSMark Danial
2004018d25dSMark Danial case ImperfectLoopNest:
2014018d25dSMark Danial break;
2024018d25dSMark Danial }
2034018d25dSMark Danial
2044018d25dSMark Danial // Identify the outer loop latch comparison instruction.
2054018d25dSMark Danial auto OuterLoopLB = OuterLoop.getBounds(SE);
2064018d25dSMark Danial
2074018d25dSMark Danial CmpInst *OuterLoopLatchCmp = getOuterLoopLatchCmp(OuterLoop);
2084018d25dSMark Danial CmpInst *InnerLoopGuardCmp = getInnerLoopGuardCmp(InnerLoop);
2094018d25dSMark Danial
2104018d25dSMark Danial auto GetUnsafeInstructions = [&](const BasicBlock &BB) {
2114018d25dSMark Danial for (const Instruction &I : BB) {
2124018d25dSMark Danial if (!checkSafeInstruction(I, InnerLoopGuardCmp, OuterLoopLatchCmp,
2134018d25dSMark Danial OuterLoopLB)) {
2144018d25dSMark Danial Instr.push_back(&I);
2154018d25dSMark Danial DEBUG_WITH_TYPE(VerboseDebug, {
2164018d25dSMark Danial dbgs() << "Instruction: " << I << "\nin basic block:" << BB
2174018d25dSMark Danial << "is unsafe.\n";
2184018d25dSMark Danial });
2194018d25dSMark Danial }
2204018d25dSMark Danial }
2214018d25dSMark Danial };
2224018d25dSMark Danial
2234018d25dSMark Danial // Check the code surrounding the inner loop for instructions that are deemed
2244018d25dSMark Danial // unsafe.
2254018d25dSMark Danial const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
2264018d25dSMark Danial const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
2274018d25dSMark Danial const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
2284018d25dSMark Danial const BasicBlock *InnerLoopExitBlock = InnerLoop.getExitBlock();
2294018d25dSMark Danial
2304018d25dSMark Danial GetUnsafeInstructions(*OuterLoopHeader);
2314018d25dSMark Danial GetUnsafeInstructions(*OuterLoopLatch);
2324018d25dSMark Danial GetUnsafeInstructions(*InnerLoopExitBlock);
2334018d25dSMark Danial
2344018d25dSMark Danial if (InnerLoopPreHeader != OuterLoopHeader) {
2354018d25dSMark Danial GetUnsafeInstructions(*InnerLoopPreHeader);
2364018d25dSMark Danial }
2374018d25dSMark Danial return Instr;
238c84532a7SWhitney Tsang }
239c84532a7SWhitney Tsang
240c84532a7SWhitney Tsang SmallVector<LoopVectorTy, 4>
getPerfectLoops(ScalarEvolution & SE) const241c84532a7SWhitney Tsang LoopNest::getPerfectLoops(ScalarEvolution &SE) const {
242c84532a7SWhitney Tsang SmallVector<LoopVectorTy, 4> LV;
243c84532a7SWhitney Tsang LoopVectorTy PerfectNest;
244c84532a7SWhitney Tsang
245c84532a7SWhitney Tsang for (Loop *L : depth_first(const_cast<Loop *>(Loops.front()))) {
246c84532a7SWhitney Tsang if (PerfectNest.empty())
247c84532a7SWhitney Tsang PerfectNest.push_back(L);
248c84532a7SWhitney Tsang
249c84532a7SWhitney Tsang auto &SubLoops = L->getSubLoops();
250c84532a7SWhitney Tsang if (SubLoops.size() == 1 && arePerfectlyNested(*L, *SubLoops.front(), SE)) {
251c84532a7SWhitney Tsang PerfectNest.push_back(SubLoops.front());
252c84532a7SWhitney Tsang } else {
253c84532a7SWhitney Tsang LV.push_back(PerfectNest);
254c84532a7SWhitney Tsang PerfectNest.clear();
255c84532a7SWhitney Tsang }
256c84532a7SWhitney Tsang }
257c84532a7SWhitney Tsang
258c84532a7SWhitney Tsang return LV;
259c84532a7SWhitney Tsang }
260c84532a7SWhitney Tsang
getMaxPerfectDepth(const Loop & Root,ScalarEvolution & SE)261c84532a7SWhitney Tsang unsigned LoopNest::getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE) {
262c84532a7SWhitney Tsang LLVM_DEBUG(dbgs() << "Get maximum perfect depth of loop nest rooted by loop '"
263c84532a7SWhitney Tsang << Root.getName() << "'\n");
264c84532a7SWhitney Tsang
265c84532a7SWhitney Tsang const Loop *CurrentLoop = &Root;
266c84532a7SWhitney Tsang const auto *SubLoops = &CurrentLoop->getSubLoops();
267c84532a7SWhitney Tsang unsigned CurrentDepth = 1;
268c84532a7SWhitney Tsang
269c84532a7SWhitney Tsang while (SubLoops->size() == 1) {
270c84532a7SWhitney Tsang const Loop *InnerLoop = SubLoops->front();
271c84532a7SWhitney Tsang if (!arePerfectlyNested(*CurrentLoop, *InnerLoop, SE)) {
272c84532a7SWhitney Tsang LLVM_DEBUG({
273c84532a7SWhitney Tsang dbgs() << "Not a perfect nest: loop '" << CurrentLoop->getName()
274c84532a7SWhitney Tsang << "' is not perfectly nested with loop '"
275c84532a7SWhitney Tsang << InnerLoop->getName() << "'\n";
276c84532a7SWhitney Tsang });
277c84532a7SWhitney Tsang break;
278c84532a7SWhitney Tsang }
279c84532a7SWhitney Tsang
280c84532a7SWhitney Tsang CurrentLoop = InnerLoop;
281c84532a7SWhitney Tsang SubLoops = &CurrentLoop->getSubLoops();
282c84532a7SWhitney Tsang ++CurrentDepth;
283c84532a7SWhitney Tsang }
284c84532a7SWhitney Tsang
285c84532a7SWhitney Tsang return CurrentDepth;
286c84532a7SWhitney Tsang }
287c84532a7SWhitney Tsang
skipEmptyBlockUntil(const BasicBlock * From,const BasicBlock * End,bool CheckUniquePred)288c0055189SWhitney Tsang const BasicBlock &LoopNest::skipEmptyBlockUntil(const BasicBlock *From,
2891006ac39SWhitney Tsang const BasicBlock *End,
2901006ac39SWhitney Tsang bool CheckUniquePred) {
291c0055189SWhitney Tsang assert(From && "Expecting valid From");
292c0055189SWhitney Tsang assert(End && "Expecting valid End");
293c0055189SWhitney Tsang
29498c6110dSTa-Wei Tu if (From == End || !From->getUniqueSuccessor())
295c0055189SWhitney Tsang return *From;
296c0055189SWhitney Tsang
297c0055189SWhitney Tsang auto IsEmpty = [](const BasicBlock *BB) {
298c0055189SWhitney Tsang return (BB->getInstList().size() == 1);
299c0055189SWhitney Tsang };
300c0055189SWhitney Tsang
301c0055189SWhitney Tsang // Visited is used to avoid running into an infinite loop.
302c0055189SWhitney Tsang SmallPtrSet<const BasicBlock *, 4> Visited;
30398c6110dSTa-Wei Tu const BasicBlock *BB = From->getUniqueSuccessor();
3041006ac39SWhitney Tsang const BasicBlock *PredBB = From;
3051006ac39SWhitney Tsang while (BB && BB != End && IsEmpty(BB) && !Visited.count(BB) &&
3061006ac39SWhitney Tsang (!CheckUniquePred || BB->getUniquePredecessor())) {
307c0055189SWhitney Tsang Visited.insert(BB);
308c0055189SWhitney Tsang PredBB = BB;
30998c6110dSTa-Wei Tu BB = BB->getUniqueSuccessor();
310c0055189SWhitney Tsang }
311c0055189SWhitney Tsang
312c0055189SWhitney Tsang return (BB == End) ? *End : *PredBB;
313c0055189SWhitney Tsang }
314c0055189SWhitney Tsang
checkLoopsStructure(const Loop & OuterLoop,const Loop & InnerLoop,ScalarEvolution & SE)3157ff2768bSTa-Wei Tu static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
316c84532a7SWhitney Tsang ScalarEvolution &SE) {
317c84532a7SWhitney Tsang // The inner loop must be the only outer loop's child.
318c84532a7SWhitney Tsang if ((OuterLoop.getSubLoops().size() != 1) ||
319c84532a7SWhitney Tsang (InnerLoop.getParentLoop() != &OuterLoop))
320c84532a7SWhitney Tsang return false;
321c84532a7SWhitney Tsang
322c84532a7SWhitney Tsang // We expect loops in normal form which have a preheader, header, latch...
323c84532a7SWhitney Tsang if (!OuterLoop.isLoopSimplifyForm() || !InnerLoop.isLoopSimplifyForm())
324c84532a7SWhitney Tsang return false;
325c84532a7SWhitney Tsang
326c84532a7SWhitney Tsang const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
327c84532a7SWhitney Tsang const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
328c84532a7SWhitney Tsang const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
329c84532a7SWhitney Tsang const BasicBlock *InnerLoopLatch = InnerLoop.getLoopLatch();
330c84532a7SWhitney Tsang const BasicBlock *InnerLoopExit = InnerLoop.getExitBlock();
331c84532a7SWhitney Tsang
332c84532a7SWhitney Tsang // We expect rotated loops. The inner loop should have a single exit block.
333c84532a7SWhitney Tsang if (OuterLoop.getExitingBlock() != OuterLoopLatch ||
334c84532a7SWhitney Tsang InnerLoop.getExitingBlock() != InnerLoopLatch || !InnerLoopExit)
335c84532a7SWhitney Tsang return false;
336c84532a7SWhitney Tsang
337abbd652dSTa-Wei Tu // Returns whether the block `ExitBlock` contains at least one LCSSA Phi node.
338abbd652dSTa-Wei Tu auto ContainsLCSSAPhi = [](const BasicBlock &ExitBlock) {
339abbd652dSTa-Wei Tu return any_of(ExitBlock.phis(), [](const PHINode &PN) {
340abbd652dSTa-Wei Tu return PN.getNumIncomingValues() == 1;
341abbd652dSTa-Wei Tu });
342abbd652dSTa-Wei Tu };
343abbd652dSTa-Wei Tu
344abbd652dSTa-Wei Tu // Returns whether the block `BB` qualifies for being an extra Phi block. The
345abbd652dSTa-Wei Tu // extra Phi block is the additional block inserted after the exit block of an
346abbd652dSTa-Wei Tu // "guarded" inner loop which contains "only" Phi nodes corresponding to the
347abbd652dSTa-Wei Tu // LCSSA Phi nodes in the exit block.
348abbd652dSTa-Wei Tu auto IsExtraPhiBlock = [&](const BasicBlock &BB) {
349abbd652dSTa-Wei Tu return BB.getFirstNonPHI() == BB.getTerminator() &&
350abbd652dSTa-Wei Tu all_of(BB.phis(), [&](const PHINode &PN) {
351abbd652dSTa-Wei Tu return all_of(PN.blocks(), [&](const BasicBlock *IncomingBlock) {
352abbd652dSTa-Wei Tu return IncomingBlock == InnerLoopExit ||
353abbd652dSTa-Wei Tu IncomingBlock == OuterLoopHeader;
354abbd652dSTa-Wei Tu });
355abbd652dSTa-Wei Tu });
356abbd652dSTa-Wei Tu };
357abbd652dSTa-Wei Tu
358abbd652dSTa-Wei Tu const BasicBlock *ExtraPhiBlock = nullptr;
359c84532a7SWhitney Tsang // Ensure the only branch that may exist between the loops is the inner loop
360c84532a7SWhitney Tsang // guard.
361c84532a7SWhitney Tsang if (OuterLoopHeader != InnerLoopPreHeader) {
362c0055189SWhitney Tsang const BasicBlock &SingleSucc =
363c0055189SWhitney Tsang LoopNest::skipEmptyBlockUntil(OuterLoopHeader, InnerLoopPreHeader);
364c0055189SWhitney Tsang
365c0055189SWhitney Tsang // no conditional branch present
366c0055189SWhitney Tsang if (&SingleSucc != InnerLoopPreHeader) {
367c0055189SWhitney Tsang const BranchInst *BI = dyn_cast<BranchInst>(SingleSucc.getTerminator());
368c84532a7SWhitney Tsang
369c84532a7SWhitney Tsang if (!BI || BI != InnerLoop.getLoopGuardBranch())
370c84532a7SWhitney Tsang return false;
371c84532a7SWhitney Tsang
372abbd652dSTa-Wei Tu bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
373abbd652dSTa-Wei Tu
374c84532a7SWhitney Tsang // The successors of the inner loop guard should be the inner loop
375c0055189SWhitney Tsang // preheader or the outer loop latch possibly through empty blocks.
376c84532a7SWhitney Tsang for (const BasicBlock *Succ : BI->successors()) {
377c0055189SWhitney Tsang const BasicBlock *PotentialInnerPreHeader = Succ;
378c0055189SWhitney Tsang const BasicBlock *PotentialOuterLatch = Succ;
379c0055189SWhitney Tsang
380c0055189SWhitney Tsang // Ensure the inner loop guard successor is empty before skipping
381c0055189SWhitney Tsang // blocks.
382c0055189SWhitney Tsang if (Succ->getInstList().size() == 1) {
383c0055189SWhitney Tsang PotentialInnerPreHeader =
384c0055189SWhitney Tsang &LoopNest::skipEmptyBlockUntil(Succ, InnerLoopPreHeader);
385c0055189SWhitney Tsang PotentialOuterLatch =
386c0055189SWhitney Tsang &LoopNest::skipEmptyBlockUntil(Succ, OuterLoopLatch);
387c0055189SWhitney Tsang }
388c0055189SWhitney Tsang
389c0055189SWhitney Tsang if (PotentialInnerPreHeader == InnerLoopPreHeader)
390c84532a7SWhitney Tsang continue;
391c0055189SWhitney Tsang if (PotentialOuterLatch == OuterLoopLatch)
392c84532a7SWhitney Tsang continue;
393c84532a7SWhitney Tsang
394abbd652dSTa-Wei Tu // If `InnerLoopExit` contains LCSSA Phi instructions, additional block
395abbd652dSTa-Wei Tu // may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
396abbd652dSTa-Wei Tu // loops are still considered perfectly nested if the extra block only
397abbd652dSTa-Wei Tu // contains Phi instructions from InnerLoopExit and OuterLoopHeader.
398abbd652dSTa-Wei Tu if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
399abbd652dSTa-Wei Tu Succ->getSingleSuccessor() == OuterLoopLatch) {
400abbd652dSTa-Wei Tu // Points to the extra block so that we can reference it later in the
401abbd652dSTa-Wei Tu // final check. We can also conclude that the inner loop is
402c0055189SWhitney Tsang // guarded and there exists LCSSA Phi node in the exit block later if
403c0055189SWhitney Tsang // we see a non-null `ExtraPhiBlock`.
404abbd652dSTa-Wei Tu ExtraPhiBlock = Succ;
405abbd652dSTa-Wei Tu continue;
406abbd652dSTa-Wei Tu }
407abbd652dSTa-Wei Tu
408c84532a7SWhitney Tsang DEBUG_WITH_TYPE(VerboseDebug, {
409c84532a7SWhitney Tsang dbgs() << "Inner loop guard successor " << Succ->getName()
410c84532a7SWhitney Tsang << " doesn't lead to inner loop preheader or "
411c84532a7SWhitney Tsang "outer loop latch.\n";
412c84532a7SWhitney Tsang });
413c84532a7SWhitney Tsang return false;
414c84532a7SWhitney Tsang }
415c84532a7SWhitney Tsang }
416c0055189SWhitney Tsang }
417c84532a7SWhitney Tsang
418c0055189SWhitney Tsang // Ensure the inner loop exit block lead to the outer loop latch possibly
419c0055189SWhitney Tsang // through empty blocks.
4201006ac39SWhitney Tsang if ((!ExtraPhiBlock ||
4211006ac39SWhitney Tsang &LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
4221006ac39SWhitney Tsang ExtraPhiBlock) != ExtraPhiBlock) &&
4231006ac39SWhitney Tsang (&LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
4241006ac39SWhitney Tsang OuterLoopLatch) != OuterLoopLatch)) {
425c84532a7SWhitney Tsang DEBUG_WITH_TYPE(
426c84532a7SWhitney Tsang VerboseDebug,
427c84532a7SWhitney Tsang dbgs() << "Inner loop exit block " << *InnerLoopExit
428c84532a7SWhitney Tsang << " does not directly lead to the outer loop latch.\n";);
429c84532a7SWhitney Tsang return false;
430c84532a7SWhitney Tsang }
431c84532a7SWhitney Tsang
432c84532a7SWhitney Tsang return true;
433c84532a7SWhitney Tsang }
434c84532a7SWhitney Tsang
435fa3693adSWhitney Tsang AnalysisKey LoopNestAnalysis::Key;
436fa3693adSWhitney Tsang
operator <<(raw_ostream & OS,const LoopNest & LN)437c84532a7SWhitney Tsang raw_ostream &llvm::operator<<(raw_ostream &OS, const LoopNest &LN) {
438c84532a7SWhitney Tsang OS << "IsPerfect=";
439c84532a7SWhitney Tsang if (LN.getMaxPerfectDepth() == LN.getNestDepth())
440c84532a7SWhitney Tsang OS << "true";
441c84532a7SWhitney Tsang else
442c84532a7SWhitney Tsang OS << "false";
443c84532a7SWhitney Tsang OS << ", Depth=" << LN.getNestDepth();
444c84532a7SWhitney Tsang OS << ", OutermostLoop: " << LN.getOutermostLoop().getName();
445c84532a7SWhitney Tsang OS << ", Loops: ( ";
446c84532a7SWhitney Tsang for (const Loop *L : LN.getLoops())
447c84532a7SWhitney Tsang OS << L->getName() << " ";
448c84532a7SWhitney Tsang OS << ")";
449c84532a7SWhitney Tsang
450c84532a7SWhitney Tsang return OS;
451c84532a7SWhitney Tsang }
452c84532a7SWhitney Tsang
453c84532a7SWhitney Tsang //===----------------------------------------------------------------------===//
454c84532a7SWhitney Tsang // LoopNestPrinterPass implementation
455c84532a7SWhitney Tsang //
456c84532a7SWhitney Tsang
run(Loop & L,LoopAnalysisManager & AM,LoopStandardAnalysisResults & AR,LPMUpdater & U)457c84532a7SWhitney Tsang PreservedAnalyses LoopNestPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
458c84532a7SWhitney Tsang LoopStandardAnalysisResults &AR,
459c84532a7SWhitney Tsang LPMUpdater &U) {
460c84532a7SWhitney Tsang if (auto LN = LoopNest::getLoopNest(L, AR.SE))
461c84532a7SWhitney Tsang OS << *LN << "\n";
462c84532a7SWhitney Tsang
463c84532a7SWhitney Tsang return PreservedAnalyses::all();
464c84532a7SWhitney Tsang }
465