[clang] ac73b73 - [clang] Add mustprogress and llvm.loop.mustprogress attribute deduction

2020-11-04 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-04T22:03:14-05:00
New Revision: ac73b73c16526c9e51943759ea6cab285a57e33f

URL: 
https://github.com/llvm/llvm-project/commit/ac73b73c16526c9e51943759ea6cab285a57e33f
DIFF: 
https://github.com/llvm/llvm-project/commit/ac73b73c16526c9e51943759ea6cab285a57e33f.diff

LOG: [clang] Add mustprogress and llvm.loop.mustprogress attribute deduction

Since C++11, the C++ standard has a forward progress guarantee
[intro.progress], so all such functions must have the `mustprogress`
requirement. In addition, from C11 and onwards, loops without a non-zero
constant conditional or no conditional are also required to make
progress (C11 6.8.5p6). This patch implements these attribute deductions
so they can be used by the optimization passes.

Differential Revision: https://reviews.llvm.org/D86841

Added: 
clang/test/CodeGen/attr-mustprogress-0.c
clang/test/CodeGen/attr-mustprogress-0.cpp
clang/test/CodeGen/attr-mustprogress-1.c
clang/test/CodeGen/attr-mustprogress-1.cpp

Modified: 
clang/lib/CodeGen/CGLoopInfo.cpp
clang/lib/CodeGen/CGLoopInfo.h
clang/lib/CodeGen/CGStmt.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/test/CodeGen/address-safety-attr-flavors.cpp
clang/test/CodeGen/address-safety-attr.cpp
clang/test/CodeGen/memtag-attr.cpp
clang/test/CodeGen/no-builtin.cpp
clang/test/CodeGen/pragma-do-while.cpp
clang/test/CodeGenCXX/attr-likelihood-iteration-stmt.cpp
clang/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
clang/test/CodeGenCXX/debug-info-line-if.cpp
clang/test/CodeGenCXX/debug-info-loops.cpp
clang/test/CodeGenCXX/fno-unroll-loops-metadata.cpp
clang/test/CodeGenCXX/pragma-followup_inner.cpp
clang/test/CodeGenCXX/pragma-followup_outer.cpp
clang/test/CodeGenCXX/pragma-loop-distribute.cpp
clang/test/CodeGenCXX/pragma-loop-pr27643.cpp
clang/test/CodeGenCXX/pragma-loop-predicate.cpp
clang/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
clang/test/CodeGenCXX/pragma-loop-safety-nested.cpp
clang/test/CodeGenCXX/pragma-loop-safety-outer.cpp
clang/test/CodeGenCXX/pragma-loop-safety.cpp
clang/test/CodeGenCXX/pragma-loop.cpp
clang/test/CodeGenCXX/pragma-pipeline.cpp
clang/test/CodeGenCXX/pragma-unroll-and-jam.cpp
clang/test/CodeGenCXX/pragma-unroll.cpp
clang/test/CodeGenCXX/thunks-ehspec.cpp
clang/test/CodeGenCXX/thunks.cpp
clang/test/OpenMP/simd_metadata.c
clang/test/Profile/c-unprofiled-blocks.c
clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected

clang/test/utils/update_cc_test_checks/Inputs/check-attributes.cpp.funcattrs.expected

clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.expected

clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected

Removed: 




diff  --git a/clang/lib/CodeGen/CGLoopInfo.cpp 
b/clang/lib/CodeGen/CGLoopInfo.cpp
index a02d832b84b4..be4993e802f8 100644
--- a/clang/lib/CodeGen/CGLoopInfo.cpp
+++ b/clang/lib/CodeGen/CGLoopInfo.cpp
@@ -411,10 +411,14 @@ MDNode *LoopInfo::createMetadata(
   LoopProperties.push_back(EndLoc.getAsMDNode());
   }
 
+  LLVMContext &Ctx = Header->getContext();
+  if (Attrs.MustProgress)
+LoopProperties.push_back(
+MDNode::get(Ctx, MDString::get(Ctx, "llvm.loop.mustprogress")));
+
   assert(!!AccGroup == Attrs.IsParallel &&
  "There must be an access group iff the loop is parallel");
   if (Attrs.IsParallel) {
-LLVMContext &Ctx = Header->getContext();
 LoopProperties.push_back(MDNode::get(
 Ctx, {MDString::get(Ctx, "llvm.loop.parallel_accesses"), AccGroup}));
   }
