atmnpatel updated this revision to Diff 294570.
atmnpatel added a comment.
All language standards (minus gnu extensions) are now tested.
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/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/CodeGenCXX/cxx11-trivial-initializer-struct.cpp
clang/test/CodeGenCXX/fno-unroll-loops-metadata.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
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/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.
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/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,186 @@
+// 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 mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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 uwtable mustprogress
+// 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-1.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/attr-mustprogress-1.c
@@ -0,0 +1,193 @@
+// 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 [[LOOP6:!.*]]
+// 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:%.*]], !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);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[GEN3:!.*]]}
+// CHECK: [[GEN3]] = !{!"llvm.loop.mustprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[GEN3]]}
+// CHECK: [[LOOP6]] = distinct !{[[LOOP6]], [[GEN3]]}
+// CHECK: [[LOOP7]] = distinct !{[[LOOP7]], [[GEN3]]}
+// CHECK: [[LOOP8]] = distinct !{[[LOOP8]], [[GEN3]]}
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.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -1158,6 +1158,11 @@
void CodeGenFunction::EmitFunctionBody(const Stmt *Body) {
incrementProfileCounter(Body);
+
+ if (getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
+ getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20)
+ CurFn->addFnAttr(llvm::Attribute::MustProgress);
+
if (const CompoundStmt *S = dyn_cast<CompoundStmt>(Body))
EmitCompoundStmtWithoutScope(*S);
else
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -763,11 +763,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");
@@ -795,9 +790,17 @@
// 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))
+ bool MustProgress = false;
+ if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
if (C->isOne())
EmitBoolCondBranch = false;
+ } else if (getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x)
+ MustProgress = true;
+
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
+ WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()), MustProgress);
// As long as the condition is true, go to the loop body.
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
@@ -865,11 +868,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."
@@ -883,9 +881,17 @@
// "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 MustProgress = false;
+ if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
if (C->isZero())
EmitBoolCondBranch = false;
+ } else if (getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x)
+ MustProgress = true;
+
+ const SourceRange &R = S.getSourceRange();
+ LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()), MustProgress);
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch) {
@@ -923,10 +929,16 @@
llvm::BasicBlock *CondBlock = Continue.getBlock();
EmitBlock(CondBlock);
+ bool MustProgress = false;
+ Expr::EvalResult Result;
+ if ((getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x) &&
+ (!S.getCond() || !S.getCond()->EvaluateAsInt(Result, getContext())))
+ MustProgress = true;
+
const SourceRange &R = S.getSourceRange();
LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs,
SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()));
+ SourceLocToDebugLoc(R.getEnd()), MustProgress);
// 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
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits