CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate.
+/// Treat loops as finite: language, always, never.
+ENUM_CODEGENOPT(FiniteLoops, FiniteLoopsKind, 2, FiniteLoopsKind::Language)
+
/// Attempt to use register sized accesses to bit-fields in structures, when
/// possible.
CODEGENOPT(UseRegisterSizedBitfieldAccess , 1, 0)
All, // Keep all frame pointers.
};
+ enum FiniteLoopsKind {
+ Language, // Not specified, use language standard.
+ Always, // All loops are assumed to be finite.
+ Never, // No loop is assumed to be finite.
+ };
+
/// The code model to use (-mcmodel).
std::string CodeModel;
defm reroll_loops : BoolFOption<"reroll-loops",
CodeGenOpts<"RerollLoops">, DefaultFalse,
PosFlag<SetTrue, [CC1Option], "Turn on loop reroller">, NegFlag<SetFalse>>;
+def ffinite_loops: Flag<["-"], "ffinite-loops">, Group<f_Group>,
+ HelpText<"Assume all loops are finite.">, Flags<[CC1Option]>;
+def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group<f_Group>,
+ HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>;
+
def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
HelpText<"Process trigraph sequences">, Flags<[CC1Option]>;
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
/// True if the C++ Standard Requires Progress.
bool CPlusPlusWithProgress() {
+ if (CGM.getCodeGenOpts().getFiniteLoops() ==
+ CodeGenOptions::FiniteLoopsKind::Never)
+ return false;
+
return getLangOpts().CPlusPlus11 || getLangOpts().CPlusPlus14 ||
getLangOpts().CPlusPlus17 || getLangOpts().CPlusPlus20;
}
/// True if the C Standard Requires Progress.
bool CWithProgress() {
+ if (CGM.getCodeGenOpts().getFiniteLoops() ==
+ CodeGenOptions::FiniteLoopsKind::Always)
+ return true;
+ if (CGM.getCodeGenOpts().getFiniteLoops() ==
+ CodeGenOptions::FiniteLoopsKind::Never)
+ return false;
+
return getLangOpts().C11 || getLangOpts().C17 || getLangOpts().C2x;
}
if (A->getOption().matches(options::OPT_freroll_loops))
CmdArgs.push_back("-freroll-loops");
+ Args.AddLastArg(CmdArgs, options::OPT_ffinite_loops,
+ options::OPT_fno_finite_loops);
+
Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings);
Args.AddLastArg(CmdArgs, options::OPT_funroll_loops,
options::OPT_fno_unroll_loops);
Opts.UnrollLoops =
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
(Opts.OptimizationLevel > 1));
-
Opts.BinutilsVersion =
std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ));
Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
+ if (Args.hasArg(options::OPT_ffinite_loops))
+ Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
+ else if (Args.hasArg(options::OPT_fno_finite_loops))
+ Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Never;
return Success;
}
+++ /dev/null
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
-// RUN: %clang_cc1 -std=c89 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c99 -triple=x86_64-unknown-linux-gnu -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-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
-// 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
-// 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
-// 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
-// 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
-// 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
-// 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
-// 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
-// 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);
-}
+++ /dev/null
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
-// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-
-int a = 0;
-int b = 0;
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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
-// 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]]
-// CHECK: for.end:
-// CHECK-NEXT: ret void
-//
-void f2() {
- for (; a == b;) {
- }
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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]]
-// CHECK: for.end3:
-// CHECK-NEXT: ret void
-//
-void F() {
- for (; 1;) {
- }
- for (; a == b;) {
- }
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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
-// 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]]
-// CHECK: while.end:
-// CHECK-NEXT: ret void
-//
-void w2() {
- while (a == b) {
- }
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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]]
-// 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
-// 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
-// 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:%.*]]
-// CHECK: do.end:
-// CHECK-NEXT: ret void
-//
-void d2() {
- do {
- } while (a == b);
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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:%.*]]
-// CHECK: do.end3:
-// CHECK-NEXT: ret void
-//
-void D() {
- do {
- } while (1);
- do {
- } while (a == b);
-}
+++ /dev/null
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
-// RUN: %clang_cc1 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c18 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c2x -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-
-int a = 0;
-int b = 0;
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @f0(
-// CHECK-NEXT: entry:
-// CHECK-NEXT: br label [[FOR_COND:%.*]]
-// CHECK: for.cond:
-// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}}
-//
-void f0() {
- for (; ;) ;
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @f1(
-// CHECK-NEXT: entry:
-// 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
-// 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]], [[LOOP2:!llvm.loop !.*]]
-// CHECK: for.end:
-// CHECK-NEXT: 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-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]], [[LOOP4:!llvm.loop !.*]]
-// CHECK: for.end3:
-// CHECK-NEXT: 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-NEXT: 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-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]], [[LOOP5:!llvm.loop !.*]]
-// CHECK: while.end:
-// CHECK-NEXT: 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-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]], [[LOOP6:!llvm.loop !.*]]
-// 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
-// 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
-// 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:%.*]], [[LOOP7:!llvm.loop !.*]]
-// CHECK: do.end:
-// CHECK-NEXT: 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-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:%.*]], [[LOOP8:!llvm.loop !.*]]
-// CHECK: do.end3:
-// CHECK-NEXT: ret void
-//
-void D() {
- do {
- } while (1);
- do {
- } while (a == b);
-}
+++ /dev/null
-// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
-// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s
-
-int a = 0;
-int b = 0;
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @_Z2f0v(
-// CHECK-NEXT: entry:
-// CHECK-NEXT: br label [[FOR_COND:%.*]]
-// CHECK: for.cond:
-// CHECK-NOT: br label [[FOR_COND]], !llvm.loop !{{.*}}
-void f0() {
- for (; ;) ;
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// CHECK-LABEL: @_Z2f1v(
-// CHECK-NEXT: entry:
-// 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 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]], [[LOOP2:!llvm.loop !.*]]
-// CHECK: for.end:
-// CHECK-NEXT: ret void
-//
-void f2() {
- for (; a == b;)
- ;
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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]], [[LOOP4:!llvm.loop !.*]]
-// CHECK: for.end3:
-// CHECK-NEXT: ret void
-//
-void F() {
- for (; 1;)
- ;
- for (; a == b;)
- ;
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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]], [[LOOP5:!llvm.loop !.*]]
-// 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
-// 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 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]], [[LOOP6:!llvm.loop !.*]]
-// CHECK: while.end:
-// CHECK-NEXT: ret void
-//
-void w2() {
- while (a == b)
- ;
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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]], [[LOOP7:!llvm.loop !.*]]
-// 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
-// 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
-// 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 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:%.*]], [[LOOP8:!llvm.loop !.*]]
-// CHECK: do.end:
-// CHECK-NEXT: ret void
-//
-void d2() {
- do
- ;
- while (a == b);
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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:%.*]], [[LOOP9:!llvm.loop !.*]]
-// CHECK: do.end3:
-// CHECK-NEXT: ret void
-//
-void D() {
- do
- ;
- while (1);
- do
- ;
- while (a == b);
-}
-
-// CHECK: Function Attrs: noinline nounwind optnone
-// 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:%.*]], [[LOOP10:!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: 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);
-}
-
--- /dev/null
+// 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]]}
--- /dev/null
+// RUN: %clang_cc1 -std=c++98 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
+// RUN: %clang_cc1 -std=c++11 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
+// RUN: %clang_cc1 -std=c++14 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
+// RUN: %clang_cc1 -std=c++17 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
+// RUN: %clang_cc1 -std=c++20 -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX11 %s
+
+// Make sure -ffinite-loops overrides -std=c++98 for loops.
+// RUN: %clang_cc1 -std=c++98 -ffinite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=FINITE %s
+
+// Make sure -fno-finite-loops overrides -std=c++11
+// RUN: %clang_cc1 -std=c++11 -fno-finite-loops -triple=x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck --check-prefix=CHECK --check-prefix=CXX98 %s
+
+int a = 0;
+int b = 0;
+
+// CHECK: datalayout
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// CHECK-LABEL: @_Z2f0v(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: br label %for.cond
+// CHECK: for.cond:
+// CHECK-NOT: br {{.*}} llvm.loop
+void f0() {
+ for (; ;) ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// 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-NOT: br {{.*}}, !llvm.loop
+// CHECK: for.end:
+// CHECK-NEXT: ret void
+//
+void f1() {
+ for (; 1;)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: 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:
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP1:!.*]]
+// CHECK: for.end:
+// CHECK-NEXT: ret void
+//
+void f2() {
+ for (; a == b;)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// 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-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:
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]]
+// FINITE-NEXT: br label %for.cond1, !llvm.loop [[LOOP2:!.*]]
+// CHECK: for.end3:
+// CHECK-NEXT: ret void
+//
+void F() {
+ for (; 1;)
+ ;
+ for (; a == b;)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: 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:
+// CXX98_NOT: br {{.*}} !llvm.loop
+// CXX11-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
+// FINITE-NEXT: br label %for.cond, !llvm.loop [[LOOP3:!.*]]
+// 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-NOT: br {{.*}}, !llvm.loop
+// CHECK: for.end3:
+// CHECK-NEXT: ret void
+//
+void F2() {
+ for (; a == b;)
+ ;
+ for (; 1;)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// CHECK-LABEL: @_Z2w1v(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: br label %while.body
+// CHECK: while.body:
+// CHECK-NOT: br {{.*}}, !llvm.loop
+//
+void w1() {
+ while (1)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: 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:
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
+// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP4:!.*]]
+// CHECK: while.end:
+// CHECK-NEXT: ret void
+//
+void w2() {
+ while (a == b)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// 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:
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]]
+// FINITE-NEXT: br label %while.cond, !llvm.loop [[LOOP5:!.*]]
+// CHECK: while.end:
+// CHECK-NEXT: br label %while.body2
+// CHECK: while.body2:
+// CHECK-NOT: br {{.*}}, !llvm.loop
+//
+void W() {
+ while (a == b)
+ ;
+ while (1)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// CHECK-LABEL: @_Z2W2v(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: br label %while.body
+// CHECK: while.body:
+// CHECK-NOT: br {{.*}}, !llvm.loop
+//
+void W2() {
+ while (1)
+ ;
+ while (a == b)
+ ;
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// 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-NOT: br {{.*}}, !llvm.loop
+// CHECK: do.end:
+// CHECK-NEXT: ret void
+//
+void d1() {
+ do
+ ;
+ while (1);
+}
+
+// CXX98-NOT: mustprogress
+// CXX11: mustprogress
+// FINITE-NOT: 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]]
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP6:!.*]]
+// CHECK: do.end:
+// CHECK-NEXT: ret void
+//
+void d2() {
+ do
+ ;
+ while (a == b);
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: mustprogress
+// 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-NOT: br {{.*}}, !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]]
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body1, label %do.end3, !llvm.loop [[LOOP7:!.*]]
+// CHECK: do.end3:
+// CHECK-NEXT: ret void
+//
+void D() {
+ do
+ ;
+ while (1);
+ do
+ ;
+ while (a == b);
+}
+
+// CXX98-NOT: mustprogress
+// CXX11-NOT: mustprogress
+// FINITE-NOT: 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]]
+// CXX98-NOT: br {{.*}}, !llvm.loop
+// CXX11-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]]
+// FINITE-NEXT: br i1 [[CMP]], label %do.body, label %do.end, !llvm.loop [[LOOP8:!.*]]
+// CHECK: do.end:
+// CHECK-NEXT: br label %do.body1
+// CHECK: do.body1:
+// CHECK-NEXT: br label %do.cond2
+// CHECK: do.cond2:
+// CHECK-NOT: br {{.*}}, !llvm.loop
+// CHECK: do.end3:
+// CHECK-NEXT: ret void
+//
+void D2() {
+ do
+ ;
+ while (a == b);
+ do
+ ;
+ while (1);
+}
+
+// CXX11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]}
+// CXX11: [[MP]] = !{!"llvm.loop.mustprogress"}
+// CXX11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]}
+// CXX11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]}
+// CXX11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]}
+// CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]}
+// CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]}
+// CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]}
+// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]}