atmnpatel created this revision.
atmnpatel added reviewers: fhahn, jdoerfert, xbolva00.
atmnpatel requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Currently, clang does not emit the `mustprogress` loop or function
attribute for loops with non-zero constant conditionals. Based on recent
discussion in D86844 <https://reviews.llvm.org/D86844> and D86841 
<https://reviews.llvm.org/D86841>, it seems that it would be preferable to
emit these attributes to adhere more tightly to the C++ standard as gcc
does.

I will be pushing a patch to add `-ffinite-loops` and `-fno-finite-loops` to
clang to provide more control over this momentarily.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94366

Files:
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/attr-mustprogress-1.cpp

Index: clang/test/CodeGen/attr-mustprogress-1.cpp
===================================================================
--- clang/test/CodeGen/attr-mustprogress-1.cpp
+++ clang/test/CodeGen/attr-mustprogress-1.cpp
@@ -7,24 +7,25 @@
 int a = 0;
 int b = 0;
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z2f0v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[FOR_COND:%.*]]
 // CHECK:       for.cond:
-// CHECK-NOT:    br label [[FOR_COND]], !llvm.loop !{{.*}}
+// CHECK-NEXT:    br label [[FOR_COND]], [[LOOP2:!llvm.loop !.*]]
+//
 void f0() {
   for (; ;) ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone 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-NEXT:    br label [[FOR_COND]]
+// CHECK-NEXT:    br label [[FOR_COND]], [[LOOP4:!llvm.loop !.*]]
 // CHECK:       for.end:
 // CHECK-NEXT:    ret void
 //
@@ -43,7 +44,7 @@
 // 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-NEXT:    br label [[FOR_COND]], [[LOOP5:!llvm.loop !.*]]
 // CHECK:       for.end:
 // CHECK-NEXT:    ret void
 //
@@ -52,14 +53,14 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone 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-NEXT:    br label [[FOR_COND]]
+// CHECK-NEXT:    br label [[FOR_COND]], [[LOOP6:!llvm.loop !.*]]
 // CHECK:       for.end:
 // CHECK-NEXT:    br label [[FOR_COND1:%.*]]
 // CHECK:       for.cond1:
@@ -68,7 +69,7 @@
 // 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-NEXT:    br label [[FOR_COND1]], [[LOOP7:!llvm.loop !.*]]
 // CHECK:       for.end3:
 // CHECK-NEXT:    ret void
 //
@@ -79,7 +80,7 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z2F2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[FOR_COND:%.*]]
@@ -89,13 +90,13 @@
 // 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-NEXT:    br label [[FOR_COND]], [[LOOP8:!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-NEXT:    br label [[FOR_COND1]], [[LOOP9:!llvm.loop !.*]]
 // CHECK:       for.end3:
 // CHECK-NEXT:    ret void
 //
@@ -106,7 +107,7 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z2w1v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
@@ -128,7 +129,7 @@
 // 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-NEXT:    br label [[WHILE_COND]], [[LOOP10:!llvm.loop !.*]]
 // CHECK:       while.end:
 // CHECK-NEXT:    ret void
 //
@@ -137,7 +138,7 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z1Wv(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[WHILE_COND:%.*]]
@@ -147,7 +148,7 @@
 // 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-NEXT:    br label [[WHILE_COND]], [[LOOP11:!llvm.loop !.*]]
 // CHECK:       while.end:
 // CHECK-NEXT:    br label [[WHILE_BODY2:%.*]]
 // CHECK:       while.body2:
@@ -160,7 +161,7 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z2W2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[WHILE_BODY:%.*]]
@@ -174,14 +175,14 @@
     ;
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone 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-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP12:!llvm.loop !.*]]
 // CHECK:       do.end:
 // CHECK-NEXT:    ret void
 //
@@ -201,7 +202,7 @@
 // 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-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP13:!llvm.loop !.*]]
 // CHECK:       do.end:
 // CHECK-NEXT:    ret void
 //
@@ -211,14 +212,14 @@
   while (a == b);
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone 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-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]]
+// CHECK-NEXT:    br i1 true, label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP14:!llvm.loop !.*]]
 // CHECK:       do.end:
 // CHECK-NEXT:    br label [[DO_BODY1:%.*]]
 // CHECK:       do.body1:
@@ -227,7 +228,7 @@
 // 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-NEXT:    br i1 [[CMP]], label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP15:!llvm.loop !.*]]
 // CHECK:       do.end3:
 // CHECK-NEXT:    ret void
 //
@@ -240,7 +241,7 @@
   while (a == b);
 }
 
-// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK: Function Attrs: noinline nounwind optnone mustprogress
 // CHECK-LABEL: @_Z2D2v(
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    br label [[DO_BODY:%.*]]
@@ -250,13 +251,13 @@
 // 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-NEXT:    br i1 [[CMP]], label [[DO_BODY]], label [[DO_END:%.*]], [[LOOP16:!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-NEXT:    br i1 true, label [[DO_BODY1]], label [[DO_END3:%.*]], [[LOOP17:!llvm.loop !.*]]
 // CHECK:       do.end3:
 // CHECK-NEXT:    ret void
 //
Index: clang/lib/CodeGen/CGStmt.cpp
===================================================================
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -796,7 +796,8 @@
   if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
     if (C->isOne()) {
       EmitBoolCondBranch = false;
-      FnIsMustProgress = false;
+      if (CWithProgress())
+        FnIsMustProgress = false;
     }
   } else if (LanguageRequiresProgress())
     LoopMustProgress = true;
@@ -897,8 +898,10 @@
   if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) {
     if (C->isZero())
       EmitBoolCondBranch = false;
-    else if (C->isOne())
+    else if (C->isOne() && CWithProgress())
       FnIsMustProgress = false;
+    else if (CPlusPlusWithProgress())
+      LoopMustProgress = true;
   } else if (LanguageRequiresProgress())
     LoopMustProgress = true;
 
@@ -945,12 +948,13 @@
 
   bool LoopMustProgress = false;
   Expr::EvalResult Result;
+
   if (LanguageRequiresProgress()) {
-    if (!S.getCond()) {
+    if (!S.getCond() && CWithProgress())
       FnIsMustProgress = false;
-    } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) {
+    else if (CPlusPlusWithProgress() ||
+             !S.getCond()->EvaluateAsInt(Result, getContext()))
       LoopMustProgress = true;
-    }
   }
 
   const SourceRange &R = S.getSourceRange();
@@ -994,7 +998,7 @@
         S.getCond(), getProfileCount(S.getBody()), S.getBody());
 
     if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
-      if (C->isOne())
+      if (C->isOne() && CWithProgress())
         FnIsMustProgress = false;
 
     Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to