@@ -431,7 +435,7 @@ LoopAttributes::LoopAttributes(bool IsParallel)
   VectorizePredicateEnable(LoopAttributes::Unspecified), VectorizeWidth(0),
   InterleaveCount(0), UnrollCount(0), UnrollAndJamCount(0),
   DistributeEnable(LoopAttributes::Unspecified), PipelineDisabled(false),
-  PipelineInitiationInterval(0) {}
+  PipelineInitiationInterval(0), MustProgress(false) {}
 
 void LoopAttributes::clear() {
   IsParallel = false;
@@ -446,6 +450,7 @@ void LoopAttributes::clear() {
   DistributeEnable = LoopAttributes::Unspecified;
   PipelineDisabled = false;
   PipelineInitiationInterval = 0;
+  MustProgress = false;
 }
 
 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
@@ -469,7 +474,7 @@ LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes 
&Attrs,
   Attrs.UnrollEnable == LoopAttributes::Unspecified &&
   Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
   Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
-  !EndLoc)
+  !EndLoc && !Attrs.MustProgress)
 return;
 
   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
@@ -570,8 +575,7 @@ void LoopInfoStack::push(Basic

[clang] 0b17c6e - [LoopDeletion] Allows deletion of possibly infinite side-effect free loops

2020-11-06 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-06T22:06:58-05:00
New Revision: 0b17c6e4479d62bd4ff05c48d6cdf340b198832f

URL: 
https://github.com/llvm/llvm-project/commit/0b17c6e4479d62bd4ff05c48d6cdf340b198832f
DIFF: 
https://github.com/llvm/llvm-project/commit/0b17c6e4479d62bd4ff05c48d6cdf340b198832f.diff

LOG: [LoopDeletion] Allows deletion of possibly infinite side-effect free loops

>From C11 and C++11 onwards, a forward-progress requirement has been
introduced for both languages. In the case of C, loops with non-constant
conditionals that do not have any observable side-effects (as defined by
6.8.5p6) can be assumed by the implementation to terminate, and in the
case of C++, this assumption extends to all functions. The clang
frontend will emit the `mustprogress` function attribute for C++
functions (D86233, D85393, D86841) and emit the loop metadata
`llvm.loop.mustprogress` for every loop in C11 or later that has a
non-constant conditional.

This patch modifies LoopDeletion so that only loops with
the `llvm.loop.mustprogress` metadata or loops contained in functions
that are required to make progress (`mustprogress` or `willreturn`) are
checked for observable side-effects. If these loops do not have an
observable side-effect, then we delete them.

Loops without observable side-effects that do not satisfy the above
conditions will not be deleted.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D86844

Added: 
llvm/test/Transforms/LoopDeletion/mustprogress.ll

Modified: 
clang/test/Misc/loop-opt-setup.c
llvm/include/llvm/Transforms/Utils/LoopUtils.h
llvm/lib/Transforms/Scalar/LoopDeletion.cpp
llvm/lib/Transforms/Utils/LoopUtils.cpp
llvm/test/Other/loop-deletion-printer.ll
llvm/test/Other/loop-pm-invalidation.ll
llvm/test/Transforms/LICM/2003-02-27-PreheaderProblem.ll
llvm/test/Transforms/LoopDeletion/2017-07-11-incremental-dt.ll
llvm/test/Transforms/LoopDeletion/basic-remark.ll
llvm/test/Transforms/LoopDeletion/diundef.ll
llvm/test/Transforms/LoopDeletion/invalidation.ll
llvm/test/Transforms/LoopDeletion/multiple-exit-conditions.ll
llvm/test/Transforms/LoopDeletion/multiple-exits.ll
llvm/test/Transforms/LoopDeletion/no-exit-blocks.ll
llvm/test/Transforms/LoopDeletion/unreachable-loops.ll
llvm/test/Transforms/LoopDeletion/use-in-unreachable.ll
llvm/test/Transforms/SCCP/calltest.ll
llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll

Removed: 




diff  --git a/clang/test/Misc/loop-opt-setup.c 
b/clang/test/Misc/loop-opt-setup.c
index 322f5e0e6d4a..43a9f85bca27 100644
--- a/clang/test/Misc/loop-opt-setup.c
+++ b/clang/test/Misc/loop-opt-setup.c
@@ -25,6 +25,6 @@ void Helper() {
 
 // Check br i1 to make sure the loop is gone, there will still be a label 
branch for the infinite loop.
 // CHECK-LABEL: Helper
-// CHECK: br label
+// CHECK: entry:
 // CHECK-NOT: br i1
-// CHECK: br label
+// CHECK-NEXT: ret void

diff  --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h 
b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index d741b5142e5b..076ea2f4453b 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -229,6 +229,9 @@ bool hasDisableAllTransformsHint(const Loop *L);
 /// Look for the loop attribute that disables the LICM transformation 
heuristics.
 bool hasDisableLICMTransformsHint(const Loop *L);
 
+/// Look for the loop attribute that requires progress within the loop.
+bool hasMustProgress(const Loop *L);
+
 /// The mode sets how eager a transformation should be applied.
 enum TransformationMode {
   /// The pass can use heuristics to determine whether a transformation should

diff  --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp 
b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 065db647561e..0db50d06ff26 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -210,8 +210,10 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, 
DominatorTree &DT,
   // Don't remove loops for which we can't solve the trip count.
   // They could be infinite, in which case we'd be changing program behavior.
   const SCEV *S = SE.getConstantMaxBackedgeTakenCount(L);
-  if (isa(S)) {
-LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount.\n");
+  if (isa(S) &&
+  !L->getHeader()->getParent()->mustProgress() && !hasMustProgress(L)) {
+LLVM_DEBUG(dbgs() << "Could not compute SCEV MaxBackedgeTakenCount and was 
"
+ "not required to make progress.\n");
 return Changed ? LoopDeletionResult::Modified
: LoopDeletionResult::Unmodified;
   }

diff  --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp 
b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index e10a2306547a..4210cd66f3f6 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.

[clang] 569abb5 - [LoopDeletion] Fixes failing test

2020-11-06 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-06T22:45:28-05:00
New Revision: 569abb530ece721675032d3127bd6d63f252b12b

URL: 
https://github.com/llvm/llvm-project/commit/569abb530ece721675032d3127bd6d63f252b12b
DIFF: 
https://github.com/llvm/llvm-project/commit/569abb530ece721675032d3127bd6d63f252b12b.diff

LOG: [LoopDeletion] Fixes failing test

The commit 0b17c6e4479d62bd4ff05c48d6cdf340b198832f occasionally causes this 
test to
fail, this fixes it.

Added: 


Modified: 
clang/test/Misc/loop-opt-setup.c

Removed: 




diff  --git a/clang/test/Misc/loop-opt-setup.c 
b/clang/test/Misc/loop-opt-setup.c
index 43a9f85bca27..7d26905b2ccc 100644
--- a/clang/test/Misc/loop-opt-setup.c
+++ b/clang/test/Misc/loop-opt-setup.c
@@ -25,6 +25,5 @@ void Helper() {
 
 // Check br i1 to make sure the loop is gone, there will still be a label 
branch for the infinite loop.
 // CHECK-LABEL: Helper
-// CHECK: entry:
 // CHECK-NOT: br i1
-// CHECK-NEXT: ret void
+// CHECK: ret void



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] b1878b4 - [CodeGen] Fixes sanitizer test

2020-11-06 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-06T23:53:38-05:00
New Revision: b1878b4641e06baa754ce6e3e0387b1e7d7dc143

URL: 
https://github.com/llvm/llvm-project/commit/b1878b4641e06baa754ce6e3e0387b1e7d7dc143
DIFF: 
https://github.com/llvm/llvm-project/commit/b1878b4641e06baa754ce6e3e0387b1e7d7dc143.diff

LOG: [CodeGen] Fixes sanitizer test

By turning the loop into an infinite one, the loop can't be deleted
anymore so the test will continue to pass.

Added: 


Modified: 
clang/test/CodeGen/sanitizer-module-constructor.c

Removed: 




diff  --git a/clang/test/CodeGen/sanitizer-module-constructor.c 
b/clang/test/CodeGen/sanitizer-module-constructor.c
index 3e29a923a9f1..ee4c4f7e1019 100644
--- a/clang/test/CodeGen/sanitizer-module-constructor.c
+++ b/clang/test/CodeGen/sanitizer-module-constructor.c
@@ -11,7 +11,7 @@ struct a {
 int d;
 b e;
 static void f(b g) {
-  for (d = g->c;;)
+  for (d = g->c; 1 ;)
 ;
 }
 void h() { f(e); }



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] d3e75d3 - Revert "[CodeGen] Fixes sanitizer test"

2020-11-06 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-07T00:32:12-05:00
New Revision: d3e75d31e3c831d00277518caee80b15b72666a8

URL: 
https://github.com/llvm/llvm-project/commit/d3e75d31e3c831d00277518caee80b15b72666a8
DIFF: 
https://github.com/llvm/llvm-project/commit/d3e75d31e3c831d00277518caee80b15b72666a8.diff

LOG: Revert "[CodeGen] Fixes sanitizer test"

This reverts commit b1878b4641e06baa754ce6e3e0387b1e7d7dc143. This does
fix the test but it means that ac73b73c1652 is not implemented
correctly. Reverting for now, and will be reverting the commit that
causes this to fail.

Added: 


Modified: 
clang/test/CodeGen/sanitizer-module-constructor.c

Removed: 




diff  --git a/clang/test/CodeGen/sanitizer-module-constructor.c 
b/clang/test/CodeGen/sanitizer-module-constructor.c
index ee4c4f7e1019..3e29a923a9f1 100644
--- a/clang/test/CodeGen/sanitizer-module-constructor.c
+++ b/clang/test/CodeGen/sanitizer-module-constructor.c
@@ -11,7 +11,7 @@ struct a {
 int d;
 b e;
 static void f(b g) {
-  for (d = g->c; 1 ;)
+  for (d = g->c;;)
 ;
 }
 void h() { f(e); }



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] fd3cad7 - [clang] Fix ForStmt mustprogress handling

2020-11-09 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2020-11-09T11:38:06-05:00
New Revision: fd3cad7a60168b49f7bc160354655d7605847d41

URL: 
https://github.com/llvm/llvm-project/commit/fd3cad7a60168b49f7bc160354655d7605847d41
DIFF: 
https://github.com/llvm/llvm-project/commit/fd3cad7a60168b49f7bc160354655d7605847d41.diff

LOG: [clang] Fix ForStmt mustprogress handling

D86841 had an error where for statements with no conditional were
required to make progress. This is not true, this patch removes that
line, and adds regression tests.

Differential Revision: https://reviews.llvm.org/D91075

Added: 


Modified: 
clang/lib/CodeGen/CGStmt.cpp
clang/test/CodeGen/attr-mustprogress-1.c
clang/test/CodeGen/attr-mustprogress-1.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 972da3d4ea2d..d8be0ef4e525 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -947,7 +947,6 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S,
   Expr::EvalResult Result;
   if (LanguageRequiresProgress()) {
 if (!S.getCond()) {
-  LoopMustProgress = true;
   FnIsMustProgress = false;
 } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) {
   LoopMustProgress = true;

diff  --git a/clang/test/CodeGen/attr-mustprogress-1.c 
b/clang/test/CodeGen/attr-mustprogress-1.c
index a5a8595218a1..2ff068b8b90a 100644
--- a/clang/test/CodeGen/attr-mustprogress-1.c
+++ b/clang/test/CodeGen/attr-mustprogress-1.c
@@ -7,6 +7,17 @@
 int a = 0;
 int b = 0;
 
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @f0(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[FOR_COND:%.*]]
+// CHECK:   for.cond:
+// CHECK-NOT:br label [[FOR_COND]], !llvm.loop !{{.*}}
+//
+void f0() {
+  for (; ;) ;
+}
+
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: @f1(
 // CHECK-NEXT:  entry:

diff  --git a/clang/test/CodeGen/attr-mustprogress-1.cpp 
b/clang/test/CodeGen/attr-mustprogress-1.cpp
index 6d53d2d1148d..945d74663c6d 100644
--- a/clang/test/CodeGen/attr-mustprogress-1.cpp
+++ b/clang/test/CodeGen/attr-mustprogress-1.cpp
@@ -7,6 +7,16 @@
 int a = 0;
 int b = 0;
 
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @_Z2f0v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[FOR_COND:%.*]]
+// CHECK:   for.cond:
+// CHECK-NOT:br label [[FOR_COND]], !llvm.loop !{{.*}}
+void f0() {
+  for (; ;) ;
+}
+
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: @_Z2f1v(
 // CHECK-NEXT:  entry:



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] f88a797 - [LoopDeletion] Allows deletion of possibly infinite side-effect free loops

2021-01-05 Thread Atmn Patel via cfe-commits

Author: Atmn Patel
Date: 2021-01-05T09:56:16-05:00
New Revision: f88a7975210fc995197af4b393e3bb5030e97a5c

URL: 
https://github.com/llvm/llvm-project/commit/f88a7975210fc995197af4b393e3bb5030e97a5c
DIFF: 
https://github.com/llvm/llvm-project/commit/f88a7975210fc995197af4b393e3bb5030e97a5c.diff

LOG: [LoopDeletion] Allows deletion of possibly infinite side-effect free loops

>From C11 and C++11 onwards, a forward-progress requirement has been
introduced for both languages. In the case of C, loops with non-constant
conditionals that do not have any observable side-effects (as defined by
6.8.5p6) can be assumed by the implementation to terminate, and in the
case of C++, this assumption extends to all functions. The clang
frontend will emit the `mustprogress` function attribute for C++
functions (D86233, D85393, D86841) and emit the loop metadata
`llvm.loop.mustprogress` for every loop in C11 or later that has a
non-constant conditional.

This patch modifies LoopDeletion so that only loops with
the `llvm.loop.mustprogress` metadata or loops contained in functions
that are required to make progress (`mustprogress` or `willreturn`) are
checked for observable side-effects. If these loops do not have an
observable side-effect, then we delete them.

Loops without observable side-effects that do not satisfy the above
conditions will not be deleted.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D86844

Added: 
llvm/test/Transforms/LoopDeletion/mustprogress.ll

Modified: 
clang/test/Misc/loop-opt-setup.c
llvm/include/llvm/Transforms/Utils/LoopUtils.h
llvm/lib/Transforms/Scalar/LoopDeletion.cpp
llvm/lib/Transforms/Utils/LoopUtils.cpp
llvm/test/Transforms/LoopDeletion/no-exit-blocks.ll

Removed: 




diff  --git a/clang/test/Misc/loop-opt-setup.c 
b/clang/test/Misc/loop-opt-setup.c
index 9cea02a8bcb3..e9a9c1e8ae2d 100644
--- a/clang/test/Misc/loop-opt-setup.c
+++ b/clang/test/Misc/loop-opt-setup.c
@@ -1,5 +1,6 @@
-// This relies on %clang_cc1, %clang does not emit the block names in Release 
mode.
+// This tests loop unrolling and loop deletion (enabled under -O1)
 // RUN: %clang_cc1 -O1 -fno-unroll-loops -S -o - %s -emit-llvm | FileCheck %s
+// RUN: %clang_cc1 -std=c99 -O1 -fno-unroll-loops -S -o - %s -emit-llvm | 
FileCheck %s --check-prefix C99
 
 extern int a[16];
 int b = 0;
@@ -25,7 +26,12 @@ void Helper() {
 }
 
 // Check br i1 to make sure the loop is gone, there will still be a label 
branch for the infinite loop.
+// In C99, there was no forward progress requirement, so we expect the 
infinite loop to still exist,
+// but for C11 and onwards, the infinite loop can be deleted.
 // CHECK-LABEL: Helper
-// CHECK: br label
-// CHECK-NOT: br i1
-// CHECK: br label
+// C99: br label
+// C99-NOT: br i1
+// C99: br label
+// CHECK: entry:
+// CHECK-NOT: br i1
+// CHECK-NEXT: ret void

diff  --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h 
b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index d606fa954f95..80c6b09d9cf0 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -255,6 +255,9 @@ bool hasDisableAllTransformsHint(const Loop *L);
 /// Look for the loop attribute that disables the LICM transformation 
heuristics.
 bool hasDisableLICMTransformsHint(const Loop *L);
 
+/// Look for the loop attribute that requires progress within the loop.
+bool hasMustProgress(const Loop *L);
+
 /// The mode sets how eager a transformation should be applied.
 enum TransformationMode {
   /// The pass can use heuristics to determine whether a transformation should

diff  --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp 
b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
index 065db647561e..814cfc7ac6a9 100644
--- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp
@@ -128,10 +128,11 @@ static bool isLoopNeverExecuted(Loop *L) {
 
 /// Remove a loop if it is dead.
 ///
-/// A loop is considered dead if it does not impact the observable behavior of
-/// the program other than finite running time. This never removes a loop that
-/// might be infinite (unless it is never executed), as doing so could change
-/// the halting/non-halting nature of a program.
+/// A loop is considered dead either if it does not impact the observable
+/// behavior of the program other than finite running time, or if it is
+/// required to make progress by an attribute such as 'mustprogress' or
+/// 'llvm.loop.mustprogress' and does not make any. This may remove
+/// infinite loops that have been required to make progress.
 ///
 /// This entire process relies pretty heavily on LoopSimplify form and LCSSA in
 /// order to make various safety checks work.
@@ -207,11 +208,13 @@ static LoopDeletionResult deleteLoopIfDead(Loop *L, 
DominatorTree &DT,
: LoopDeletionResult::Unmodifie