| // RUN: %clang_cc1 -std=c89 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s | |
| // RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s | |
| // RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s | |
| // | |
| // Check -ffinite-loops option in combination with various standard versions. | |
| // RUN: %clang_cc1 -std=c89 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s | |
| // RUN: %clang_cc1 -std=c99 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s | |
| // RUN: %clang_cc1 -std=c11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s | |
| // RUN: %clang_cc1 -std=c18 -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s | |
| // RUN: %clang_cc1 -std=c2x -ffinite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s | |
| // | |
| // Check -fno-finite-loops option in combination with various standard versions. | |
| // RUN: %clang_cc1 -std=c89 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c99 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c18 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| // RUN: %clang_cc1 -std=c2x -fno-finite-loops -triple=x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s | |
| int a = 0; | |
| int b = 0; | |
| // CHECK: datalayout | |
| // | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @f0( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label %for.cond | |
| // CHECK: for.cond: | |
| // C99-NOT: br {{.*}}!llvm.loop | |
| // C11-NOT: br {{.*}}!llvm.loop | |
| // FINITE-NOR: br {{.*}}!llvm.loop | |
| // | |
| void f0(void) { | |
| for (; ;) ; | |
| } | |
| // CHECK-NOT: mustprogress | |
| // 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: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11-NOT: br {{.*}}, !llvm.loop | |
| // FINITE-NOT: br {{.*}}, !llvm.loop | |
| // CHECK: for.end: | |
| // CHECK-NEXT: ret void | |
| // | |
| void f1(void) { | |
| for (; 1;) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @f2( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label %for.cond | |
| // CHECK: for.cond: | |
| // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @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: | |
| // C99-NOT: br {{.*}} !llvm.loop | |
| // C11: br label %for.cond, !llvm.loop [[LOOP1:!.*]] | |
| // FINITE: br label %for.cond, !llvm.loop [[LOOP1:!.*]] | |
| // CHECK: for.end: | |
| // CHECK-NEXT: ret void | |
| // | |
| void f2(void) { | |
| for (; a == b;) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // 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: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11-NOT: br {{.*}}, !llvm.loop | |
| // FINITE-NOT: br {{.*}}, !llvm.loop | |
| // CHECK: for.end: | |
| // CHECK-NEXT: br label %for.cond1 | |
| // CHECK: for.cond1: | |
| // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @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: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] | |
| // FINITE: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] | |
| // CHECK: for.end3: | |
| // CHECK-NEXT: ret void | |
| // | |
| void F(void) { | |
| for (; 1;) { | |
| } | |
| for (; a == b;) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @w1( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label %while.body | |
| // CHECK: while.body: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11-NOT: br {{.*}}, !llvm.loop | |
| // FINITE-NOT: br {{.*}}, !llvm.loop | |
| // | |
| void w1(void) { | |
| while (1) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @w2( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label %while.cond | |
| // CHECK: while.cond: | |
| // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @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: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11: br label %while.cond, !llvm.loop [[LOOP3:!.*]] | |
| // FINITE: br label %while.cond, !llvm.loop [[LOOP3:!.*]] | |
| // CHECK: while.end: | |
| // CHECK-NEXT: ret void | |
| // | |
| void w2(void) { | |
| while (a == b) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @W( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label [[WHILE_COND:%.*]] | |
| // CHECK: while.cond: | |
| // CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @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: | |
| // C99-NOT: br {{.*}} !llvm.loop | |
| // C11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] | |
| // FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]] | |
| // CHECK: while.end: | |
| // CHECK-NEXT: br label %while.body2 | |
| // CHECK: while.body2: | |
| // C99-NOT: br {{.*}} !llvm.loop | |
| // C11-NOT: br {{.*}} !llvm.loop | |
| // FINITE-NOT: br {{.*}} !llvm.loop | |
| // | |
| void W(void) { | |
| while (a == b) { | |
| } | |
| while (1) { | |
| } | |
| } | |
| // CHECK-NOT: mustprogress | |
| // CHECK-LABEL: @d1( | |
| // CHECK-NEXT: entry: | |
| // CHECK-NEXT: br label %do.body | |
| // CHECK: do.body: | |
| // CHECK-NEXT: br label %do.cond | |
| // CHECK: do.cond: | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11-NOT: br {{.*}}, !llvm.loop | |
| // FINITE-NOT: br {{.*}}, !llvm.loop | |
| // CHECK: do.end: | |
| // CHECK-NEXT: ret void | |
| // | |
| void d1(void) { | |
| do { | |
| } while (1); | |
| } | |
| // CHECK-NOT: mustprogress | |
| // 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, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 4 | |
| // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] | |
| // FINITE: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP5:!.*]] | |
| // CHECK: do.end: | |
| // CHECK-NEXT: ret void | |
| // | |
| void d2(void) { | |
| do { | |
| } while (a == b); | |
| } | |
| // CHECK-NOT: mustprogress | |
| // 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-NOT: br label {{.*}}, !llvm.loop | |
| // 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, ptr @a, align 4 | |
| // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @b, align 4 | |
| // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] | |
| // C99-NOT: br {{.*}}, !llvm.loop | |
| // C11: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] | |
| // FINITE: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP6:!.*]] | |
| // CHECK: do.end3: | |
| // CHECK-NEXT: ret void | |
| // | |
| void D(void) { | |
| do { | |
| } while (1); | |
| do { | |
| } while (a == b); | |
| } | |
| // C11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} | |
| // C11: [[MP]] = !{!"llvm.loop.mustprogress"} | |
| // C11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} | |
| // C11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} | |
| // C11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} | |
| // C11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} | |
| // C11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} |