llvm-project/clang/test/CodeGen/attr-mustprogress.c
Florian Hahn 51bf4c0e6d [clang] Add -ffinite-loops & -fno-finite-loops options.
This patch adds 2 new options to control when Clang adds `mustprogress`:

  1. -ffinite-loops: assume all loops are finite; mustprogress is added
     to all loops, regardless of the selected language standard.
  2. -fno-finite-loops: assume no loop is finite; mustprogress is not
     added to any loop or function. We could add mustprogress to
     functions without loops, but we would have to detect that in Clang,
     which is probably not worth it.

Reviewed By: jdoerfert

Differential Revision: https://reviews.llvm.org/D96419
2021-02-12 19:25:49 +00:00

222 lines
6.8 KiB
C

// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C99 %s
// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=C11 %s
//
// RUN: %clang_cc1 -std=c11 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
// RUN: %clang_cc1 -std=c11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -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:
// CHECK-NOT: br {{.*}}!llvm.loop
//
void f0() {
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:
// CHECK-NOT: br {{.*}}, !llvm.loop
// CHECK: for.end:
// CHECK-NEXT: ret void
//
void f1() {
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, 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:
// 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() {
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:
// CHECK-NOT: br {{.*}}, !llvm.loop
// 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:
// 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() {
for (; 1;) {
}
for (; a == b;) {
}
}
// CHECK-NOT: mustprogress
// CHECK-LABEL: @w1(
// CHECK-NEXT: entry:
// CHECK-NEXT: br label %while.body
// CHECK: while.body:
// CHECK-NOT: br {{.*}}, !llvm.loop
//
void w1() {
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, 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:
// 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() {
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, 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:
// C99-NOT: br {{.*}} !llvm.loop
// C11: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
// FINITE: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
// CHECK: while.end:
// CHECK-NEXT: br label %while.body2
// CHECK: while.body2:
// CHECK-NOT: br {{.*}} !llvm.loop
//
void W() {
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:
// CHECK-NOT: br {{.*}}, !llvm.loop
// CHECK: do.end:
// CHECK-NEXT: ret void
//
void d1() {
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, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @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() {
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, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @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() {
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]]}