atmnpatel updated this revision to Diff 296747.
atmnpatel added a comment.

Fixes.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86841/new/

https://reviews.llvm.org/D86841

Files:
  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/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
  clang/test/CodeGen/memtag-attr.cpp
  clang/test/CodeGen/no-builtin.cpp
  clang/test/CodeGen/pragma-do-while.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

Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected
===================================================================
--- clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected
+++ clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.no-generated.expected
@@ -41,7 +41,7 @@
 // NOOMP-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I]], align 4
 // NOOMP-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP2]], 1
 // NOOMP-NEXT:    store i32 [[INC]], i32* [[I]], align 4
-// NOOMP-NEXT:    br label [[FOR_COND]]
+// NOOMP-NEXT:    br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]]
 // NOOMP:       for.end:
 // NOOMP-NEXT:    call void @foo()
 // NOOMP-NEXT:    ret i32 0
@@ -86,7 +86,7 @@
 // NOOMP-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I]], align 4
 // NOOMP-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP2]], 1
 // NOOMP-NEXT:    store i32 [[INC]], i32* [[I]], align 4
-// NOOMP-NEXT:    br label [[FOR_COND]]
+// NOOMP-NEXT:    br label [[FOR_COND]], [[LOOP4:!llvm.loop !.*]]
 // NOOMP:       for.end:
 // NOOMP-NEXT:    ret void
 //
Index: clang/test/utils/update_cc_test_checks/Inputs/generated-funcs.c.generated.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.generated.expected
@@ -197,7 +197,7 @@
 // NOOMP-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I]], align 4
 // NOOMP-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP2]], 1
 // NOOMP-NEXT:    store i32 [[INC]], i32* [[I]], align 4
-// NOOMP-NEXT:    br label [[FOR_COND]]
+// NOOMP-NEXT:    br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]]
 // NOOMP:       for.end:
 // NOOMP-NEXT:    call void @foo()
 // NOOMP-NEXT:    ret i32 0
@@ -223,7 +223,7 @@
 // NOOMP-NEXT:    [[TMP2:%.*]] = load i32, i32* [[I]], align 4
 // NOOMP-NEXT:    [[INC:%.*]] = add nsw i32 [[TMP2]], 1
 // NOOMP-NEXT:    store i32 [[INC]], i32* [[I]], align 4
-// NOOMP-NEXT:    br label [[FOR_COND]]
+// NOOMP-NEXT:    br label [[FOR_COND]], [[LOOP4:!llvm.loop !.*]]
 // NOOMP:       for.end:
 // NOOMP-NEXT:    ret void
 //
Index: clang/test/utils/update_cc_test_checks/Inputs/check-attributes.cpp.funcattrs.expected
===================================================================
--- clang/test/utils/update_cc_test_checks/Inputs/check-attributes.cpp.funcattrs.expected
+++ clang/test/utils/update_cc_test_checks/Inputs/check-attributes.cpp.funcattrs.expected
@@ -11,7 +11,7 @@
   struct RT Z;
 };
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z3fooP2ST(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    [[S_ADDR:%.*]] = alloca %struct.ST*, align 8
Index: clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
===================================================================
--- clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
+++ clang/test/utils/update_cc_test_checks/Inputs/basic-cplusplus.cpp.expected
@@ -44,7 +44,7 @@
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca %class.Foo*, align 8
 // CHECK-NEXT:    store %class.Foo* [[THIS:%.*]], %class.Foo** [[THIS_ADDR]], align 8
 // CHECK-NEXT:    [[THIS1:%.*]] = load %class.Foo*, %class.Foo** [[THIS_ADDR]], align 8
-// CHECK-NEXT:    call void @_ZN3FooD2Ev(%class.Foo* [[THIS1]]) [[ATTR2:#.*]]
+// CHECK-NEXT:    call void @_ZN3FooD2Ev(%class.Foo* [[THIS1]]) [[ATTR3:#.*]]
 // CHECK-NEXT:    ret void
 //
 Foo::~Foo() {}
@@ -70,7 +70,7 @@
 // CHECK-NEXT:    call void @_ZN3FooC1Ei(%class.Foo* [[F]], i32 1)
 // CHECK-NEXT:    [[CALL:%.*]] = call i32 @_ZNK3Foo23function_defined_inlineEi(%class.Foo* [[F]], i32 2)
 // CHECK-NEXT:    [[CALL1:%.*]] = call i32 @_ZNK3Foo28function_defined_out_of_lineEi(%class.Foo* [[F]], i32 3)
-// CHECK-NEXT:    call void @_ZN3FooD1Ev(%class.Foo* [[F]]) [[ATTR2]]
+// CHECK-NEXT:    call void @_ZN3FooD1Ev(%class.Foo* [[F]]) [[ATTR3]]
 // CHECK-NEXT:    ret i32 0
 //
 int main() {
Index: clang/test/Profile/c-unprofiled-blocks.c
===================================================================
--- clang/test/Profile/c-unprofiled-blocks.c
+++ clang/test/Profile/c-unprofiled-blocks.c
@@ -16,7 +16,7 @@
   // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}{{$}}
   while (--i) {}
 
-  // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}{{$}}
+  // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}, !llvm.loop [[LOOP1:!.*]]
   do {} while (i++ < 75);
 
   // PGOUSE: switch {{.*}} [
@@ -46,7 +46,7 @@
     // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}{{$}}
     while (--i) {}
 
-    // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}{{$}}
+    // PGOUSE: br i1 %{{[^,]*}}, label %{{[^,]*}}, label %{{[^,]*}}, !llvm.loop [[LOOP2:!.*]]
     do {} while (i++ < 75);
 
     // PGOUSE: switch {{.*}} [
Index: clang/test/OpenMP/simd_metadata.c
===================================================================
--- clang/test/OpenMP/simd_metadata.c
+++ clang/test/OpenMP/simd_metadata.c
@@ -110,7 +110,8 @@
     }
 // CHECK: store float {{.+}}, float* {{.+}}, align {{.+}}, !llvm.access.group ![[ACCESS_GROUP_13:[0-9]+]]
   }
-// CHECK: br label %{{.+}}, !llvm.loop [[LOOP_H3_HEADER:![0-9]+]]
+  // CHECK: br label %{{.+}}, !llvm.loop [[LOOP_H3_HEADER_INNER:![0-9]+]]
+  // CHECK: br label %{{.+}}, !llvm.loop [[LOOP_H3_HEADER:![0-9]+]]
 }
 
 // Metadata for h1:
Index: clang/test/CodeGenCXX/thunks.cpp
===================================================================
--- clang/test/CodeGenCXX/thunks.cpp
+++ clang/test/CodeGenCXX/thunks.cpp
@@ -529,7 +529,7 @@
 // CHECK-NONOPT-LABEL: define linkonce_odr void @_ZThn8_N6Test101C3fooEv
 
 // Checking with opt
-// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #0 align 2
+// CHECK-OPT-LABEL: define internal void @_ZThn8_N6Test4B12_GLOBAL__N_11C1fEv(%"struct.Test4B::(anonymous namespace)::C"* %this) unnamed_addr #1 align 2
 
 // This is from Test5:
 // CHECK-OPT-LABEL: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
Index: clang/test/CodeGenCXX/thunks-ehspec.cpp
===================================================================
--- clang/test/CodeGenCXX/thunks-ehspec.cpp
+++ clang/test/CodeGenCXX/thunks-ehspec.cpp
@@ -17,13 +17,13 @@
 };
 void C::primary_key() {}
 
-// CHECK-LABEL: define available_externally void @_ZThn8_N1C9secondaryEv(%class.C* %this)
+// CHECK-LABEL: define available_externally void @_ZThn8_N1C9secondaryEv(%class.C* %this) {{.*}} #2
 // CHECK-NOT: invoke
 // CHECK: tail call void @_ZN1C9secondaryEv(%class.C* %{{.*}})
 // CHECK-NOT: invoke
 // CHECK: ret void
 
-// CHECK-LABEL: define available_externally void @_ZThn8_N1C16secondary_varargEiz(%class.C* %this, i32 %0, ...)
+// CHECK-LABEL: define available_externally void @_ZThn8_N1C16secondary_varargEiz(%class.C* %this, i32 %0, ...) {{.*}} #2
 // CHECK-NOT: invoke
-// CHECK:  musttail call void (%class.C*, i32, ...) @_ZN1C16secondary_varargEiz(%class.C* %{{.*}}, i32 %{{.*}}, ...) #2
+// CHECK:  musttail call void (%class.C*, i32, ...) @_ZN1C16secondary_varargEiz(%class.C* %{{.*}}, i32 %{{.*}}, ...) #3
 // CHECK-NEXT:  ret void
