This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG51bf4c0e6d4c: [clang] Add -ffinite-loops & 
-fno-finite-loops options. (authored by fhahn).

Changed prior to commit:
  https://reviews.llvm.org/D96419?vs=323373&id=323418#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96419/new/

https://reviews.llvm.org/D96419

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/attr-mustprogress.c
  clang/test/CodeGenCXX/attr-mustprogress.cpp

Index: clang/test/CodeGenCXX/attr-mustprogress.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-mustprogress.cpp
+++ 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 @@
 
 // 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 @@
 
 // CXX98-NOT: mustprogress
 // CXX11:     mustprogress
+// FINITE-NOT: mustprogress
 // CHECK-LABEL: @_Z2f2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label %for.cond
@@ -52,6 +59,7 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
 }
 
 // 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 @@
 // 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 @@
 
 // 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 @@
 
 // CXX98-NOT: mustprogress
 // CXX11:     mustprogress
+// FINITE-NOT: mustprogress
 // CHECK-LABEL: @_Z2w2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label %while.cond
@@ -146,7 +157,8 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
 
 // 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 @@
 
 // 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 @@
 
 // CXX98-NOT: mustprogress
 // CXX11:     mustprogress
+// FINITE-NOT:  mustprogress
 // CHECK-LABEL: @_Z2d2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label %do.body
@@ -228,7 +242,8 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
 
 // 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 @@
 // 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 @@
   while (1);
 }
 
-
 // CXX11: [[LOOP1]] = distinct !{[[LOOP1]], [[MP:!.*]]}
 // CXX11: [[MP]] = !{!"llvm.loop.mustprogress"}
 // CXX11: [[LOOP2]] = distinct !{[[LOOP2]], [[MP]]}
@@ -311,3 +327,4 @@
 // CXX11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]}
 // CXX11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]}
 // CXX11: [[LOOP7]] = distinct !{[[LOOP7]], [[MP]]}
+// CXX11: [[LOOP8]] = distinct !{[[LOOP8]], [[MP]]}
Index: clang/test/CodeGen/attr-mustprogress.c
===================================================================
--- clang/test/CodeGen/attr-mustprogress.c
+++ 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // C11: [[LOOP3]] = distinct !{[[LOOP3]], [[MP]]}
 // C11: [[LOOP4]] = distinct !{[[LOOP4]], [[MP]]}
 // C11: [[LOOP5]] = distinct !{[[LOOP5]], [[MP]]}
+// C11: [[LOOP6]] = distinct !{[[LOOP6]], [[MP]]}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1633,7 +1633,6 @@
   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 @@
 
   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;
 }
 
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -5640,6 +5640,9 @@
     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);
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -507,12 +507,26 @@
 
   /// 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;
   }
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2469,6 +2469,11 @@
 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>,
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -140,6 +140,12 @@
     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;
 
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -266,6 +266,9 @@
 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)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to