diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -6873,6 +6873,14 @@ not found to interact with the environment in an observable way, the loop may be removed. This corresponds to the ``mustprogress`` function attribute. +'``llvm.loop.finite``' Metadata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``llvm.loop.finite`` metadata indicates that this loop is finite. The loop +attached must terminate. The reason for termination is unspecified. This is a + stronger form of ``llvm.loop.mustprogress`` which simply says that the loop +either may terminate, unwind or interact with the environment. + '``irr_loop``' Metadata ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/llvm/include/llvm/Analysis/LoopInfo.h b/llvm/include/llvm/Analysis/LoopInfo.h --- a/llvm/include/llvm/Analysis/LoopInfo.h +++ b/llvm/include/llvm/Analysis/LoopInfo.h @@ -853,6 +853,9 @@ /// Add llvm.loop.mustprogress to this loop's loop id metadata. void setLoopMustProgress(); + /// Add llvm.loop.finite to this loop's loop id metadata. + void setLoopFinite(); + void dump() const; void dumpVerbose() const; @@ -1332,6 +1335,9 @@ /// the containing function attribute too. bool hasMustProgress(const Loop *L); +/// Look for the loop attribute that requires the loop to be finite. +bool hasFinite(const Loop *L); + /// Return true if this loop can be assumed to make progress. (i.e. can't /// be infinite without side effects without also being undefined) bool isMustProgress(const Loop *L); diff --git a/llvm/lib/Analysis/LoopInfo.cpp b/llvm/lib/Analysis/LoopInfo.cpp --- a/llvm/lib/Analysis/LoopInfo.cpp +++ b/llvm/lib/Analysis/LoopInfo.cpp @@ -564,6 +564,22 @@ setLoopID(NewLoopID); } +void Loop::setLoopFinite() { + LLVMContext &Context = getHeader()->getContext(); + + MDNode *Finite = findOptionMDForLoop(this, "llvm.loop.finite"); + + if (Finite) + return; + + MDNode *FiniteMD = + MDNode::get(Context, MDString::get(Context, "llvm.loop.finite")); + MDNode *LoopID = getLoopID(); + MDNode *NewLoopID = + makePostTransformationMetadata(Context, LoopID, {}, {FiniteMD}); + setLoopID(NewLoopID); +} + bool Loop::isAnnotatedParallel() const { MDNode *DesiredLoopIdMetadata = getLoopID(); @@ -1107,6 +1123,12 @@ return getOptionalIntLoopAttribute(TheLoop, Name).getValueOr(Default); } +static const char *LLVMLoopFinite = "llvm.loop.finite"; + +bool llvm::hasFinite(const Loop *L) { + return getBooleanLoopAttribute(L, LLVMLoopFinite); +} + static const char *LLVMLoopMustProgress = "llvm.loop.mustprogress"; bool llvm::hasMustProgress(const Loop *L) { @@ -1114,7 +1136,8 @@ } bool llvm::isMustProgress(const Loop *L) { - return L->getHeader()->getParent()->mustProgress() || hasMustProgress(L); + return L->getHeader()->getParent()->mustProgress() || hasMustProgress(L) || + hasFinite(L); } bool llvm::isValidAsAccessGroup(MDNode *Node) {