Index: clang/test/CodeGenCXX/pragma-unroll.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-unroll.cpp
+++ clang/test/CodeGenCXX/pragma-unroll.cpp
@@ -96,11 +96,11 @@
   for_template_define_test<double>(List, Length, Value);
 }
 
-// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_ENABLE:.*]]}
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[UNROLL_ENABLE:.*]]}
 // CHECK: ![[UNROLL_ENABLE]] = !{!"llvm.loop.unroll.enable"}
 // CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]}
 // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
-// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_8:.*]]}
+// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], [[MP]], ![[UNROLL_8:.*]]}
 // CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
 // CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[UNROLL_4:.*]]}
 // CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4}
Index: clang/test/CodeGenCXX/pragma-unroll-and-jam.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-unroll-and-jam.cpp
+++ clang/test/CodeGenCXX/pragma-unroll-and-jam.cpp
@@ -6,6 +6,7 @@
   for (int i = 0; i < Length; i++) {
     for (int j = 0; j < Length; j++) {
       // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
       List[i * Length + j] = Value;
     }
   }
@@ -16,7 +17,8 @@
 #pragma unroll_and_jam(4)
   for (int i = 0; i < Length; i++) {
     for (int j = 0; j < Length; j++) {
-      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_4:.*]]
       List[i * Length + j] = Value;
     }
   }
@@ -27,7 +29,8 @@
 #pragma nounroll_and_jam
   for (int i = 0; i < Length; i++) {
     for (int j = 0; j < Length; j++) {
-      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_5:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_6:.*]]
       List[i * Length + j] = Value;
     }
   }
@@ -40,16 +43,17 @@
   for (int i = 0; i < Length; i++) {
     for (int j = 0; j < Length; j++) {
       // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_7:.*]]
+      // CHECK: br label {{.*}}, !llvm.loop ![[LOOP_8:.*]]
       List[i * Length + j] = Value;
     }
   }
 }
 
-// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNJ_ENABLE:.*]]}
+// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], [[MP:![0-9]+]], ![[UNJ_ENABLE:.*]]}
 // CHECK: ![[UNJ_ENABLE]] = !{!"llvm.loop.unroll_and_jam.enable"}
-// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNJ_4:.*]]}
+// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], [[MP]], ![[UNJ_4:.*]]}
 // CHECK: ![[UNJ_4]] = !{!"llvm.loop.unroll_and_jam.count", i32 4}
-// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNJ_DISABLE:.*]]}
+// CHECK: ![[LOOP_6]] = distinct !{![[LOOP_6]], [[MP]], ![[UNJ_DISABLE:.*]]}
 // CHECK: ![[UNJ_DISABLE]] = !{!"llvm.loop.unroll_and_jam.disable"}
-// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[UNJ_DISABLE:.*]], ![[UNROLL_4:.*]]}
+// CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], [[MP]], ![[UNJ_DISABLE:.*]], ![[UNROLL_4:.*]]}
 // CHECK: ![[UNROLL_4]] = !{!"llvm.loop.unroll.count", i32 4}
Index: clang/test/CodeGenCXX/pragma-pipeline.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-pipeline.cpp
+++ clang/test/CodeGenCXX/pragma-pipeline.cpp
@@ -36,12 +36,12 @@
   }
 }
 
-// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[PIPELINE_DISABLE:.*]]}
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[PIPELINE_DISABLE:.*]]}
 // CHECK: ![[PIPELINE_DISABLE]] = !{!"llvm.loop.pipeline.disable", i1 true}
 
 // CHECK-NOT:llvm.loop.pipeline
 
-// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[PIPELINE_II_10:.*]]}
+// CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], [[MP]], ![[PIPELINE_II_10:.*]]}
 // CHECK: ![[PIPELINE_II_10]] = !{!"llvm.loop.pipeline.initiationinterval", i32 10}
 
-// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[PIPELINE_DISABLE]]}
+// CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], [[MP]], ![[PIPELINE_DISABLE]]}
Index: clang/test/CodeGenCXX/pragma-loop.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop.cpp
+++ clang/test/CodeGenCXX/pragma-loop.cpp
@@ -158,10 +158,10 @@
   for_template_constant_expression_test<double, 2, 4, 8>(List, Length);
 }
 
-// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_FULL:.*]]}
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[UNROLL_FULL:.*]]}
 // CHECK: ![[UNROLL_FULL]] = !{!"llvm.loop.unroll.full"}
 
-// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[VECTORIZE_ENABLE:.*]]}
+// CHECK: ![[LOOP_2]] = distinct !{![[LOOP_2]], [[MP]], ![[UNROLL_DISABLE:.*]], ![[DISTRIBUTE_DISABLE:.*]], ![[WIDTH_8:.*]], ![[INTERLEAVE_4:.*]], ![[VECTORIZE_ENABLE:.*]]}
 // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
 // CHECK: ![[DISTRIBUTE_DISABLE]] = !{!"llvm.loop.distribute.enable", i1 false}
 // CHECK: ![[WIDTH_8]] = !{!"llvm.loop.vectorize.width", i32 8}
@@ -170,7 +170,7 @@
 
 // CHECK: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[INTERLEAVE_4:.*]], ![[VECTORIZE_ENABLE]], ![[FOLLOWUP_VECTOR_3:.*]]}
 // CHECK: ![[FOLLOWUP_VECTOR_3]] = !{!"llvm.loop.vectorize.followup_all", ![[AFTER_VECTOR_3:.*]]}
-// CHECK: ![[AFTER_VECTOR_3]] = distinct !{![[AFTER_VECTOR_3]], ![[ISVECTORIZED:.*]], ![[UNROLL_8:.*]]}
+// CHECK: ![[AFTER_VECTOR_3]] = distinct !{![[AFTER_VECTOR_3]], [[MP]], ![[ISVECTORIZED:.*]], ![[UNROLL_8:.*]]}
 // CHECK: ![[ISVECTORIZED]] = !{!"llvm.loop.isvectorized"}
 // CHECK: ![[UNROLL_8]] = !{!"llvm.loop.unroll.count", i32 8}
 
@@ -185,7 +185,7 @@
 // CHECK: ![[FOLLOWUP_VECTOR_6]] = !{!"llvm.loop.vectorize.followup_all", ![[AFTER_VECTOR_6:.*]]}
 // CHECK: ![[AFTER_VECTOR_6]] = distinct !{![[AFTER_VECTOR_6]], ![[ISVECTORIZED:.*]], ![[UNROLL_8:.*]]}
 
-// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], ![[WIDTH_5:.*]], ![[VECTORIZE_ENABLE]]}
+// CHECK: ![[LOOP_7]] = distinct !{![[LOOP_7]], [[MP]], ![[WIDTH_5:.*]], ![[VECTORIZE_ENABLE]]}
 // CHECK: ![[WIDTH_5]] = !{!"llvm.loop.vectorize.width", i32 5}
 
 // CHECK: ![[LOOP_8]] = distinct !{![[LOOP_8]], ![[WIDTH_5:.*]]}
@@ -213,5 +213,5 @@
 // CHECK: ![[AFTER_VECTOR_13]] = distinct !{![[AFTER_VECTOR_13]], ![[ISVECTORIZED:.*]], ![[UNROLL_32:.*]]}
 // CHECK: ![[UNROLL_32]] = !{!"llvm.loop.unroll.count", i32 32}
 
-// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], ![[WIDTH_10:.*]], ![[VECTORIZE_ENABLE]]}
+// CHECK: ![[LOOP_14]] = distinct !{![[LOOP_14]], [[MP]], ![[WIDTH_10:.*]], ![[VECTORIZE_ENABLE]]}
 // CHECK: ![[WIDTH_10]] = !{!"llvm.loop.vectorize.width", i32 10}
Index: clang/test/CodeGenCXX/pragma-loop-safety.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-safety.cpp
+++ clang/test/CodeGenCXX/pragma-loop-safety.cpp
@@ -47,12 +47,12 @@
 }
 
 // CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
-// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], ![[PARALLEL_ACCESSES_7:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]]}
+// CHECK: ![[LOOP1_HINTS]] = distinct !{![[LOOP1_HINTS]], [[MP:![0-9]+]], ![[PARALLEL_ACCESSES_7:[0-9]+]], ![[UNROLL_DISABLE:[0-9]+]], ![[INTERLEAVE_1:[0-9]+]], ![[INTENABLE_1:[0-9]+]]}
 // CHECK: ![[PARALLEL_ACCESSES_7]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
 // CHECK: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
 // CHECK: ![[INTERLEAVE_1]] = !{!"llvm.loop.interleave.count", i32 1}
 // CHECK: ![[INTENABLE_1]] = !{!"llvm.loop.vectorize.enable", i1 true}
 // CHECK: ![[ACCESS_GROUP_8]] = distinct !{}
-// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], ![[PARALLEL_ACCESSES_11:[0-9]+]], ![[UNROLL_DISABLE]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]]}
+// CHECK: ![[LOOP2_HINTS]] = distinct !{![[LOOP2_HINTS]], [[MP]], ![[PARALLEL_ACCESSES_11:[0-9]+]], ![[UNROLL_DISABLE]], ![[WIDTH_1:[0-9]+]], ![[INTENABLE_1]]}
 // CHECK: ![[PARALLEL_ACCESSES_11]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_8]]}
 // CHECK: ![[WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1}
Index: clang/test/CodeGenCXX/pragma-loop-safety-outer.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-safety-outer.cpp
+++ clang/test/CodeGenCXX/pragma-loop-safety-outer.cpp
@@ -18,5 +18,5 @@
 
 // CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
 // CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]],
-// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], ![[PARALLEL_ACCESSES_9:[0-9]+]]
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], [[MP:![0-9]+]], ![[PARALLEL_ACCESSES_9:[0-9]+]]
 // CHECK: ![[PARALLEL_ACCESSES_9]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
Index: clang/test/CodeGenCXX/pragma-loop-safety-nested.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-safety-nested.cpp
+++ clang/test/CodeGenCXX/pragma-loop-safety-nested.cpp
@@ -21,7 +21,7 @@
 // CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
 // CHECK: ![[ACCESS_GROUP_LIST_3]] = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]}
 // CHECK: ![[ACCESS_GROUP_4]] = distinct !{}
-// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], ![[PARALLEL_ACCESSES_8:[0-9]+]]
+// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], [[MP:![0-9]+]], ![[PARALLEL_ACCESSES_8:[0-9]+]]
 // CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]}
-// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], ![[PARALLEL_ACCESSES_10:[0-9]+]]
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], [[MP]], ![[PARALLEL_ACCESSES_10:[0-9]+]]
 // CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
Index: clang/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
+++ clang/test/CodeGenCXX/pragma-loop-safety-imperfectly_nested.cpp
@@ -26,7 +26,8 @@
 // CHECK: ![[ACCESS_GROUP_2]] = distinct !{}
 // CHECK: ![[ACCESS_GROUP_LIST_3:[0-9]+]]  = !{![[ACCESS_GROUP_2]], ![[ACCESS_GROUP_4:[0-9]+]]}
 // CHECK: ![[ACCESS_GROUP_4]] = distinct !{}
-// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], ![[PARALLEL_ACCESSES_8:[0-9]+]]
+// CHECK: ![[INNER_LOOPID]] = distinct !{![[INNER_LOOPID]], [[MP:![0-9]+]], ![[PARALLEL_ACCESSES_8:[0-9]+]]
+// CHECK: [[MP]] = !{!"llvm.loop.mustprogress"}
 // CHECK: ![[PARALLEL_ACCESSES_8]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_4]]}
-// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], ![[PARALLEL_ACCESSES_10:[0-9]+]]
+// CHECK: ![[OUTER_LOOPID]] = distinct !{![[OUTER_LOOPID]], [[MP]], ![[PARALLEL_ACCESSES_10:[0-9]+]]
 // CHECK: ![[PARALLEL_ACCESSES_10]] = !{!"llvm.loop.parallel_accesses", ![[ACCESS_GROUP_2]]}
Index: clang/test/CodeGenCXX/pragma-loop-predicate.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-predicate.cpp
+++ clang/test/CodeGenCXX/pragma-loop-predicate.cpp
@@ -58,19 +58,19 @@
     List[i] = i * 2;
 }
 
+// CHECK:      ![[LOOP0]] = distinct !{![[LOOP0]], [[MP:![0-9]+]], [[GEN3:![0-9]+]]}
+// CHECK:      [[MP]] = !{!"llvm.loop.mustprogress"}
+// CHECK-NEXT: [[GEN3]] = !{!"llvm.loop.vectorize.enable", i1 true}
 
-// CHECK:      ![[LOOP0]] = distinct !{![[LOOP0]], !3}
-// CHECK-NEXT: !3 = !{!"llvm.loop.vectorize.enable", i1 true}
+// CHECK-NEXT: ![[LOOP1]] = distinct !{![[LOOP1]], [[MP]], [[GEN6:![0-9]+]], [[GEN3]]}
+// CHECK-NEXT: [[GEN6]] = !{!"llvm.loop.vectorize.predicate.enable", i1 true}
 
-// CHECK-NEXT: ![[LOOP1]] = distinct !{![[LOOP1]], !5, !3}
-// CHECK-NEXT: !5 = !{!"llvm.loop.vectorize.predicate.enable", i1 true}
+// CHECK-NEXT: ![[LOOP2]] = distinct !{![[LOOP2]], [[MP]], [[GEN8:![0-9]+]], [[GEN3]]}
+// CHECK-NEXT: [[GEN8]] = !{!"llvm.loop.vectorize.predicate.enable", i1 false}
 
-// CHECK-NEXT: ![[LOOP2]] = distinct !{![[LOOP2]], !7, !3}
-// CHECK-NEXT: !7 = !{!"llvm.loop.vectorize.predicate.enable", i1 false}
+// CHECK-NEXT: ![[LOOP3]] = distinct !{![[LOOP3]], [[MP]], [[GEN6]], [[GEN3]]}
 
-// CHECK-NEXT: ![[LOOP3]] = distinct !{![[LOOP3]], !5, !3}
+// CHECK-NEXT: ![[LOOP4]] = distinct !{![[LOOP4]], [[MP]], [[GEN10:![0-9]+]]}
+// CHECK-NEXT: [[GEN10]] = !{!"llvm.loop.vectorize.width", i32 1}
 
-// CHECK-NEXT: ![[LOOP4]] = distinct !{![[LOOP4]], !10}
-// CHECK-NEXT: !10 = !{!"llvm.loop.vectorize.width", i32 1}
-
-// CHECK-NEXT: ![[LOOP5]] = distinct !{![[LOOP5]], !10}
+// CHECK-NEXT: ![[LOOP5]] = distinct !{![[LOOP5]], [[MP]], [[GEN10]]}
Index: clang/test/CodeGenCXX/pragma-loop-pr27643.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-pr27643.cpp
+++ clang/test/CodeGenCXX/pragma-loop-pr27643.cpp
@@ -40,13 +40,13 @@
     List[i] = i * 2;
 }
 
-// CHECK: ![[LOOP1]] = distinct !{![[LOOP1]], ![[VEC_WIDTH_1:.*]], ![[VEC_ENABLE:.*]]}
+// CHECK: ![[LOOP1]] = distinct !{![[LOOP1]], [[MP:![0-9]+]], ![[VEC_WIDTH_1:.*]], ![[VEC_ENABLE:.*]]}
 // CHECK: ![[VEC_WIDTH_1]] = !{!"llvm.loop.vectorize.width", i32 1}
 // CHECK: ![[VEC_ENABLE]] = !{!"llvm.loop.vectorize.enable", i1 true}
 
-// CHECK: ![[LOOP2]] = distinct !{![[LOOP2]], ![[VEC_WIDTH_2:.*]], ![[VEC_ENABLE]]}
+// CHECK: ![[LOOP2]] = distinct !{![[LOOP2]], [[MP]], ![[VEC_WIDTH_2:.*]], ![[VEC_ENABLE]]}
 // CHECK: ![[VEC_WIDTH_2]] = !{!"llvm.loop.vectorize.width", i32 2}
 
-// CHECK: ![[LOOP3]] = distinct !{![[LOOP3]], ![[VEC_WIDTH_1]]}
+// CHECK: ![[LOOP3]] = distinct !{![[LOOP3]], [[MP]], ![[VEC_WIDTH_1]]}
 
-// CHECK: ![[LOOP4]] = distinct !{![[LOOP4]], ![[VEC_WIDTH_2]], ![[VEC_ENABLE]]}
+// CHECK: ![[LOOP4]] = distinct !{![[LOOP4]], [[MP]], ![[VEC_WIDTH_2]], ![[VEC_ENABLE]]}
Index: clang/test/CodeGenCXX/pragma-loop-distribute.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-loop-distribute.cpp
+++ clang/test/CodeGenCXX/pragma-loop-distribute.cpp
@@ -13,11 +13,12 @@
 
   i = 0;
   while (i < Length2) {
-    // CHECK-NOT: br label {{.*}}, !llvm.loop
+    // CHECK: br label {{.*}}, !llvm.loop [[LOOP_2:![0-9]+]]
     List2[i] = i * 2;
     i++;
   }
 }
 
-// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[DISTRIBUTE_ENABLE:.*]]}
+// CHECK: ![[LOOP_1]] = distinct !{![[LOOP_1]], [[MP:![0-9]+]], ![[DISTRIBUTE_ENABLE:.*]]}
 // CHECK: ![[DISTRIBUTE_ENABLE]] = !{!"llvm.loop.distribute.enable", i1 true}
+// CHECK: [[LOOP_2]] = distinct !{[[LOOP_2]], [[MP]]}
Index: clang/test/CodeGenCXX/pragma-followup_outer.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-followup_outer.cpp
+++ clang/test/CodeGenCXX/pragma-followup_outer.cpp
@@ -17,25 +17,25 @@
 
 // CHECK-DAG: ![[ACCESSGROUP_2:[0-9]+]] = distinct !{}
 
-// CHECK-DAG: ![[LOOP_3:[0-9]+]] = distinct !{![[LOOP_3:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[DISTRIBUTE_5:[0-9]+]], ![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]]}
+// CHECK-DAG: ![[LOOP_3:[0-9]+]] = distinct !{![[LOOP_3:[0-9]+]], [[MP:![0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[DISTRIBUTE_5:[0-9]+]], ![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]]}
 // CHECK-DAG: ![[PARALLEL_ACCESSES_4:[0-9]+]] = !{!"llvm.loop.parallel_accesses", ![[ACCESSGROUP_2]]}
 // CHECK-DAG: ![[DISTRIBUTE_5:[0-9]+]] = !{!"llvm.loop.distribute.enable", i1 true}
 // CHECK-DAG: ![[DISTRIBUTE_FOLLOWUP_6:[0-9]+]] = !{!"llvm.loop.distribute.followup_all", ![[LOOP_7:[0-9]+]]}
 
-// CHECK-DAG: ![[LOOP_7:[0-9]+]] = distinct !{![[LOOP_7:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[VECTORIZE_8:[0-9]+]], ![[VECTORIZE_FOLLOWUP_9:[0-9]+]]}
+// CHECK-DAG: ![[LOOP_7:[0-9]+]] = distinct !{![[LOOP_7:[0-9]+]], [[MP]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[VECTORIZE_8:[0-9]+]], ![[VECTORIZE_FOLLOWUP_9:[0-9]+]]}
 // CHECK-DAG: ![[VECTORIZE_8:[0-9]+]] = !{!"llvm.loop.vectorize.enable", i1 true}
 // CHECK-DAG: ![[VECTORIZE_FOLLOWUP_9:[0-9]+]] = !{!"llvm.loop.vectorize.followup_all", ![[LOOP_10:[0-9]+]]}
 
-// CHECK-DAG: ![[LOOP_10:[0-9]+]] = distinct !{![[LOOP_10:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_12:[0-9]+]], ![[UNROLLANDJAM_FOLLOWUPOUTER_13:[0-9]+]]}
+// CHECK-DAG: ![[LOOP_10:[0-9]+]] = distinct !{![[LOOP_10:[0-9]+]], [[MP]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_12:[0-9]+]], ![[UNROLLANDJAM_FOLLOWUPOUTER_13:[0-9]+]]}
 // CHECK-DAG: ![[ISVECTORIZED_11:[0-9]+]] = !{!"llvm.loop.isvectorized"}
 // CHECK-DAG: ![[UNROLLANDJAM_12:[0-9]+]] =  !{!"llvm.loop.unroll_and_jam.enable"}
 // CHECK-DAG: ![[UNROLLANDJAM_FOLLOWUPOUTER_13:[0-9]+]] = !{!"llvm.loop.unroll_and_jam.followup_outer", ![[LOOP_14:[0-9]+]]}
 
-// CHECK-DAG: ![[LOOP_14:[0-9]+]] = distinct !{![[LOOP_14:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_DISABLE_15:[0-9]+]], ![[UNROLL_COUNT_16:[0-9]+]], ![[UNROLL_FOLLOWUP_17:[0-9]+]]}
+// CHECK-DAG: ![[LOOP_14:[0-9]+]] = distinct !{![[LOOP_14:[0-9]+]], [[MP]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_DISABLE_15:[0-9]+]], ![[UNROLL_COUNT_16:[0-9]+]], ![[UNROLL_FOLLOWUP_17:[0-9]+]]}
 // CHECK-DAG: ![[UNROLLANDJAM_DISABLE_15:[0-9]+]]  = !{!"llvm.loop.unroll_and_jam.disable"}
 // CHECK-DAG: ![[UNROLL_COUNT_16:[0-9]+]] = !{!"llvm.loop.unroll.count", i32 4}
 // CHECK-DAG: ![[UNROLL_FOLLOWUP_17:[0-9]+]] = !{!"llvm.loop.unroll.followup_all", ![[LOOP_18:[0-9]+]]}
 
-// CHECK-DAG: ![[LOOP_18:[0-9]+]] = distinct !{![[LOOP_18:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_DISABLE_15:[0-9]+]], ![[UNROLL_DISABLE_19:[0-9]+]], ![[INITIATIONINTERVAL_20:[0-9]+]]}
+// CHECK-DAG: ![[LOOP_18:[0-9]+]] = distinct !{![[LOOP_18:[0-9]+]], [[MP]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_11:[0-9]+]], ![[UNROLLANDJAM_DISABLE_15:[0-9]+]], ![[UNROLL_DISABLE_19:[0-9]+]], ![[INITIATIONINTERVAL_20:[0-9]+]]}
 // CHECK-DAG: ![[UNROLL_DISABLE_19:[0-9]+]]  = !{!"llvm.loop.unroll.disable"}
 // CHECK-DAG: ![[INITIATIONINTERVAL_20:[0-9]+]] = !{!"llvm.loop.pipeline.initiationinterval", i32 10}
Index: clang/test/CodeGenCXX/pragma-followup_inner.cpp
===================================================================
--- clang/test/CodeGenCXX/pragma-followup_inner.cpp
+++ clang/test/CodeGenCXX/pragma-followup_inner.cpp
@@ -28,9 +28,9 @@
 // CHECK-DAG: ![[LOOP_7:[0-9]+]] = distinct !{![[LOOP_7:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[VECTORIZE_8:[0-9]+]]}
 // CHECK-DAG: ![[VECTORIZE_8:[0-9]+]] = !{!"llvm.loop.vectorize.enable", i1 true}
 
-// CHECK-DAG: ![[OUTERLOOP_9:[0-9]+]] = distinct !{![[OUTERLOOP_9:[0-9]+]], ![[UNROLLANDJAM_COUNT_10:[0-9]+]], ![[UNROLLANDJAM_FOLLOWUPINNER_11:[0-9]+]]}
+// CHECK-DAG: ![[OUTERLOOP_9:[0-9]+]] = distinct !{![[OUTERLOOP_9:[0-9]+]], [[MP:![0-9]+]], ![[UNROLLANDJAM_COUNT_10:[0-9]+]], ![[UNROLLANDJAM_FOLLOWUPINNER_11:[0-9]+]]}
 // CHECK-DAG: ![[UNROLLANDJAM_COUNT_10:[0-9]+]] = !{!"llvm.loop.unroll_and_jam.count", i32 4}
-// CHECK-DAG: ![[UNROLLANDJAM_FOLLOWUPINNER_11:[0-9]+]] = !{!"llvm.loop.unroll_and_jam.followup_inner", !12}
+// CHECK-DAG: ![[UNROLLANDJAM_FOLLOWUPINNER_11:[0-9]+]] = !{!"llvm.loop.unroll_and_jam.followup_inner", !13}
 
 // CHECK-DAG: ![[LOOP_12:[0-9]+]] = distinct !{![[LOOP_12:[0-9]+]], ![[PARALLEL_ACCESSES_4:[0-9]+]], ![[ISVECTORIZED_13:[0-9]+]], ![[UNROLL_COUNT_13:[0-9]+]], ![[UNROLL_FOLLOWUP_14:[0-9]+]]}
 // CHECK-DAG: ![[ISVECTORIZED_13:[0-9]+]] = !{!"llvm.loop.isvectorized"}
