[LoopInfo] empty() -> isInnermost(), add isOutermost()

Differential Revision: https://reviews.llvm.org/D82895
This commit is contained in:
Stefanos Baziotis 2020-09-22 23:28:00 +03:00
parent 4edb3d3646
commit 89c1e35f3c
26 changed files with 57 additions and 47 deletions

View File

@ -155,7 +155,17 @@ public:
iterator end() const { return getSubLoops().end(); }
reverse_iterator rbegin() const { return getSubLoops().rbegin(); }
reverse_iterator rend() const { return getSubLoops().rend(); }
bool empty() const { return getSubLoops().empty(); }
// LoopInfo does not detect irreducible control flow, just natural
// loops. That is, it is possible that there is cyclic control
// flow within the "innermost loop" or around the "outermost
// loop".
/// Return true if the loop does not contain any (natural) loops.
bool isInnermost() const { return getSubLoops().empty(); }
/// Return true if the loop does not have a parent (natural) loop
// (i.e. it is outermost, which is the same as top-level).
bool isOutermost() const { return getParentLoop() == nullptr; }
/// Get a list of the basic blocks which make up this loop.
ArrayRef<BlockT *> getBlocks() const {
@ -974,7 +984,7 @@ public:
LoopT *removeLoop(iterator I) {
assert(I != end() && "Cannot remove end iterator!");
LoopT *L = *I;
assert(!L->getParentLoop() && "Not a top-level loop!");
assert(L->isOutermost() && "Not a top-level loop!");
TopLevelLoops.erase(TopLevelLoops.begin() + (I - begin()));
return L;
}
@ -1002,7 +1012,7 @@ public:
/// This adds the specified loop to the collection of top-level loops.
void addTopLevelLoop(LoopT *New) {
assert(!New->getParentLoop() && "Loop already in subloop!");
assert(New->isOutermost() && "Loop already in subloop!");
TopLevelLoops.push_back(New);
}

View File

@ -502,7 +502,7 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
if (Subloop && Block == Subloop->getHeader()) {
// We reach this point once per subloop after processing all the blocks in
// the subloop.
if (Subloop->getParentLoop())
if (!Subloop->isOutermost())
Subloop->getParentLoop()->getSubLoopsVector().push_back(Subloop);
else
LI->addTopLevelLoop(Subloop);
@ -681,7 +681,7 @@ void LoopInfoBase<BlockT, LoopT>::verify(
const DomTreeBase<BlockT> &DomTree) const {
DenseSet<const LoopT *> Loops;
for (iterator I = begin(), E = end(); I != E; ++I) {
assert(!(*I)->getParentLoop() && "Top-level loop has a parent!");
assert((*I)->isOutermost() && "Top-level loop has a parent!");
(*I)->verifyLoopNest(&Loops);
}

View File

@ -1769,7 +1769,7 @@ bool LoopAccessInfo::canAnalyzeLoop() {
<< TheLoop->getHeader()->getName() << '\n');
// We can only analyze innermost loops.
if (!TheLoop->empty()) {
if (!TheLoop->isInnermost()) {
LLVM_DEBUG(dbgs() << "LAA: loop is not the innermost loop\n");
recordAnalysis("NotInnerMostLoop") << "loop is not the innermost loop";
return false;

View File

@ -499,7 +499,7 @@ CacheCost::CacheCost(const LoopVectorTy &Loops, const LoopInfo &LI,
std::unique_ptr<CacheCost>
CacheCost::getCacheCost(Loop &Root, LoopStandardAnalysisResults &AR,
DependenceInfo &DI, Optional<unsigned> TRT) {
if (Root.getParentLoop()) {
if (!Root.isOutermost()) {
LLVM_DEBUG(dbgs() << "Expecting the outermost loop in a loop nest\n");
return nullptr;
}

View File

@ -764,7 +764,7 @@ void UnloopUpdater::removeBlocksFromAncestors() {
/// Update the parent loop for all subloops directly nested within unloop.
void UnloopUpdater::updateSubloopParents() {
while (!Unloop.empty()) {
while (!Unloop.isInnermost()) {
Loop *Subloop = *std::prev(Unloop.end());
Unloop.removeChildLoop(std::prev(Unloop.end()));
@ -862,7 +862,7 @@ void LoopInfo::erase(Loop *Unloop) {
auto InvalidateOnExit = make_scope_exit([&]() { destroy(Unloop); });
// First handle the special case of no parent loop to simplify the algorithm.
if (!Unloop->getParentLoop()) {
if (Unloop->isOutermost()) {
// Since BBLoop had no parent, Unloop blocks are no longer in a loop.
for (Loop::block_iterator I = Unloop->block_begin(),
E = Unloop->block_end();
@ -887,7 +887,7 @@ void LoopInfo::erase(Loop *Unloop) {
}
// Move all of the subloops to the top-level.
while (!Unloop->empty())
while (!Unloop->isInnermost())
addTopLevelLoop(Unloop->removeChildLoop(std::prev(Unloop->end())));
return;

View File

@ -53,8 +53,8 @@ std::unique_ptr<LoopNest> LoopNest::getLoopNest(Loop &Root,
bool LoopNest::arePerfectlyNested(const Loop &OuterLoop, const Loop &InnerLoop,
ScalarEvolution &SE) {
assert(!OuterLoop.getSubLoops().empty() && "Outer loop should have subloops");
assert(InnerLoop.getParentLoop() && "Inner loop should have a parent");
assert(!OuterLoop.isInnermost() && "Outer loop should have subloops");
assert(!InnerLoop.isOutermost() && "Inner loop should have a parent");
LLVM_DEBUG(dbgs() << "Checking whether loop '" << OuterLoop.getName()
<< "' and '" << InnerLoop.getName()
<< "' are perfectly nested.\n");

View File

@ -77,7 +77,7 @@ LPPassManager::LPPassManager()
// Insert loop into loop nest (LoopInfo) and loop queue (LQ).
void LPPassManager::addLoop(Loop &L) {
if (!L.getParentLoop()) {
if (L.isOutermost()) {
// This is the top level loop.
LQ.push_front(&L);
return;

View File

@ -3022,7 +3022,7 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,
OS.indent(Loop->getLoopDepth()*2-2);
OS << "This ";
if (Loop->empty())
if (Loop->isInnermost())
OS << "Inner ";
OS << "Loop Header: Depth=" + Twine(Loop->getLoopDepth()) << '\n';

View File

@ -234,7 +234,7 @@ bool HardwareLoops::runOnFunction(Function &F) {
for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) {
Loop *L = *I;
if (!L->getParentLoop())
if (L->isOutermost())
TryConvertLoop(L);
}

View File

@ -1043,7 +1043,7 @@ bool ARMLowOverheadLoops::runOnMachineFunction(MachineFunction &mf) {
bool Changed = false;
for (auto ML : *MLI) {
if (!ML->getParentLoop())
if (ML->isOutermost())
Changed |= ProcessLoop(ML);
}
Changed |= RevertNonLoops();

View File

@ -390,7 +390,7 @@ bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
TRI = HST.getRegisterInfo();
for (auto &L : *MLI)
if (!L->getParentLoop()) {
if (L->isOutermost()) {
bool L0Used = false;
bool L1Used = false;
Changed |= convertToHardwareLoop(L, L0Used, L1Used);

View File

@ -449,7 +449,7 @@ bool LoopInvariantCodeMotion::runOnLoop(
// specifically moving instructions across the loop boundary and so it is
// especially in need of sanity checking here.
assert(L->isLCSSAForm(*DT) && "Loop not left in LCSSA form after LICM!");
assert((!L->getParentLoop() || L->getParentLoop()->isLCSSAForm(*DT)) &&
assert((L->isOutermost() || L->getParentLoop()->isLCSSAForm(*DT)) &&
"Parent loop not left in LCSSA form after LICM!");
if (MSSAU.get() && VerifyMemorySSA)

View File

@ -271,7 +271,7 @@ bool LoopDataPrefetch::runOnLoop(Loop *L) {
bool MadeChange = false;
// Only prefetch in the inner-most loop
if (!L->empty())
if (!L->isInnermost())
return MadeChange;
SmallPtrSet<const Value *, 32> EphValues;

View File

@ -664,7 +664,7 @@ public:
/// Try to distribute an inner-most loop.
bool processLoop(std::function<const LoopAccessInfo &(Loop &)> &GetLAA) {
assert(L->empty() && "Only process inner loops.");
assert(L->isInnermost() && "Only process inner loops.");
LLVM_DEBUG(dbgs() << "\nLDist: In \""
<< L->getHeader()->getParent()->getName()
@ -982,7 +982,7 @@ static bool runImpl(Function &F, LoopInfo *LI, DominatorTree *DT,
for (Loop *TopLevelLoop : *LI)
for (Loop *L : depth_first(TopLevelLoop))
// We only handle inner-most loops.
if (L->empty())
if (L->isInnermost())
Worklist.push_back(L);
// Now walk the identified inner loops.

View File

@ -1483,7 +1483,7 @@ private:
continue;
LI.changeLoopFor(BB, FC0.L);
}
while (!FC1.L->empty()) {
while (!FC1.L->isInnermost()) {
const auto &ChildLoopIt = FC1.L->begin();
Loop *ChildLoop = *ChildLoopIt;
FC1.L->removeChildLoop(ChildLoopIt);
@ -1777,7 +1777,7 @@ private:
continue;
LI.changeLoopFor(BB, FC0.L);
}
while (!FC1.L->empty()) {
while (!FC1.L->isInnermost()) {
const auto &ChildLoopIt = FC1.L->begin();
Loop *ChildLoop = *ChildLoopIt;
FC1.L->removeChildLoop(ChildLoopIt);

View File

@ -1211,7 +1211,7 @@ bool LoopIdiomRecognize::processLoopStoreOfLoopLoad(StoreInst *SI,
bool LoopIdiomRecognize::avoidLIRForMultiBlockLoop(bool IsMemset,
bool IsLoopMemset) {
if (ApplyCodeSizeHeuristics && CurLoop->getNumBlocks() > 1) {
if (!CurLoop->getParentLoop() && (!IsMemset || !IsLoopMemset)) {
if (CurLoop->isOutermost() && (!IsMemset || !IsLoopMemset)) {
LLVM_DEBUG(dbgs() << " " << CurLoop->getHeader()->getParent()->getName()
<< " : LIR " << (IsMemset ? "Memset" : "Memcpy")
<< " avoided: multi-block top-level loop\n");

View File

@ -1197,7 +1197,7 @@ void LoopInterchangeTransform::restructureLoops(
removeChildLoop(NewInner, NewOuter);
LI->changeTopLevelLoop(NewInner, NewOuter);
}
while (!NewOuter->empty())
while (!NewOuter->isInnermost())
NewInner->addChildLoop(NewOuter->removeChildLoop(NewOuter->begin()));
NewOuter->addChildLoop(NewInner);

View File

@ -623,7 +623,7 @@ eliminateLoadsAcrossLoops(Function &F, LoopInfo &LI, DominatorTree &DT,
for (Loop *TopLevelLoop : LI)
for (Loop *L : depth_first(TopLevelLoop))
// We only handle inner-most loops.
if (L->empty())
if (L->isInnermost())
Worklist.push_back(L);
// Now walk the identified inner loops.

View File

@ -452,7 +452,7 @@ private:
if (LI.isLoopHeader(BB)) {
assert(LI.getLoopFor(BB) != &L && "Attempt to remove current loop!");
Loop *DL = LI.getLoopFor(BB);
if (DL->getParentLoop()) {
if (!DL->isOutermost()) {
for (auto *PL = DL->getParentLoop(); PL; PL = PL->getParentLoop())
for (auto *BB : DL->getBlocks())
PL->removeBlockFromLoop(BB);

View File

@ -5619,7 +5619,7 @@ LSRInstance::LSRInstance(Loop *L, IVUsers &IU, ScalarEvolution &SE,
if (IU.empty()) return;
// Skip nested loops until we can model them better with formulae.
if (!L->empty()) {
if (!L->isInnermost()) {
LLVM_DEBUG(dbgs() << "LSR skipping outer loop " << *L << "\n");
return;
}

View File

@ -345,7 +345,7 @@ static Optional<EstimatedUnrollCost> analyzeLoopUnrollCost(
// Only analyze inner loops. We can't properly estimate cost of nested loops
// and we won't visit inner loops again anyway.
if (!L->empty())
if (!L->isInnermost())
return None;
// Don't simulate loops with a big or unknown tripcount

View File

@ -1214,7 +1214,7 @@ static Loop *cloneLoopNest(Loop &OrigRootL, Loop *RootParentL,
LI.addTopLevelLoop(ClonedRootL);
AddClonedBlocksToLoop(OrigRootL, *ClonedRootL);
if (OrigRootL.empty())
if (OrigRootL.isInnermost())
return ClonedRootL;
// If we have a nest, we can quickly clone the entire loop nest using an
@ -2353,12 +2353,12 @@ static void unswitchNontrivialInvariants(
for (Loop *UpdatedL :
llvm::concat<Loop *>(NonChildClonedLoops, HoistedLoops)) {
UpdateLoop(*UpdatedL);
if (!UpdatedL->getParentLoop())
if (UpdatedL->isOutermost())
OuterExitL = nullptr;
}
if (IsStillLoop) {
UpdateLoop(L);
if (!L.getParentLoop())
if (L.isOutermost())
OuterExitL = nullptr;
}

View File

@ -304,7 +304,7 @@ void llvm::computePeelCount(Loop *L, unsigned LoopSize,
// Only try to peel innermost loops by default.
// The constraint can be relaxed by the target in TTI.getUnrollingPreferences
// or by the flag -unroll-allow-loop-nests-peeling.
if (!PP.AllowLoopNestsPeeling && !L->empty())
if (!PP.AllowLoopNestsPeeling && !L->isInnermost())
return;
// If the user provided a peel count, use that.

View File

@ -268,7 +268,7 @@ bool runImpl(LoopInfo *LI, function_ref<const LoopAccessInfo &(Loop &)> GetLAA,
for (Loop *TopLevelLoop : *LI)
for (Loop *L : depth_first(TopLevelLoop))
// We only handle inner-most loops.
if (L->empty())
if (L->isInnermost())
Worklist.push_back(L);
// Now walk the identified inner loops.

View File

@ -431,7 +431,7 @@ bool LoopVectorizationLegality::isUniform(Value *V) {
}
bool LoopVectorizationLegality::canVectorizeOuterLoop() {
assert(!TheLoop->empty() && "We are not vectorizing an outer loop.");
assert(!TheLoop->isInnermost() && "We are not vectorizing an outer loop.");
// Store the result and return it at the end instead of exiting early, in case
// allowExtraAnalysis is used to report multiple reasons for not vectorizing.
bool Result = true;
@ -1055,7 +1055,7 @@ bool LoopVectorizationLegality::canVectorizeWithIfConvert() {
// Helper function to canVectorizeLoopNestCFG.
bool LoopVectorizationLegality::canVectorizeLoopCFG(Loop *Lp,
bool UseVPlanNativePath) {
assert((UseVPlanNativePath || Lp->empty()) &&
assert((UseVPlanNativePath || Lp->isInnermost()) &&
"VPlan-native path is not enabled.");
// TODO: ORE should be improved to show more accurate information when an
@ -1165,7 +1165,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
// Specific checks for outer loops. We skip the remaining legal checks at this
// point because they don't support outer loops.
if (!TheLoop->empty()) {
if (!TheLoop->isInnermost()) {
assert(UseVPlanNativePath && "VPlan-native path is not enabled.");
if (!canVectorizeOuterLoop()) {
@ -1182,7 +1182,7 @@ bool LoopVectorizationLegality::canVectorize(bool UseVPlanNativePath) {
return Result;
}
assert(TheLoop->empty() && "Inner loop expected.");
assert(TheLoop->isInnermost() && "Inner loop expected.");
// Check if we can if-convert non-single-bb loops.
unsigned NumBlocks = TheLoop->getNumBlocks();
if (NumBlocks != 1 && !canVectorizeWithIfConvert()) {

View File

@ -1664,7 +1664,7 @@ public:
// representation for pragma 'omp simd' is introduced.
static bool isExplicitVecOuterLoop(Loop *OuterLp,
OptimizationRemarkEmitter *ORE) {
assert(!OuterLp->empty() && "This is not an outer loop");
assert(!OuterLp->isInnermost() && "This is not an outer loop");
LoopVectorizeHints Hints(OuterLp, true /*DisableInterleaving*/, *ORE);
// Only outer loops with an explicit vectorization hint are supported.
@ -1697,7 +1697,7 @@ static void collectSupportedLoops(Loop &L, LoopInfo *LI,
// now, only collect outer loops that have explicit vectorization hints. If we
// are stress testing the VPlan H-CFG construction, we collect the outermost
// loop of every loop nest.
if (L.empty() || VPlanBuildStressTest ||
if (L.isInnermost() || VPlanBuildStressTest ||
(EnableVPlanNativePath && isExplicitVecOuterLoop(&L, ORE))) {
LoopBlocksRPO RPOT(&L);
RPOT.perform(LI);
@ -6931,7 +6931,7 @@ LoopVectorizationPlanner::planInVPlanNativePath(ElementCount UserVF) {
// transformations before even evaluating whether vectorization is profitable.
// Since we cannot modify the incoming IR, we need to build VPlan upfront in
// the vectorization pipeline.
if (!OrigLoop->empty()) {
if (!OrigLoop->isInnermost()) {
// If the user doesn't provide a vectorization factor, determine a
// reasonable one.
if (UserVF.isZero()) {
@ -6969,7 +6969,7 @@ LoopVectorizationPlanner::planInVPlanNativePath(ElementCount UserVF) {
Optional<VectorizationFactor>
LoopVectorizationPlanner::plan(ElementCount UserVF, unsigned UserIC) {
assert(!UserVF.isScalable() && "scalable vectorization not yet handled");
assert(OrigLoop->empty() && "Inner loop expected.");
assert(OrigLoop->isInnermost() && "Inner loop expected.");
Optional<unsigned> MaybeMaxVF =
CM.computeMaxVF(UserVF.getKnownMinValue(), UserIC);
if (!MaybeMaxVF) // Cases that should not to be vectorized nor interleaved.
@ -7587,7 +7587,7 @@ VPRecipeBase *VPRecipeBuilder::tryToCreateWidenRecipe(Instruction *Instr,
void LoopVectorizationPlanner::buildVPlansWithVPRecipes(unsigned MinVF,
unsigned MaxVF) {
assert(OrigLoop->empty() && "Inner loop expected.");
assert(OrigLoop->isInnermost() && "Inner loop expected.");
// Collect conditions feeding internal conditional branches; they need to be
// represented in VPlan for it to model masking.
@ -7837,7 +7837,7 @@ VPlanPtr LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
// transformations before even evaluating whether vectorization is profitable.
// Since we cannot modify the incoming IR, we need to build VPlan upfront in
// the vectorization pipeline.
assert(!OrigLoop->empty());
assert(!OrigLoop->isInnermost());
assert(EnableVPlanNativePath && "VPlan-native path is not enabled.");
// Create new empty VPlan
@ -8236,7 +8236,7 @@ LoopVectorizePass::LoopVectorizePass(LoopVectorizeOptions Opts)
!EnableLoopVectorization) {}
bool LoopVectorizePass::processLoop(Loop *L) {
assert((EnableVPlanNativePath || L->empty()) &&
assert((EnableVPlanNativePath || L->isInnermost()) &&
"VPlan-native path is not enabled. Only process inner loops.");
#ifndef NDEBUG
@ -8298,11 +8298,11 @@ bool LoopVectorizePass::processLoop(Loop *L) {
// even evaluating whether vectorization is profitable. Since we cannot modify
// the incoming IR, we need to build VPlan upfront in the vectorization
// pipeline.
if (!L->empty())
if (!L->isInnermost())
return processLoopInVPlanNativePath(L, PSE, LI, DT, &LVL, TTI, TLI, DB, AC,
ORE, BFI, PSI, Hints);
assert(L->empty() && "Inner loop expected.");
assert(L->isInnermost() && "Inner loop expected.");
// Check the loop for a trip count threshold: vectorize loops with a tiny trip
// count by optimizing for size, to minimize overheads.