From 51bf4c0e6d4cbc6dfa57857fc78003413cbeb17f Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Fri, 12 Feb 2021 17:45:18 +0000 Subject: [PATCH] [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 --- clang/include/clang/Basic/CodeGenOptions.def | 3 ++ clang/include/clang/Basic/CodeGenOptions.h | 6 +++ clang/include/clang/Driver/Options.td | 5 ++ clang/lib/CodeGen/CodeGenFunction.h | 14 +++++ clang/lib/Driver/ToolChains/Clang.cpp | 3 ++ clang/lib/Frontend/CompilerInvocation.cpp | 6 ++- clang/test/CodeGen/attr-mustprogress.c | 27 +++++++--- clang/test/CodeGenCXX/attr-mustprogress.cpp | 77 +++++++++++++++++----------- 8 files changed, 102 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 5c8af65..9d53b5b 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -266,6 +266,9 @@ CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. 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) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 3897952..efcb6b1 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -140,6 +140,12 @@ public: 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; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 5228396..d22956b 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2469,6 +2469,11 @@ def fno_unroll_loops : Flag<["-"], "fno-unroll-loops">, Group, defm reroll_loops : BoolFOption<"reroll-loops", CodeGenOpts<"RerollLoops">, DefaultFalse, PosFlag, NegFlag>; +def ffinite_loops: Flag<["-"], "ffinite-loops">, Group, + HelpText<"Assume all loops are finite.">, Flags<[CC1Option]>; +def fno_finite_loops: Flag<["-"], "fno-finite-loops">, Group, + HelpText<"Do not assume that any loop is finite.">, Flags<[CC1Option]>; + def ftrigraphs : Flag<["-"], "ftrigraphs">, Group, HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group, diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index dd77d70..ff98751 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -507,12 +507,26 @@ public: /// True if the C++ Standard Requires Progress. bool CPlusPlusWithProgress() { + if (CGM.getCodeGenOpts().getFiniteLoops() == + CodeGenOptions::FiniteLoopsKind::Never) + return false; + 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; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index c2b195a..819f10e 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5640,6 +5640,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 53f90cf..b2ee11a 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1633,7 +1633,6 @@ bool CompilerInvocation::ParseCodeGenArgsImpl(CodeGenOptions &Opts, Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, (Opts.OptimizationLevel > 1)); - Opts.BinutilsVersion = std::string(Args.getLastArgValue(OPT_fbinutils_version_EQ)); @@ -1921,6 +1920,11 @@ bool CompilerInvocation::ParseCodeGenArgsImpl(CodeGenOptions &Opts, 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 && Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/CodeGen/attr-mustprogress.c b/clang/test/CodeGen/attr-mustprogress.c index d1b262d..1f83cd4 100644 --- a/clang/test/CodeGen/attr-mustprogress.c +++ b/clang/test/CodeGen/attr-mustprogress.c @@ -2,6 +2,9 @@ // 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; @@ -13,7 +16,7 @@ int b = 0; // CHECK-NEXT: entry: // CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CHECK-NOT: br {{.*}}!llvm.loop +// CHECK-NOT: br {{.*}}!llvm.loop // void f0() { for (; ;) ; @@ -45,8 +48,9 @@ void f1() { // 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:!.*]] +// 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 // @@ -73,6 +77,7 @@ void f2() { // 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 // @@ -88,7 +93,8 @@ void F() { // CHECK-NEXT: entry: // CHECK-NEXT: br label %while.body // CHECK: while.body: -// CHECK-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop +// void w1() { while (1) { } @@ -104,8 +110,9 @@ void w1() { // CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], [[TMP1]] // CHECK-NEXT: br i1 [[CMP]], label %while.body, label %while.end // CHECK: while.body: -// C11: br label %while.cond, [[LOOP5:!llvm.loop !.*]] // 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 // @@ -125,7 +132,8 @@ void w2() { // 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:!.*]] +// 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: @@ -165,7 +173,8 @@ void d1() { // 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 [[LOOP4:!.*]] +// 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 // @@ -191,7 +200,8 @@ void d2() { // 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 [[LOOP5:!.*]] +// 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 // @@ -208,3 +218,4 @@ void D() { // C11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]} // C11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]} // C11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} +// C11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} diff --git a/clang/test/CodeGenCXX/attr-mustprogress.cpp b/clang/test/CodeGenCXX/attr-mustprogress.cpp index df643ac..93e366b 100644 --- a/clang/test/CodeGenCXX/attr-mustprogress.cpp +++ b/clang/test/CodeGenCXX/attr-mustprogress.cpp @@ -4,6 +4,12 @@ // 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; @@ -11,26 +17,26 @@ int b = 0; // CXX98-NOT: mustprogress // CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2f0v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %for.cond // CHECK: for.cond: -// CXX98-NOT: br {{.*}} llvm.loop -// CXX11-NOT: br {{.*}} llvm.loop +// 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: // CHECK-NEXT: ret void // @@ -41,6 +47,7 @@ void f1() { // CXX98-NOT: mustprogress // CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2f2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %for.cond @@ -52,6 +59,7 @@ void f1() { // 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 // @@ -62,14 +70,14 @@ void f2() { // 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end: // CHECK-NEXT: br label %for.cond1 // CHECK: for.cond1: @@ -78,8 +86,9 @@ void f2() { // 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: br label %for.cond1, !llvm.loop [[LOOP2:!.*]] +// 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 // @@ -91,7 +100,8 @@ void F() { } // CXX98-NOT: mustprogress -// CXX11_NOT: mustprogress +// CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2F2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %for.cond @@ -102,14 +112,14 @@ void F() { // 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 +// 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: for.end3: // CHECK-NEXT: ret void // @@ -122,12 +132,12 @@ void F2() { // CXX98-NOT: mustprogress // CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2w1v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %while.body // CHECK: while.body: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // void w1() { while (1) @@ -136,6 +146,7 @@ void w1() { // CXX98-NOT: mustprogress // CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2w2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %while.cond @@ -146,7 +157,8 @@ void w1() { // 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 [[LOOP3:!.*]] +// 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 // @@ -157,6 +169,7 @@ void w2() { // CXX98-NOT: mustprogress // CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z1Wv( // CHECK-NEXT: entry: // CHECK-NEXT: br label %while.cond @@ -167,12 +180,12 @@ void w2() { // 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:!.*]] +// 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // void W() { while (a == b) @@ -183,12 +196,12 @@ void W() { // CXX98-NOT: mustprogress // CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2W2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %while.body // CHECK: while.body: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // void W2() { while (1) @@ -199,14 +212,14 @@ void W2() { // 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end: // CHECK-NEXT: ret void // @@ -218,6 +231,7 @@ void d1() { // CXX98-NOT: mustprogress // CXX11: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2d2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %do.body @@ -228,7 +242,8 @@ void d1() { // 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 [[LOOP5:!.*]] +// 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 // @@ -240,14 +255,14 @@ void d2() { // 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end: // CHECK-NEXT: br label %do.body1 // CHECK: do.body1: @@ -257,7 +272,8 @@ void d2() { // 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 [[LOOP6:!.*]] +// 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 // @@ -272,6 +288,7 @@ void D() { // CXX98-NOT: mustprogress // CXX11-NOT: mustprogress +// FINITE-NOT: mustprogress // CHECK-LABEL: @_Z2D2v( // CHECK-NEXT: entry: // CHECK-NEXT: br label %do.body @@ -282,14 +299,14 @@ void D() { // 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 [[LOOP7:!.*]] +// 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: -// CXX98-NOT: br {{.*}}, !llvm.loop -// CXX11-NOT: br {{.*}}, !llvm.loop +// CHECK-NOT: br {{.*}}, !llvm.loop // CHECK: do.end3: // CHECK-NEXT: ret void // @@ -302,7 +319,6 @@ void D2() { while (1); } - // CXX11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]} // CXX11: [[MP]] = !{!"llvm.loop.mustprogress"} // CXX11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]} @@ -311,3 +327,4 @@ void D2() { // CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]} // CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]} // CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]} +// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]} -- 2.7.4