Index: clang/test/CodeGenCXX/fno-unroll-loops-metadata.cpp
===================================================================
--- clang/test/CodeGenCXX/fno-unroll-loops-metadata.cpp
+++ clang/test/CodeGenCXX/fno-unroll-loops-metadata.cpp
@@ -4,7 +4,7 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s -O3 -disable-llvm-optzns -fno-unroll-loops | FileCheck --check-prefix=UNROLL_DISABLED_MD %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - %s -O3 -disable-llvm-optzns | FileCheck --check-prefix=NO_UNROLL_MD %s
 
-// NO_UNROLL_MD-NOT: llvm.loop
+// NO_UNROLL_MD-NOT: llvm.loop.unroll.disable
 
 // Verify unroll.disable metadata is added to while loop with -fno-unroll-loops
 // and optlevel > 0.
@@ -13,7 +13,7 @@
   int i = 0;
 
   while (i < Length) {
-    // UNROLL_DISABLED_MD: br label {{.*}}, !llvm.loop ![[LOOP_1:.*]]
+    // UNROLL_DISABLED_MD: br label {{.*}}, !llvm.loop [[LOOP_1:![0-9]+]]
     List[i] = i * 2;
     i++;
   }
@@ -26,7 +26,7 @@
   int i = 0;
 
   do {
-    // UNROLL_DISABLED_MD: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop ![[LOOP_2:.*]]
+    // UNROLL_DISABLED_MD: br i1 {{.*}}, label {{.*}}, label {{.*}}, !llvm.loop [[LOOP_2:![0-9]+]]
     List[i] = i * 2;
     i++;
   } while (i < Length);
@@ -37,12 +37,13 @@
 void for_test(int *List, int Length) {
   // UNROLL_DISABLED_MD: define {{.*}} @_Z8for_test
   for (int i = 0; i < Length; i++) {
-    // UNROLL_DISABLED_MD: br label {{.*}}, !llvm.loop ![[LOOP_3:.*]]
+    // UNROLL_DISABLED_MD: br label {{.*}}, !llvm.loop [[LOOP_3:![0-9]+]]
     List[i] = i * 2;
   }
 }
 
-// UNROLL_DISABLED_MD: ![[LOOP_1]] = distinct !{![[LOOP_1]], ![[UNROLL_DISABLE:.*]]}
-// UNROLL_DISABLED_MD: ![[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
-// UNROLL_DISABLED_MD: ![[LOOP_2]] = distinct !{![[LOOP_2:.*]], ![[UNROLL_DISABLE:.*]]}
-// UNROLL_DISABLED_MD: ![[LOOP_3]] = distinct !{![[LOOP_3]], ![[UNROLL_DISABLE:.*]]}
+// UNROLL_DISABLED_MD: [[LOOP_1]] = distinct !{[[LOOP_1]], [[MP:![0-9]+]], [[UNROLL_DISABLE:![0-9]+]]}
+// UNROLL_DISABLED_MD: [[MP]] = !{!"llvm.loop.mustprogress"}
+// UNROLL_DISABLED_MD: [[UNROLL_DISABLE]] = !{!"llvm.loop.unroll.disable"}
+// UNROLL_DISABLED_MD: [[LOOP_2]] = distinct !{[[LOOP_2]], [[MP]], [[UNROLL_DISABLE]]}
+// UNROLL_DISABLED_MD: [[LOOP_3]] = distinct !{[[LOOP_3]], [[MP]], [[UNROLL_DISABLE]]}
Index: clang/test/CodeGenCXX/debug-info-loops.cpp
===================================================================
--- clang/test/CodeGenCXX/debug-info-loops.cpp
+++ clang/test/CodeGenCXX/debug-info-loops.cpp
@@ -35,7 +35,7 @@
   // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, column: 3, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 105, column: 3, scope: !{{.*}})
 
-  // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]}
+  // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]], [[MP:![0-9]+]]}
   // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, column: 3, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, column: 9, scope: !{{.*}})
 
@@ -43,7 +43,7 @@
   // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 302, column: 5, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 303, column: 9, scope: !{{.*}})
   //
-  // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]]}
+  // CHECK-DAG: [[L4]] = distinct !{[[L4]], [[SLDBG4:![0-9]*]], [[ELDBG4:![0-9]*]], [[MP]]}
   // CHECK-DAG: [[SLDBG4]] = !DILocation(line: 300, column: 3, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG4]] = !DILocation(line: 304, column: 3, scope: !{{.*}})
 }
Index: clang/test/CodeGenCXX/debug-info-line-if.cpp
===================================================================
--- clang/test/CodeGenCXX/debug-info-line-if.cpp
+++ clang/test/CodeGenCXX/debug-info-line-if.cpp
@@ -57,11 +57,11 @@
   // CHECK-DAG: [[SLDBG1]] = !DILocation(line: 100, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG1]] = !DILocation(line: 104, scope: !{{.*}})
 
-  // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]]}
+  // CHECK-DAG: [[L2]] = distinct !{[[L2]], [[SLDBG2:![0-9]*]], [[ELDBG2:![0-9]*]], [[MP:![0-9]+]]}
   // CHECK-DAG: [[SLDBG2]] = !DILocation(line: 200, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG2]] = !DILocation(line: 204, scope: !{{.*}})
 
-  // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]]}
+  // CHECK-DAG: [[L3]] = distinct !{[[L3]], [[SLDBG3:![0-9]*]], [[ELDBG3:![0-9]*]], [[MP]]}
   // CHECK-DAG: [[SLDBG3]] = !DILocation(line: 300, scope: !{{.*}})
   // CHECK-DAG: [[ELDBG3]] = !DILocation(line: 304, scope: !{{.*}})
 
Index: clang/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
===================================================================
--- clang/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
+++ clang/test/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
@@ -1,7 +1,11 @@
-// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o %t-c++11.ll %s -triple x86_64-apple-darwin10 
+// RUN: %clang_cc1 -std=c++11 -S -emit-llvm -o %t-c++11.ll %s -triple x86_64-apple-darwin10
 // RUN: FileCheck %s < %t-c++11.ll
-// RUN: %clang_cc1  -std=c++98 -S -emit-llvm -o %t.ll %s -triple x86_64-apple-darwin10 
-// RUN: diff %t.ll  %t-c++11.ll
+// RUN: %clang_cc1 -std=c++17 -S -emit-llvm -o %t-c++17.ll %s -triple x86_64-apple-darwin10
+// RUN: FileCheck %s < %t-c++17.ll
+// RUN: %clang_cc1  -std=c++98 -S -emit-llvm -o %t.ll %s -triple x86_64-apple-darwin10
+// RUN: %clang_cc1  -std=c++03 -S -emit-llvm -o %t-c++03.ll %s -triple x86_64-apple-darwin10
+// RUN: diff %t-c++11.ll  %t-c++17.ll
+// RUN: diff %t.ll  %t-c++03.ll
 
 // rdar://12897704
 
Index: clang/test/CodeGen/pragma-do-while.cpp
===================================================================
--- clang/test/CodeGen/pragma-do-while.cpp
+++ clang/test/CodeGen/pragma-do-while.cpp
@@ -17,8 +17,9 @@
 // CHECK: br {{.*}}, label %do.body, label %do.end, !llvm.loop ![[LMD1:[0-9]+]]
 // CHECK-LABEL: do.end:
 // CHECK-NOT: llvm.loop
