[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
//===- LoopNestAnalysis.cpp - Loop Nest Analysis --------------------------==//
|
|
|
|
//
|
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
///
|
|
|
|
/// \file
|
|
|
|
/// The implementation for the loop nest analysis.
|
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Analysis/LoopNestAnalysis.h"
|
|
|
|
#include "llvm/ADT/BreadthFirstIterator.h"
|
|
|
|
#include "llvm/ADT/Statistic.h"
|
|
|
|
#include "llvm/Analysis/PostDominators.h"
|
|
|
|
#include "llvm/Analysis/ValueTracking.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
#define DEBUG_TYPE "loopnest"
|
|
|
|
#ifndef NDEBUG
|
|
|
|
static const char *VerboseDebug = DEBUG_TYPE "-verbose";
|
|
|
|
#endif
|
|
|
|
|
2021-03-10 18:24:43 +01:00
|
|
|
/// Determine whether the loops structure violates basic requirements for
|
|
|
|
/// perfect nesting:
|
|
|
|
/// - the inner loop should be the outer loop's only child
|
|
|
|
/// - the outer loop header should 'flow' into the inner loop preheader
|
|
|
|
/// or jump around the inner loop to the outer loop latch
|
|
|
|
/// - if the inner loop latch exits the inner loop, it should 'flow' into
|
|
|
|
/// the outer loop latch.
|
|
|
|
/// Returns true if the loop structure satisfies the basic requirements and
|
|
|
|
/// false otherwise.
|
|
|
|
static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
|
|
|
|
ScalarEvolution &SE);
|
|
|
|
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LoopNest implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
LoopNest::LoopNest(Loop &Root, ScalarEvolution &SE)
|
|
|
|
: MaxPerfectDepth(getMaxPerfectDepth(Root, SE)) {
|
2021-01-23 08:25:01 +01:00
|
|
|
append_range(Loops, breadth_first(&Root));
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root,
|
|
|
|
ScalarEvolution &SE) {
|
|
|
|
return std::make_unique<LoopNest>(Root, SE);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop,
|
|
|
|
ScalarEvolution &SE) {
|
2020-09-22 22:28:00 +02:00
|
|
|
assert(!OuterLoop.isInnermost() && "Outer loop should have subloops");
|
|
|
|
assert(!InnerLoop.isOutermost() && "Inner loop should have a parent");
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName()
|
|
|
|
<< "' and '" << InnerLoop.getName()
|
|
|
|
<< "' are perfectly nested.\n");
|
|
|
|
|
|
|
|
// Determine whether the loops structure satisfies the following requirements:
|
|
|
|
// - the inner loop should be the outer loop's only child
|
|
|
|
// - the outer loop header should 'flow' into the inner loop preheader
|
|
|
|
// or jump around the inner loop to the outer loop latch
|
|
|
|
// - if the inner loop latch exits the inner loop, it should 'flow' into
|
|
|
|
// the outer loop latch.
|
|
|
|
if (!checkLoopsStructure(OuterLoop, InnerLoop, SE)) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Not perfectly nested: invalid loop structure.\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Bail out if we cannot retrieve the outer loop bounds.
|
|
|
|
auto OuterLoopLB = OuterLoop.getBounds(SE);
|
|
|
|
if (OuterLoopLB == None) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Cannot compute loop bounds of OuterLoop: "
|
|
|
|
<< OuterLoop << "\n";);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Identify the outer loop latch comparison instruction.
|
|
|
|
const BasicBlock *Latch = OuterLoop.getLoopLatch();
|
|
|
|
assert(Latch && "Expecting a valid loop latch");
|
|
|
|
const BranchInst *BI = dyn_cast<BranchInst>(Latch->getTerminator());
|
|
|
|
assert(BI && BI->isConditional() &&
|
|
|
|
"Expecting loop latch terminator to be a branch instruction");
|
|
|
|
|
|
|
|
const CmpInst *OuterLoopLatchCmp = dyn_cast<CmpInst>(BI->getCondition());
|
|
|
|
DEBUG_WITH_TYPE(
|
|
|
|
VerboseDebug, if (OuterLoopLatchCmp) {
|
|
|
|
dbgs() << "Outer loop latch compare instruction: " << *OuterLoopLatchCmp
|
|
|
|
<< "\n";
|
|
|
|
});
|
|
|
|
|
|
|
|
// Identify the inner loop guard instruction.
|
|
|
|
BranchInst *InnerGuard = InnerLoop.getLoopGuardBranch();
|
|
|
|
const CmpInst *InnerLoopGuardCmp =
|
|
|
|
(InnerGuard) ? dyn_cast<CmpInst>(InnerGuard->getCondition()) : nullptr;
|
|
|
|
|
|
|
|
DEBUG_WITH_TYPE(
|
|
|
|
VerboseDebug, if (InnerLoopGuardCmp) {
|
|
|
|
dbgs() << "Inner loop guard compare instruction: " << *InnerLoopGuardCmp
|
|
|
|
<< "\n";
|
|
|
|
});
|
|
|
|
|
|
|
|
// Determine whether instructions in a basic block are one of:
|
|
|
|
// - the inner loop guard comparison
|
|
|
|
// - the outer loop latch comparison
|
|
|
|
// - the outer loop induction variable increment
|
|
|
|
// - a phi node, a cast or a branch
|
|
|
|
auto containsOnlySafeInstructions = [&](const BasicBlock &BB) {
|
|
|
|
return llvm::all_of(BB, [&](const Instruction &I) {
|
|
|
|
bool isAllowed = isSafeToSpeculativelyExecute(&I) || isa<PHINode>(I) ||
|
|
|
|
isa<BranchInst>(I);
|
|
|
|
if (!isAllowed) {
|
|
|
|
DEBUG_WITH_TYPE(VerboseDebug, {
|
|
|
|
dbgs() << "Instruction: " << I << "\nin basic block: " << BB
|
|
|
|
<< " is considered unsafe.\n";
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The only binary instruction allowed is the outer loop step instruction,
|
|
|
|
// the only comparison instructions allowed are the inner loop guard
|
|
|
|
// compare instruction and the outer loop latch compare instruction.
|
|
|
|
if ((isa<BinaryOperator>(I) && &I != &OuterLoopLB->getStepInst()) ||
|
|
|
|
(isa<CmpInst>(I) && &I != OuterLoopLatchCmp &&
|
|
|
|
&I != InnerLoopGuardCmp)) {
|
|
|
|
DEBUG_WITH_TYPE(VerboseDebug, {
|
|
|
|
dbgs() << "Instruction: " << I << "\nin basic block:" << BB
|
|
|
|
<< "is unsafe.\n";
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Check the code surrounding the inner loop for instructions that are deemed
|
|
|
|
// unsafe.
|
|
|
|
const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
|
|
|
|
const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
|
|
|
|
const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
|
|
|
|
|
|
|
|
if (!containsOnlySafeInstructions(*OuterLoopHeader) ||
|
|
|
|
!containsOnlySafeInstructions(*OuterLoopLatch) ||
|
|
|
|
(InnerLoopPreHeader != OuterLoopHeader &&
|
|
|
|
!containsOnlySafeInstructions(*InnerLoopPreHeader)) ||
|
|
|
|
!containsOnlySafeInstructions(*InnerLoop.getExitBlock())) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Not perfectly nested: code surrounding inner loop is "
|
|
|
|
"unsafe\n";);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LLVM_DEBUG(dbgs() << "Loop '" << OuterLoop.getName() << "' and '"
|
|
|
|
<< InnerLoop.getName() << "' are perfectly nested.\n");
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
SmallVector<LoopVectorTy, 4>
|
|
|
|
LoopNest::getPerfectLoops(ScalarEvolution &SE) const {
|
|
|
|
SmallVector<LoopVectorTy, 4> LV;
|
|
|
|
LoopVectorTy PerfectNest;
|
|
|
|
|
|
|
|
for (Loop *L : depth_first(const_cast<Loop *>(Loops.front()))) {
|
|
|
|
if (PerfectNest.empty())
|
|
|
|
PerfectNest.push_back(L);
|
|
|
|
|
|
|
|
auto &SubLoops = L->getSubLoops();
|
|
|
|
if (SubLoops.size() == 1 && arePerfectlyNested(*L, *SubLoops.front(), SE)) {
|
|
|
|
PerfectNest.push_back(SubLoops.front());
|
|
|
|
} else {
|
|
|
|
LV.push_back(PerfectNest);
|
|
|
|
PerfectNest.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return LV;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned LoopNest::getMaxPerfectDepth(const Loop &Root, ScalarEvolution &SE) {
|
|
|
|
LLVM_DEBUG(dbgs() << "Get maximum perfect depth of loop nest rooted by loop '"
|
|
|
|
<< Root.getName() << "'\n");
|
|
|
|
|
|
|
|
const Loop *CurrentLoop = &Root;
|
|
|
|
const auto *SubLoops = &CurrentLoop->getSubLoops();
|
|
|
|
unsigned CurrentDepth = 1;
|
|
|
|
|
|
|
|
while (SubLoops->size() == 1) {
|
|
|
|
const Loop *InnerLoop = SubLoops->front();
|
|
|
|
if (!arePerfectlyNested(*CurrentLoop, *InnerLoop, SE)) {
|
|
|
|
LLVM_DEBUG({
|
|
|
|
dbgs() << "Not a perfect nest: loop '" << CurrentLoop->getName()
|
|
|
|
<< "' is not perfectly nested with loop '"
|
|
|
|
<< InnerLoop->getName() << "'\n";
|
|
|
|
});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CurrentLoop = InnerLoop;
|
|
|
|
SubLoops = &CurrentLoop->getSubLoops();
|
|
|
|
++CurrentDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CurrentDepth;
|
|
|
|
}
|
|
|
|
|
2021-01-05 16:08:46 +01:00
|
|
|
const BasicBlock &LoopNest::skipEmptyBlockUntil(const BasicBlock *From,
|
2021-05-07 17:36:55 +02:00
|
|
|
const BasicBlock *End,
|
|
|
|
bool CheckUniquePred) {
|
2021-01-05 16:08:46 +01:00
|
|
|
assert(From && "Expecting valid From");
|
|
|
|
assert(End && "Expecting valid End");
|
|
|
|
|
2021-02-24 02:52:46 +01:00
|
|
|
if (From == End || !From->getUniqueSuccessor())
|
2021-01-05 16:08:46 +01:00
|
|
|
return *From;
|
|
|
|
|
|
|
|
auto IsEmpty = [](const BasicBlock *BB) {
|
|
|
|
return (BB->getInstList().size() == 1);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Visited is used to avoid running into an infinite loop.
|
|
|
|
SmallPtrSet<const BasicBlock *, 4> Visited;
|
2021-02-24 02:52:46 +01:00
|
|
|
const BasicBlock *BB = From->getUniqueSuccessor();
|
2021-05-07 17:36:55 +02:00
|
|
|
const BasicBlock *PredBB = From;
|
|
|
|
while (BB && BB != End && IsEmpty(BB) && !Visited.count(BB) &&
|
|
|
|
(!CheckUniquePred || BB->getUniquePredecessor())) {
|
2021-01-05 16:08:46 +01:00
|
|
|
Visited.insert(BB);
|
|
|
|
PredBB = BB;
|
2021-02-24 02:52:46 +01:00
|
|
|
BB = BB->getUniqueSuccessor();
|
2021-01-05 16:08:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return (BB == End) ? *End : *PredBB;
|
|
|
|
}
|
|
|
|
|
2021-03-10 18:24:43 +01:00
|
|
|
static bool checkLoopsStructure(const Loop &OuterLoop, const Loop &InnerLoop,
|
|
|
|
ScalarEvolution &SE) {
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
// The inner loop must be the only outer loop's child.
|
|
|
|
if ((OuterLoop.getSubLoops().size() != 1) ||
|
|
|
|
(InnerLoop.getParentLoop() != &OuterLoop))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// We expect loops in normal form which have a preheader, header, latch...
|
|
|
|
if (!OuterLoop.isLoopSimplifyForm() || !InnerLoop.isLoopSimplifyForm())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
const BasicBlock *OuterLoopHeader = OuterLoop.getHeader();
|
|
|
|
const BasicBlock *OuterLoopLatch = OuterLoop.getLoopLatch();
|
|
|
|
const BasicBlock *InnerLoopPreHeader = InnerLoop.getLoopPreheader();
|
|
|
|
const BasicBlock *InnerLoopLatch = InnerLoop.getLoopLatch();
|
|
|
|
const BasicBlock *InnerLoopExit = InnerLoop.getExitBlock();
|
|
|
|
|
|
|
|
// We expect rotated loops. The inner loop should have a single exit block.
|
|
|
|
if (OuterLoop.getExitingBlock() != OuterLoopLatch ||
|
|
|
|
InnerLoop.getExitingBlock() != InnerLoopLatch || !InnerLoopExit)
|
|
|
|
return false;
|
|
|
|
|
2020-08-25 18:17:01 +02:00
|
|
|
// Returns whether the block `ExitBlock` contains at least one LCSSA Phi node.
|
|
|
|
auto ContainsLCSSAPhi = [](const BasicBlock &ExitBlock) {
|
|
|
|
return any_of(ExitBlock.phis(), [](const PHINode &PN) {
|
|
|
|
return PN.getNumIncomingValues() == 1;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
// Returns whether the block `BB` qualifies for being an extra Phi block. The
|
|
|
|
// extra Phi block is the additional block inserted after the exit block of an
|
|
|
|
// "guarded" inner loop which contains "only" Phi nodes corresponding to the
|
|
|
|
// LCSSA Phi nodes in the exit block.
|
|
|
|
auto IsExtraPhiBlock = [&](const BasicBlock &BB) {
|
|
|
|
return BB.getFirstNonPHI() == BB.getTerminator() &&
|
|
|
|
all_of(BB.phis(), [&](const PHINode &PN) {
|
|
|
|
return all_of(PN.blocks(), [&](const BasicBlock *IncomingBlock) {
|
|
|
|
return IncomingBlock == InnerLoopExit ||
|
|
|
|
IncomingBlock == OuterLoopHeader;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
const BasicBlock *ExtraPhiBlock = nullptr;
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
// Ensure the only branch that may exist between the loops is the inner loop
|
|
|
|
// guard.
|
|
|
|
if (OuterLoopHeader != InnerLoopPreHeader) {
|
2021-01-05 16:08:46 +01:00
|
|
|
const BasicBlock &SingleSucc =
|
|
|
|
LoopNest::skipEmptyBlockUntil(OuterLoopHeader, InnerLoopPreHeader);
|
2021-01-04 21:41:53 +01:00
|
|
|
|
2021-01-05 16:08:46 +01:00
|
|
|
// no conditional branch present
|
|
|
|
if (&SingleSucc != InnerLoopPreHeader) {
|
|
|
|
const BranchInst *BI = dyn_cast<BranchInst>(SingleSucc.getTerminator());
|
|
|
|
|
|
|
|
if (!BI || BI != InnerLoop.getLoopGuardBranch())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bool InnerLoopExitContainsLCSSA = ContainsLCSSAPhi(*InnerLoopExit);
|
|
|
|
|
|
|
|
// The successors of the inner loop guard should be the inner loop
|
|
|
|
// preheader or the outer loop latch possibly through empty blocks.
|
|
|
|
for (const BasicBlock *Succ : BI->successors()) {
|
|
|
|
const BasicBlock *PotentialInnerPreHeader = Succ;
|
|
|
|
const BasicBlock *PotentialOuterLatch = Succ;
|
|
|
|
|
|
|
|
// Ensure the inner loop guard successor is empty before skipping
|
|
|
|
// blocks.
|
|
|
|
if (Succ->getInstList().size() == 1) {
|
|
|
|
PotentialInnerPreHeader =
|
|
|
|
&LoopNest::skipEmptyBlockUntil(Succ, InnerLoopPreHeader);
|
|
|
|
PotentialOuterLatch =
|
|
|
|
&LoopNest::skipEmptyBlockUntil(Succ, OuterLoopLatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PotentialInnerPreHeader == InnerLoopPreHeader)
|
|
|
|
continue;
|
|
|
|
if (PotentialOuterLatch == OuterLoopLatch)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// If `InnerLoopExit` contains LCSSA Phi instructions, additional block
|
|
|
|
// may be inserted before the `OuterLoopLatch` to which `BI` jumps. The
|
|
|
|
// loops are still considered perfectly nested if the extra block only
|
|
|
|
// contains Phi instructions from InnerLoopExit and OuterLoopHeader.
|
|
|
|
if (InnerLoopExitContainsLCSSA && IsExtraPhiBlock(*Succ) &&
|
|
|
|
Succ->getSingleSuccessor() == OuterLoopLatch) {
|
|
|
|
// Points to the extra block so that we can reference it later in the
|
|
|
|
// final check. We can also conclude that the inner loop is
|
|
|
|
// guarded and there exists LCSSA Phi node in the exit block later if
|
|
|
|
// we see a non-null `ExtraPhiBlock`.
|
|
|
|
ExtraPhiBlock = Succ;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_WITH_TYPE(VerboseDebug, {
|
|
|
|
dbgs() << "Inner loop guard successor " << Succ->getName()
|
|
|
|
<< " doesn't lead to inner loop preheader or "
|
|
|
|
"outer loop latch.\n";
|
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-05 16:08:46 +01:00
|
|
|
// Ensure the inner loop exit block lead to the outer loop latch possibly
|
|
|
|
// through empty blocks.
|
2021-05-07 17:36:55 +02:00
|
|
|
if ((!ExtraPhiBlock ||
|
|
|
|
&LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
|
|
|
|
ExtraPhiBlock) != ExtraPhiBlock) &&
|
|
|
|
(&LoopNest::skipEmptyBlockUntil(InnerLoop.getExitBlock(),
|
|
|
|
OuterLoopLatch) != OuterLoopLatch)) {
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
DEBUG_WITH_TYPE(
|
|
|
|
VerboseDebug,
|
|
|
|
dbgs() << "Inner loop exit block " << *InnerLoopExit
|
|
|
|
<< " does not directly lead to the outer loop latch.\n";);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-12-16 18:05:44 +01:00
|
|
|
AnalysisKey LoopNestAnalysis::Key;
|
|
|
|
|
[LoopNest]: Analysis to discover properties of a loop nest.
Summary: This patch adds an analysis pass to collect loop nests and
summarize properties of the nest (e.g the nest depth, whether the nest
is perfect, what's the innermost loop, etc...).
The motivation for this patch was discussed at the latest meeting of the
LLVM loop group (https://ibm.box.com/v/llvm-loop-nest-analysis) where we
discussed
the unimodular loop transformation framework ( “A Loop Transformation
Theory and an Algorithm to Maximize Parallelism”, Michael E. Wolf and
Monica S. Lam, IEEE TPDS, October 1991). The unimodular framework
provides a convenient way to unify legality checking and code generation
for several loop nest transformations (e.g. loop reversal, loop
interchange, loop skewing) and their compositions. Given that the
unimodular framework is applicable to perfect loop nests this is one
property of interest we expose in this analysis. Several other utility
functions are also provided. In the future other properties of interest
can be added in a centralized place.
Authored By: etiotto
Reviewer: Meinersbur, bmahjour, kbarton, Whitney, dmgreen, fhahn,
reames, hfinkel, jdoerfert, ppc-slack
Reviewed By: Meinersbur
Subscribers: bryanpkc, ppc-slack, mgorny, hiraditya, llvm-commits
Tag: LLVM
Differential Revision: https://reviews.llvm.org/D68789
2020-03-03 18:38:19 +01:00
|
|
|
raw_ostream &llvm::operator<<(raw_ostream &OS, const LoopNest &LN) {
|
|
|
|
OS << "IsPerfect=";
|
|
|
|
if (LN.getMaxPerfectDepth() == LN.getNestDepth())
|
|
|
|
OS << "true";
|
|
|
|
else
|
|
|
|
OS << "false";
|
|
|
|
OS << ", Depth=" << LN.getNestDepth();
|
|
|
|
OS << ", OutermostLoop: " << LN.getOutermostLoop().getName();
|
|
|
|
OS << ", Loops: ( ";
|
|
|
|
for (const Loop *L : LN.getLoops())
|
|
|
|
OS << L->getName() << " ";
|
|
|
|
OS << ")";
|
|
|
|
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LoopNestPrinterPass implementation
|
|
|
|
//
|
|
|
|
|
|
|
|
PreservedAnalyses LoopNestPrinterPass::run(Loop &L, LoopAnalysisManager &AM,
|
|
|
|
LoopStandardAnalysisResults &AR,
|
|
|
|
LPMUpdater &U) {
|
|
|
|
if (auto LN = LoopNest::getLoopNest(L, AR.SE))
|
|
|
|
OS << *LN << "\n";
|
|
|
|
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|