diff options
Diffstat (limited to 'llvm/lib/Analysis/LoopInfo.cpp')
| -rw-r--r-- | llvm/lib/Analysis/LoopInfo.cpp | 144 |
1 files changed, 115 insertions, 29 deletions
diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp index a85869b16333..66aab4c195c8 100644 --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -20,6 +20,7 @@ #include "llvm/Analysis/IVDescriptors.h" #include "llvm/Analysis/LoopInfoImpl.h" #include "llvm/Analysis/LoopIterator.h" +#include "llvm/Analysis/LoopNestAnalysis.h" #include "llvm/Analysis/MemorySSA.h" #include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" @@ -170,8 +171,8 @@ PHINode *Loop::getCanonicalInductionVariable() const { } /// Get the latch condition instruction. -static ICmpInst *getLatchCmpInst(const Loop &L) { - if (BasicBlock *Latch = L.getLoopLatch()) +ICmpInst *Loop::getLatchCmpInst() const { + if (BasicBlock *Latch = getLoopLatch()) if (BranchInst *BI = dyn_cast_or_null<BranchInst>(Latch->getTerminator())) if (BI->isConditional()) return dyn_cast<ICmpInst>(BI->getCondition()); @@ -182,7 +183,7 @@ static ICmpInst *getLatchCmpInst(const Loop &L) { /// Return the final value of the loop induction variable if found. static Value *findFinalIVValue(const Loop &L, const PHINode &IndVar, const Instruction &StepInst) { - ICmpInst *LatchCmpInst = getLatchCmpInst(L); + ICmpInst *LatchCmpInst = L.getLatchCmpInst(); if (!LatchCmpInst) return nullptr; @@ -296,7 +297,7 @@ PHINode *Loop::getInductionVariable(ScalarEvolution &SE) const { BasicBlock *Header = getHeader(); assert(Header && "Expected a valid loop header"); - ICmpInst *CmpInst = getLatchCmpInst(*this); + ICmpInst *CmpInst = getLatchCmpInst(); if (!CmpInst) return nullptr; @@ -380,10 +381,6 @@ BranchInst *Loop::getLoopGuardBranch() const { if (!ExitFromLatch) return nullptr; - BasicBlock *ExitFromLatchSucc = ExitFromLatch->getUniqueSuccessor(); - if (!ExitFromLatchSucc) - return nullptr; - BasicBlock *GuardBB = Preheader->getUniquePredecessor(); if (!GuardBB) return nullptr; @@ -397,7 +394,17 @@ BranchInst *Loop::getLoopGuardBranch() const { BasicBlock *GuardOtherSucc = (GuardBI->getSuccessor(0) == Preheader) ? GuardBI->getSuccessor(1) : GuardBI->getSuccessor(0); - return (GuardOtherSucc == ExitFromLatchSucc) ? GuardBI : nullptr; + + // Check if ExitFromLatch (or any BasicBlock which is an empty unique + // successor of ExitFromLatch) is equal to GuardOtherSucc. If + // skipEmptyBlockUntil returns GuardOtherSucc, then the guard branch for the + // loop is GuardBI (return GuardBI), otherwise return nullptr. + if (&LoopNest::skipEmptyBlockUntil(ExitFromLatch, GuardOtherSucc, + /*CheckUniquePred=*/true) == + GuardOtherSucc) + return GuardBI; + else + return nullptr; } bool Loop::isCanonical(ScalarEvolution &SE) const { @@ -616,15 +623,7 @@ bool Loop::isAnnotatedParallel() const { if (!LoopIdMD) return false; - bool LoopIdMDFound = false; - for (const MDOperand &MDOp : LoopIdMD->operands()) { - if (MDOp == DesiredLoopIdMetadata) { - LoopIdMDFound = true; - break; - } - } - - if (!LoopIdMDFound) + if (!llvm::is_contained(LoopIdMD->operands(), DesiredLoopIdMetadata)) return false; } } @@ -670,7 +669,7 @@ Loop::LocRange Loop::getLocRange() const { LLVM_DUMP_METHOD void Loop::dump() const { print(dbgs()); } LLVM_DUMP_METHOD void Loop::dumpVerbose() const { - print(dbgs(), /*Depth=*/0, /*Verbose=*/true); + print(dbgs(), /*Verbose=*/true); } #endif @@ -765,9 +764,8 @@ void UnloopUpdater::updateBlockParents() { void UnloopUpdater::removeBlocksFromAncestors() { // Remove all unloop's blocks (including those in nested subloops) from // ancestors below the new parent loop. - for (Loop::block_iterator BI = Unloop.block_begin(), BE = Unloop.block_end(); - BI != BE; ++BI) { - Loop *OuterParent = LI->getLoopFor(*BI); + for (BasicBlock *BB : Unloop.blocks()) { + Loop *OuterParent = LI->getLoopFor(BB); if (Unloop.contains(OuterParent)) { while (OuterParent->getParentLoop() != &Unloop) OuterParent = OuterParent->getParentLoop(); @@ -778,7 +776,7 @@ void UnloopUpdater::removeBlocksFromAncestors() { for (Loop *OldParent = Unloop.getParentLoop(); OldParent != OuterParent; OldParent = OldParent->getParentLoop()) { assert(OldParent && "new loop is not an ancestor of the original"); - OldParent->removeBlockFromLoop(*BI); + OldParent->removeBlockFromLoop(BB); } } } @@ -885,17 +883,14 @@ void LoopInfo::erase(Loop *Unloop) { // First handle the special case of no parent loop to simplify the algorithm. 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(); - I != E; ++I) { - + for (BasicBlock *BB : Unloop->blocks()) { // Don't reparent blocks in subloops. - if (getLoopFor(*I) != Unloop) + if (getLoopFor(BB) != Unloop) continue; // Blocks no longer have a parent but are still referenced by Unloop until // the Unloop object is deleted. - changeLoopFor(*I, nullptr); + changeLoopFor(BB, nullptr); } // Remove the loop from the top-level LoopInfo object. @@ -936,6 +931,31 @@ void LoopInfo::erase(Loop *Unloop) { } } +bool +LoopInfo::wouldBeOutOfLoopUseRequiringLCSSA(const Value *V, + const BasicBlock *ExitBB) const { + if (V->getType()->isTokenTy()) + // We can't form PHIs of token type, so the definition of LCSSA excludes + // values of that type. + return false; + + const Instruction *I = dyn_cast<Instruction>(V); + if (!I) + return false; + const Loop *L = getLoopFor(I->getParent()); + if (!L) + return false; + if (L->contains(ExitBB)) + // Could be an exit bb of a subloop and contained in defining loop + return false; + + // We found a (new) out-of-loop use location, for a value defined in-loop. + // (Note that because of LCSSA, we don't have to account for values defined + // in sibling loops. Such values will have LCSSA phis of their own in the + // common parent loop.) + return true; +} + AnalysisKey LoopAnalysis::Key; LoopInfo LoopAnalysis::run(Function &F, FunctionAnalysisManager &AM) { @@ -1026,6 +1046,72 @@ MDNode *llvm::findOptionMDForLoop(const Loop *TheLoop, StringRef Name) { return findOptionMDForLoopID(TheLoop->getLoopID(), Name); } +/// Find string metadata for loop +/// +/// If it has a value (e.g. {"llvm.distribute", 1} return the value as an +/// operand or null otherwise. If the string metadata is not found return +/// Optional's not-a-value. +Optional<const MDOperand *> llvm::findStringMetadataForLoop(const Loop *TheLoop, + StringRef Name) { + MDNode *MD = findOptionMDForLoop(TheLoop, Name); + if (!MD) + return None; + switch (MD->getNumOperands()) { + case 1: + return nullptr; + case 2: + return &MD->getOperand(1); + default: + llvm_unreachable("loop metadata has 0 or 1 operand"); + } +} + +Optional<bool> llvm::getOptionalBoolLoopAttribute(const Loop *TheLoop, + StringRef Name) { + MDNode *MD = findOptionMDForLoop(TheLoop, Name); + if (!MD) + return None; + switch (MD->getNumOperands()) { + case 1: + // When the value is absent it is interpreted as 'attribute set'. + return true; + case 2: + if (ConstantInt *IntMD = + mdconst::extract_or_null<ConstantInt>(MD->getOperand(1).get())) + return IntMD->getZExtValue(); + return true; + } + llvm_unreachable("unexpected number of options"); +} + +bool llvm::getBooleanLoopAttribute(const Loop *TheLoop, StringRef Name) { + return getOptionalBoolLoopAttribute(TheLoop, Name).getValueOr(false); +} + +llvm::Optional<int> llvm::getOptionalIntLoopAttribute(const Loop *TheLoop, + StringRef Name) { + const MDOperand *AttrMD = + findStringMetadataForLoop(TheLoop, Name).getValueOr(nullptr); + if (!AttrMD) + return None; + + ConstantInt *IntMD = mdconst::extract_or_null<ConstantInt>(AttrMD->get()); + if (!IntMD) + return None; + + return IntMD->getSExtValue(); +} + +static const char *LLVMLoopMustProgress = "llvm.loop.mustprogress"; + +bool llvm::hasMustProgress(const Loop *L) { + return getBooleanLoopAttribute(L, LLVMLoopMustProgress); +} + +bool llvm::isMustProgress(const Loop *L) { + return L->getHeader()->getParent()->mustProgress() || hasMustProgress(L); +} + bool llvm::isValidAsAccessGroup(MDNode *Node) { return Node->getNumOperands() == 0 && Node->isDistinct(); } |