-// CHECK: ![[LMD1]] = distinct !{![[LMD1]], ![[LMD2:[0-9]+]]}
-// CHECK: ![[LMD2]] = !{!"llvm.loop.unroll.count", i32 4}
+// CHECK: ![[LMD1]] = distinct !{![[LMD1]], [[LMD2:![0-9]+]], ![[LMD3:[0-9]+]]}
+// CHECK: [[LMD2]] = !{!"llvm.loop.mustprogress"}
+// CHECK: ![[LMD3]] = !{!"llvm.loop.unroll.count", i32 4}
 
 int test(int a[], int n) {
   int i = 0;
Index: clang/test/CodeGen/no-builtin.cpp
===================================================================
--- clang/test/CodeGen/no-builtin.cpp
+++ clang/test/CodeGen/no-builtin.cpp
@@ -43,7 +43,7 @@
 
 // CHECK-LABEL: define void @call_foo_no_mempcy() #3
 extern "C" void call_foo_no_mempcy() {
-  // CHECK: call void @foo_no_mempcy() #6
+  // CHECK: call void @foo_no_mempcy() #7
   foo_no_mempcy(); // call gets annotated with "no-builtin-memcpy"
 }
 
@@ -51,7 +51,7 @@
 B::~B() {} // Anchoring B so B::foo() gets generated
 
 // CHECK-LABEL: define linkonce_odr i32 @_ZNK1A3fooEv(%struct.A* %this) unnamed_addr #0 comdat align 2
-// CHECK-LABEL: define linkonce_odr i32 @_ZNK1B3fooEv(%struct.B* %this) unnamed_addr #5 comdat align 2
+// CHECK-LABEL: define linkonce_odr i32 @_ZNK1B3fooEv(%struct.B* %this) unnamed_addr #6 comdat align 2
 
 // CHECK:     attributes #0 = {{{.*}}"no-builtin-memcpy"{{.*}}}
 // CHECK-NOT: attributes #0 = {{{.*}}"no-builtin-memmove"{{.*}}}
@@ -59,7 +59,7 @@
 // CHECK:     attributes #1 = {{{.*}}"no-builtins"{{.*}}}
 // CHECK:     attributes #2 = {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}}
 // CHECK-NOT: attributes #2 = {{{.*}}"no-builtin-memmove"{{.*}}}
-// CHECK:     attributes #5 = {{{.*}}"no-builtin-memmove"{{.*}}}
+// CHECK:     attributes #6 = {{{.*}}"no-builtin-memmove"{{.*}}}
 // CHECK-NOT: attributes #5 = {{{.*}}"no-builtin-memcpy"{{.*}}}
 // CHECK-NOT: attributes #5 = {{{.*}}"no-builtin-memset"{{.*}}}
-// CHECK:     attributes #6 = { "no-builtin-memcpy" }
+// CHECK:     attributes #7 = { "no-builtin-memcpy" }
Index: clang/test/CodeGen/memtag-attr.cpp
===================================================================
--- clang/test/CodeGen/memtag-attr.cpp
+++ clang/test/CodeGen/memtag-attr.cpp
@@ -9,11 +9,11 @@
 // RUN:   FileCheck -check-prefix=CHECK-MEMTAG %s
 
 int HasSanitizeMemTag() { return 1; }
-// CHECK-NO: {{Function Attrs: noinline nounwind$}}
+// CHECK-NO: {{Function Attrs: noinline nounwind mustprogress$}}
 // CHECK-MEMTAG: Function Attrs: noinline nounwind sanitize_memtag
 
 __attribute__((no_sanitize("memtag"))) int NoSanitizeQuoteAddress() {
   return 0;
 }
-// CHECK-NO: {{Function Attrs: noinline nounwind$}}
-// CHECK-MEMTAG: {{Function Attrs: noinline nounwind$}}
+// CHECK-NO: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-MEMTAG: {{Function Attrs: noinline nounwind mustprogress$}}
Index: clang/test/CodeGen/attr-mustprogress-1.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-mustprogress-1.cpp
@@ -0,0 +1,270 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clangxx -std=c++11 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clangxx -std=c++14 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clangxx -std=c++17 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clangxx -std=c++20 -S -emit-llvm %s -o - | FileCheck %s
+
+int a = 0;
+int b = 0;
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2f1v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f1() {
+  for (; 1;)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable mustprogress
+// CHECK-LABEL: @_Z2f2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP2:!.*]]
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f2() {
+  for (; a == b;)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z1Fv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    br label [[FOR_COND1:%.*]]
+// CHECK:       for.cond1:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]]
+// CHECK:       for.body2:
+// CHECK-NEXT:    br label [[FOR_COND1]], !llvm.loop [[LOOP4:!.*]]
+// CHECK:       for.end3:
+// CHECK-NEXT:    ret void
+//
+void F() {
+  for (; 1;)
+    ;
+  for (; a == b;)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2F2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP5:!.*]]
+// CHECK:       for.end:
+// CHECK-NEXT:    br label [[FOR_COND1:%.*]]
+// CHECK:       for.cond1:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]]
+// CHECK:       for.body2:
+// CHECK-NEXT:    br label [[FOR_COND1]]
+// CHECK:       for.end3:
+// CHECK-NEXT:    ret void
+//
+void F2() {
+  for (; a == b;)
+    ;
+  for (; 1;)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2w1v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_BODY]]
+//
+void w1() {
+  while (1)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable mustprogress
+// CHECK-LABEL: @_Z2w2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]], !llvm.loop [[LOOP6:!.*]]
+// CHECK:       while.end:
+// CHECK-NEXT:    ret void
+//
+void w2() {
+  while (a == b)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z1Wv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]], !llvm.loop [[LOOP7:!.*]]
+// CHECK:       while.end:
+// CHECK-NEXT:    br label [[WHILE_BODY2:%.*]]
+// CHECK:       while.body2:
+// CHECK-NEXT:    br label [[WHILE_BODY2]]
+//
+void W() {
+  while (a == b)
+    ;
+  while (1)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2W2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_BODY]]
+//
+void W2() {
+  while (1)
+    ;
+  while (a == b)
+    ;
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2d1v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d1() {
+  do
+    ;
+  while (1);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable mustprogress
+// CHECK-LABEL: @_Z2d2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], !llvm.loop [[LOOP8:!.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d2() {
+  do
+    ;
+  while (a == b);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z1Dv(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    br label [[DO_BODY1:%.*]]
+// CHECK:       do.body1:
+// CHECK-NEXT:    br label [[DO_COND2:%.*]]
+// CHECK:       do.cond2:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], !llvm.loop [[LOOP9:!.*]]
+// CHECK:       do.end3:
+// CHECK-NEXT:    ret void
+//
+void D() {
+  do
+    ;
+  while (1);
+  do
+    ;
+  while (a == b);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @_Z2D2v(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], !llvm.loop [[LOOP10:!.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    br label [[DO_BODY1:%.*]]
+// CHECK:       do.body1:
+// CHECK-NEXT:    br label [[DO_COND2:%.*]]
+// CHECK:       do.cond2:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY1]], label [[DO_END3:%.*]]
+// CHECK:       do.end3:
+// CHECK-NEXT:    ret void
+//
+void D2() {
+  do
+    ;
+  while (a == b);
+  do
+    ;
+  while (1);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[GEN3:![0-9]+]]}
+// CHECK: [[GEN3]] = !{!"llvm.loop.mustprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[GEN3]]}
+// CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[GEN3]]}
+// CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[GEN3]]}
+// CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[GEN3]]}
+// CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[GEN3]]}
+// CHECK: [[LOOP9]] = distinct !{[[LOOP9]], [[GEN3]]}
+// CHECK: [[LOOP10]] = distinct !{[[LOOP10]], [[GEN3]]}
Index: clang/test/CodeGen/attr-mustprogress-1.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-mustprogress-1.c
@@ -0,0 +1,186 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -std=c11 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -std=c18 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -std=c2x -S -emit-llvm %s -o - | FileCheck %s
+
+int a = 0;
+int b = 0;
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @f1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f1() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @f2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]], !llvm.loop [[LOOP2:!.*]]
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f2() {
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @F(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    br label [[FOR_COND1:%.*]]
+// CHECK:       for.cond1:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]]
+// CHECK:       for.body2:
+// CHECK-NEXT:    br label [[FOR_COND1]], !llvm.loop [[LOOP4:!.*]]
+// CHECK:       for.end3:
+// CHECK-NEXT:    ret void
+//
+void F() {
+  for (; 1;) {
+  }
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @w1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_BODY]]
+//
+void w1() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @w2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]], !llvm.loop [[LOOP5:.*]]
+// CHECK:       while.end:
+// CHECK-NEXT:    ret void
+//
+void w2() {
+  while (a == b) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @W(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]], !llvm.loop [[LOOP6:!.*]]
+// CHECK:       while.end:
+// CHECK-NEXT:    br label [[WHILE_BODY2:%.*]]
+// CHECK:       while.body2:
+// CHECK-NEXT:    br label [[WHILE_BODY2]]
+//
+void W() {
+  while (a == b) {
+  }
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @d1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d1() {
+  do {
+  } while (1);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @d2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], !llvm.loop [[LOOP7:!.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d2() {
+  do {
+  } while (a == b);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @D(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    br label [[DO_BODY1:%.*]]
+// CHECK:       do.body1:
+// CHECK-NEXT:    br label [[DO_COND2:%.*]]
+// CHECK:       do.cond2:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], !llvm.loop [[LOOP8:!.*]]
+// CHECK:       do.end3:
+// CHECK-NEXT:    ret void
+//
+void D() {
+  do {
+  } while (1);
+  do {
+  } while (a == b);
+}
Index: clang/test/CodeGen/attr-mustprogress-0.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-mustprogress-0.cpp
@@ -0,0 +1,183 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang++ -std=c++98 -S -emit-llvm %s -o - | FileCheck %s
+
+int a = 0;
+int b = 0;
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}f1{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK:         br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK:         br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK:         ret void
+//
+void f1() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}f2{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A:@.*]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B:@.*]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK:         br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK:         ret void
+//
+void f2() {
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}F{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK:         br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK:         br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK:         br label [[FOR_COND1:%.*]]
+// CHECK:       for.cond1:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]]
+// CHECK:       for.body2:
+// CHECK:         br label [[FOR_COND1]]
+// CHECK:       for.end3:
+// CHECK:         ret void
+//
+void F() {
+  for (; 1;) {
+  }
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}w1{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       while.body:
+// CHECK:         br label [[WHILE_BODY]]
+//
+void w1() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}w2{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK:         br label [[WHILE_COND]]
+// CHECK:       while.end:
+// CHECK:         ret void
+//
+void w2() {
+  while (a == b) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}W{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK:         br label [[WHILE_COND]]
+// CHECK:       while.end:
+// CHECK:         br label [[WHILE_BODY2:%.*]]
+// CHECK:       while.body2:
+// CHECK:         br label [[WHILE_BODY2]]
+//
+void W() {
+  while (a == b) {
+  }
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}d1{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK:         br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK:         br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK:         ret void
+//
+void d1() {
+  do {
+  } while (1);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}d2{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK:         br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK:         ret void
+//
+void d2() {
+  do {
+  } while (a == b);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: @{{.*}}D{{.*}}(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK:         br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK:         br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK:         br label [[DO_BODY1:%.*]]
+// CHECK:       do.body1:
+// CHECK:         br label [[DO_COND2:%.*]]
+// CHECK:       do.cond2:
+// CHECK:         [[TMP0:%.*]] = load i32, i32* [[VAR_A]], align 4
+// CHECK:         [[TMP1:%.*]] = load i32, i32* [[VAR_B]], align 4
+// CHECK:         [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK:         br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]]
+// CHECK:       do.end3:
+// CHECK:         ret void
+//
+void D() {
+  do {
+  } while (1);
+  do {
+  } while (a == b);
+}
Index: clang/test/CodeGen/attr-mustprogress-0.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-mustprogress-0.c
@@ -0,0 +1,184 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang -std=c89 -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -std=c99 -S -emit-llvm %s -o - | FileCheck %s
+
+int a = 0;
+int b = 0;
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @f1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f1() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @f2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]{{$}}
+// CHECK:       for.end:
+// CHECK-NEXT:    ret void
+//
+void f2() {
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @F(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[FOR_COND:%.*]]
+// CHECK:       for.cond:
+// CHECK-NEXT:    br i1 true, label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
+// CHECK:       for.body:
+// CHECK-NEXT:    br label [[FOR_COND]]
+// CHECK:       for.end:
+// CHECK-NEXT:    br label [[FOR_COND1:%.*]]
+// CHECK:       for.cond1:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[FOR_BODY2:%.*]], label [[FOR_END3:%.*]]
+// CHECK:       for.body2:
+// CHECK-NEXT:    br label [[FOR_COND1]]{{$}}
+// CHECK:       for.end3:
+// CHECK-NEXT:    ret void
+//
+void F() {
+  for (; 1;) {
+  }
+  for (; a == b;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @w1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_BODY]]
+//
+void w1() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @w2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]{{$}}
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]]
+// CHECK:       while.end:
+// CHECK-NEXT:    ret void
+//
+void w2() {
+  while (a == b) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @W(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[WHILE_COND:%.*]]
+// CHECK:       while.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[WHILE_BODY:%.*]], label [[WHILE_END:%.*]]
+// CHECK:       while.body:
+// CHECK-NEXT:    br label [[WHILE_COND]]
+// CHECK:       while.end:
+// CHECK-NEXT:    br label [[WHILE_BODY2:%.*]]
+// CHECK:       while.body2:
+// CHECK-NEXT:    br label [[WHILE_BODY2]]
+//
+void W() {
+  while (a == b) {
+  }
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @d1(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d1() {
+  do {
+  } while (1);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @d2(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]]{{$}}
+// CHECK:       do.end:
+// CHECK-NEXT:    ret void
+//
+void d2() {
+  do {
+  } while (a == b);
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone uwtable
+// CHECK-LABEL: @D(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    br label [[DO_BODY:%.*]]
+// CHECK:       do.body:
+// CHECK-NEXT:    br label [[DO_COND:%.*]]
+// CHECK:       do.cond:
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK:       do.end:
+// CHECK-NEXT:    br label [[DO_BODY1:%.*]]
+// CHECK:       do.body1:
+// CHECK-NEXT:    br label [[DO_COND2:%.*]]
+// CHECK:       do.cond2:
+// CHECK-NEXT:    [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT:    [[TMP1:%.*]] = load i32, i32* @b, align 4
+// CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT:    br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]]{{$}}
+// CHECK:       do.end3:
+// CHECK-NEXT:    ret void
+//
+void D() {
+  do {
+  } while (1);
+  do {
+  } while (a == b);
+}
Index: clang/test/CodeGen/address-safety-attr.cpp
===================================================================
--- clang/test/CodeGen/address-safety-attr.cpp
+++ clang/test/CodeGen/address-safety-attr.cpp
@@ -35,8 +35,7 @@
 // ASAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
 // ASAN: @__cxx_global_array_dtor{{.*}}[[WITH]]
 
-
-// WITHOUT:  NoAddressSafety1{{.*}}) [[NOATTR]]
+// WITHOUT:  NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
 // BLFILE:  NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
 // BLFUNC:  NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
 // ASAN:  NoAddressSafety1{{.*}}) [[NOATTR:#[0-9]+]]
@@ -83,8 +82,8 @@
 
 // WITHOUT:  AddressSafetyOk{{.*}}) [[NOATTR]]
 // BLFILE:  AddressSafetyOk{{.*}}) [[NOATTR]]
-// BLFUNC: AddressSafetyOk{{.*}}) [[WITH]]
-// ASAN: AddressSafetyOk{{.*}}) [[WITH]]
+// BLFUNC: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]]
+// ASAN: AddressSafetyOk{{.*}}) [[WITH:#[0-9]+]]
 int AddressSafetyOk(int *a) { return *a; }
 
 // WITHOUT:  BlacklistedFunction{{.*}}) [[NOATTR]]
@@ -138,10 +137,10 @@
 // Check that __cxx_global_var_init* get the sanitize_address attribute.
 int global1 = 0;
 int global2 = *(int*)((char*)&global1+1);
-// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR]]
+// WITHOUT: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
 // BLFILE: @__cxx_global_var_init{{.*}}[[NOATTR:#[0-9]+]]
-// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH]]
-// ASAN: @__cxx_global_var_init{{.*}}[[WITH]]
+// BLFUNC: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
+// ASAN: @__cxx_global_var_init{{.*}}[[WITH:#[0-9]+]]
 
 // WITHOUT: attributes [[NOATTR]] = { noinline nounwind{{.*}} }
 
Index: clang/test/CodeGen/address-safety-attr-flavors.cpp
===================================================================
--- clang/test/CodeGen/address-safety-attr-flavors.cpp
+++ clang/test/CodeGen/address-safety-attr-flavors.cpp
@@ -25,51 +25,51 @@
 // RUN:   FileCheck -check-prefix=CHECK-KHWASAN %s
 
 int HasSanitizeAddress() { return 1; }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address
-// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address
-// CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress
-// CHECK-KHWASAN: Function Attrs: noinline nounwind sanitize_hwaddress
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: Function Attrs: noinline nounwind sanitize_address mustprogress
+// CHECK-KASAN: Function Attrs: noinline nounwind sanitize_address mustprogress
+// CHECK-HWASAN: Function Attrs: noinline nounwind sanitize_hwaddress mustprogress
+// CHECK-KHWASAN: Function Attrs: noinline nounwind sanitize_hwaddress mustprogress
 
 __attribute__((no_sanitize("address"))) int NoSanitizeQuoteAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
 
 __attribute__((no_sanitize_address)) int NoSanitizeAddress() { return 0; }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
 
 __attribute__((no_sanitize("kernel-address"))) int NoSanitizeKernelAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
-// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind sanitize_hwaddress mustprogress$}}
 
 __attribute__((no_sanitize("hwaddress"))) int NoSanitizeHWAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address mustprogress$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address mustprogress$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind mustprogress$}}
 
 __attribute__((no_sanitize("kernel-hwaddress"))) int NoSanitizeKernelHWAddress() {
   return 0;
 }
-// CHECK-NOASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address$}}
-// CHECK-HWASAN: {{Function Attrs: noinline nounwind$}}
-// CHECK-KHWASAN: {{Function Attrs: noinline nounwind$}}
+// CHECK-NOASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-ASAN: {{Function Attrs: noinline nounwind sanitize_address mustprogress$}}
+// CHECK-KASAN: {{Function Attrs: noinline nounwind sanitize_address mustprogress$}}
+// CHECK-HWASAN: {{Function Attrs: noinline nounwind mustprogress$}}
+// CHECK-KHWASAN: {{Function Attrs: noinline nounwind mustprogress$}}
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -502,6 +502,26 @@
   /// True if the current statement has nomerge attribute.
   bool InNoMergeAttributedStmt = false;
 
+  /// True if the current function should be marked mustprogress.
+  bool FnIsMustProgress = false;
+
+  /// True if the C++ Standard Requires Progress.
+  bool CPlusPlusWithProgress() {
+    return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
+           getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20;
+  }
+
+  /// True if the C Standard Requires Progress.
+  bool CWithProgress() {
+    return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x;
+  }
+
+  /// True if the language standard requires progress in functions or
+  /// in infinite loops with non-constant conditionals.
+  bool LanguageRequiresProgress() {
+    return CWithProgress() || CPlusPlusWithProgress();
+  }
+
   const CodeGen::CGBlockInfo *BlockInfo = nullptr;
   llvm::Value *BlockPointer = nullptr;
 
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1159,10 +1159,18 @@
 
 void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
   incrementProfileCounter(Body);
+  if (CPlusPlusWithProgress())
+    FnIsMustProgress = true;
+
   if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
     EmitCompoundStmtWithoutScope(*S);
   else
     EmitStmt(Body);
+
+  // This is checked after emitting the function body so we know if there
+  // are any permitted infinite loops.
+  if (FnIsMustProgress)
+    CurFn->addFnAttr(llvm::Attribute::MustProgress);
 }
 
 /// When instrumenting to collect profile data, the counts for some blocks
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -742,11 +742,6 @@
   JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
   EmitBlock(LoopHeader.getBlock());
 
-  const SourceRange &R = S.getSourceRange();
-  LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
-                 WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
-                 SourceLocToDebugLoc(R.getEnd()));
-
   // Create an exit block for when the condition fails, which will
   // also become the break target.
   JumpDest LoopExit = getJumpDestInCurrentScope("while.end");
@@ -774,9 +769,19 @@
   // while(1) is common, avoid extra exit blocks.  Be sure
   // to correctly handle break/continue though.
   bool EmitBoolCondBranch = true;
-  if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
-    if (C->isOne())
+  bool LoopMustProgress = false;
+  if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
+    if (C->isOne()) {
       EmitBoolCondBranch = false;
+      FnIsMustProgress = false;
+    }
+  } else if (LanguageRequiresProgress())
+    LoopMustProgress = true;
+
+  const SourceRange &R = S.getSourceRange();
+  LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
+                 WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
+                 SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
 
   // As long as the condition is true, go to the loop body.
   llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
@@ -844,11 +849,6 @@
 
   EmitBlock(LoopCond.getBlock());
 
-  const SourceRange &R = S.getSourceRange();
-  LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
-                 SourceLocToDebugLoc(R.getBegin()),
-                 SourceLocToDebugLoc(R.getEnd()));
-
   // C99 6.8.5.2: "The evaluation of the controlling expression takes place
   // after each execution of the loop body."
 
@@ -862,9 +862,19 @@
   // "do {} while (0)" is common in macros, avoid extra blocks.  Be sure
   // to correctly handle break/continue though.
   bool EmitBoolCondBranch = true;
-  if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
+  bool LoopMustProgress = false;
+  if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
     if (C->isZero())
       EmitBoolCondBranch = false;
+    else if (C->isOne())
+      FnIsMustProgress = false;
+  } else if (LanguageRequiresProgress())
+    LoopMustProgress = true;
+
+  const SourceRange &R = S.getSourceRange();
+  LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
+                 SourceLocToDebugLoc(R.getBegin()),
+                 SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
 
   // As long as the condition is true, iterate the loop.
   if (EmitBoolCondBranch) {
@@ -902,10 +912,18 @@
   llvm::BasicBlock *CondBlock = Continue.getBlock();
   EmitBlock(CondBlock);
 
+  bool LoopMustProgress = false;
+  Expr::EvalResult Result;
+  if (LanguageRequiresProgress() &&
+      (!S.getCond() || !S.getCond()->EvaluateAsInt(Result, getContext()))) {
+    LoopMustProgress = true;
+    FnIsMustProgress = false;
+  }
+
   const SourceRange &R = S.getSourceRange();
   LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
                  SourceLocToDebugLoc(R.getBegin()),
-                 SourceLocToDebugLoc(R.getEnd()));
+                 SourceLocToDebugLoc(R.getEnd()), LoopMustProgress);
 
   // If the for loop doesn't have an increment we can just use the
   // condition as the continue block.  Otherwise we'll need to create
@@ -939,6 +957,10 @@
     // C99 6.8.5p2/p4: The first substatement is executed if the expression
     // compares unequal to 0.  The condition must be a scalar type.
     llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+    if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
+      if (C->isOne())
+        FnIsMustProgress = false;
+
     Builder.CreateCondBr(
         BoolCondVal, ForBody, ExitBlock,
         createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())));
Index: clang/lib/CodeGen/CGLoopInfo.h
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.h
+++ clang/lib/CodeGen/CGLoopInfo.h
@@ -75,6 +75,9 @@
 
   /// Value for llvm.loop.pipeline.iicount metadata.
   unsigned PipelineInitiationInterval;
+
+  /// Value for whether the loop is required to make progress.
+  bool MustProgress;
 };
 
 /// Information used when generating a structured loop.
@@ -205,7 +208,7 @@
   void push(llvm::BasicBlock *Header, clang::ASTContext &Ctx,
             const clang::CodeGenOptions &CGOpts,
             llvm::ArrayRef<const Attr *> Attrs, const llvm::DebugLoc &StartLoc,
-            const llvm::DebugLoc &EndLoc);
+            const llvm::DebugLoc &EndLoc, bool MustProgress = false);
 
   /// End the current loop.
   void pop();
@@ -272,6 +275,9 @@
     StagedAttrs.PipelineInitiationInterval = C;
   }
 
+  /// Set no progress for the next loop pushed.
+  void setMustProgress(bool P) { StagedAttrs.MustProgress = P; }
+
 private:
   /// Returns true if there is LoopInfo on the stack.
   bool hasInfo() const { return !Active.empty(); }
Index: clang/lib/CodeGen/CGLoopInfo.cpp
===================================================================
--- clang/lib/CodeGen/CGLoopInfo.cpp
+++ clang/lib/CodeGen/CGLoopInfo.cpp
@@ -418,10 +418,14 @@
       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}));
   }
@@ -438,7 +442,7 @@
       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;
@@ -453,6 +457,7 @@
   DistributeEnable = LoopAttributes::Unspecified;
   PipelineDisabled = false;
   PipelineInitiationInterval = 0;
+  MustProgress = false;
 }
 
 LoopInfo::LoopInfo(BasicBlock *Header, const LoopAttributes &Attrs,
@@ -476,7 +481,7 @@
       Attrs.UnrollEnable == LoopAttributes::Unspecified &&
       Attrs.UnrollAndJamEnable == LoopAttributes::Unspecified &&
       Attrs.DistributeEnable == LoopAttributes::Unspecified && !StartLoc &&
-      !EndLoc)
+      !EndLoc && !Attrs.MustProgress)
     return;
 
   TempLoopID = MDNode::getTemporary(Header->getContext(), None);
@@ -577,8 +582,7 @@
                          const clang::CodeGenOptions &CGOpts,
                          ArrayRef<const clang::Attr *> Attrs,
                          const llvm::DebugLoc &StartLoc,
-                         const llvm::DebugLoc &EndLoc) {
-
+                         const llvm::DebugLoc &EndLoc, bool MustProgress) {
   // Identify loop hint attributes from Attrs.
   for (const auto *Attr : Attrs) {
     const LoopHintAttr *LH = dyn_cast<LoopHintAttr>(Attr);
@@ -755,6 +759,8 @@
     }
   }
 
+  setMustProgress(MustProgress);
+
   if (CGOpts.OptimizationLevel > 0)
     // Disable unrolling for the loop, if unrolling is disabled (via
     // -fno-unroll-loops) and no pragmas override the decision.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to