[PATCH] D86841: [clang] Adds noprogress attribute deduction for infinite loops

2020-08-29 Thread Atmn Patel via Phabricator via cfe-commits
atmnpatel updated this revision to Diff 288818.
atmnpatel added a comment.

Fixed comment in C++ test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86841

Files:
  clang/lib/CodeGen/CGLoopInfo.cpp
  clang/lib/CodeGen/CGLoopInfo.h
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/attr-noprogress.c
  clang/test/CodeGen/attr-noprogress.cpp

Index: clang/test/CodeGen/attr-noprogress.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noprogress.cpp
@@ -0,0 +1,55 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1fv
+// CHECK-SAME: () [[ATTR0:#.*]] {
+// 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]], !llvm.loop [[LOOP2:!.]]
+// CHECK:   for.end:
+// CHECK-NEXT:ret void
+//
+void f() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1wv
+// CHECK-SAME: () [[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[WHILE_BODY:%.*]]
+// CHECK:   while.body:
+// CHECK-NEXT:br label [[WHILE_BODY]], !llvm.loop [[LOOP4:!.]]
+//
+void w() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1dv
+// CHECK-SAME: () [[ATTR0]] {
+// 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:%.*]], !llvm.loop [[LOOP5:!.]]
+// CHECK:   do.end:
+// CHECK-NEXT:ret void
+//
+void d() {
+  do {
+
+  } while (1);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[LOOP_MD:!.]]}
+// CHECK: [[LOOP_MD]] = !{!"llvm.loop.noprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[LOOP_MD]]}
+// CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[LOOP_MD]]}
Index: clang/test/CodeGen/attr-noprogress.c
===
--- /dev/null
+++ clang/test/CodeGen/attr-noprogress.c
@@ -0,0 +1,52 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// 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]], !llvm.loop [[LOOP2:!.]]
+// CHECK:   for.end:
+// CHECK-NEXT:ret void
+//
+void f() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: @w(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[WHILE_BODY:%.*]]
+// CHECK:   while.body:
+// CHECK-NEXT:br label [[WHILE_BODY]], !llvm.loop [[LOOP4:!.]]
+//
+void w() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// 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:%.*]], !llvm.loop [[LOOP5:!.]]
+// CHECK:   do.end:
+// CHECK-NEXT:ret void
+//
+void d() {
+  do {
+
+  } while (1);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[LOOP_MD:!.]]}
+// CHECK: [[LOOP_MD]] = !{!"llvm.loop.noprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[LOOP_MD]]}
+// CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[LOOP_MD]]}
Index: clang/lib/CodeGen/CGStmt.cpp
===
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -736,10 +736,26 @@
   JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
   EmitBlock(LoopHeader.getBlock());
 
+  // Evaluate the conditional in the while header.  C99 6.8.5.1: The
+  // evaluation of the controlling expression takes place before each
+  // execution of the loop body.
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+  // while(1) is common, avoid extra exit blocks.  Be sure
+  // to correctly handle break/continue though.
+  bool EmitBoolCondBranch = true;
+  bool NoProgress = false;
+  if (llvm::ConstantInt *C = dyn_cast(BoolCondVal))
+if (C->isOne()) {
+  EmitBoolCondBranch = false;
+  CurFn->addFnAttr(llvm::Attribute::NoProgress);
+

[PATCH] D86841: [clang] Adds noprogress attribute deduction for infinite loops

2020-08-29 Thread Atmn Patel via Phabricator via cfe-commits
atmnpatel updated this revision to Diff 288817.
atmnpatel edited the summary of this revision.
atmnpatel added a comment.

Sorry, Fixed the test, added a C++ test. I checked the C++, OpenCL C, and 
OpenCL C++ specs and couldn't find anything that diverged from C spec in this 
regard, but none of them explicitly stated this behavior either.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86841

Files:
  clang/lib/CodeGen/CGLoopInfo.cpp
  clang/lib/CodeGen/CGLoopInfo.h
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/attr-noprogress.c
  clang/test/CodeGen/attr-noprogress.cpp

Index: clang/test/CodeGen/attr-noprogress.cpp
===
--- /dev/null
+++ clang/test/CodeGen/attr-noprogress.cpp
@@ -0,0 +1,55 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --force-update
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1fv
+// CHECK-SAME: () [[ATTR0:#.*]] {
+// 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]], !llvm.loop [[LOOP2:!.]]
+// CHECK:   for.end:
+// CHECK-NEXT:ret void
+//
+void f() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1wv
+// CHECK-SAME: () [[ATTR0]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[WHILE_BODY:%.*]]
+// CHECK:   while.body:
+// CHECK-NEXT:br label [[WHILE_BODY]], !llvm.loop [[LOOP4:!.]]
+//
+void w() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: define {{[^@]+}}@_Z1dv
+// CHECK-SAME: () [[ATTR0]] {
+// 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:%.*]], !llvm.loop [[LOOP5:!.]]
+// CHECK:   do.end:
+// CHECK-NEXT:ret void
+//
+void d() {
+  do {
+
+  } while (1);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[LOOP_MD:!.]]}
+// CHECK: [[LOOP_MD]] = !{!"llvm.loop.noprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[LOOP_MD]]}
+// CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[LOOP_MD]]}
Index: clang/test/CodeGen/attr-noprogress.c
===
--- /dev/null
+++ clang/test/CodeGen/attr-noprogress.c
@@ -0,0 +1,52 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --check-attributes
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | FileCheck %s
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// 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]], !llvm.loop [[LOOP2:!.]]
+// CHECK:   for.end:
+// CHECK-NEXT:ret void
+//
+void f() {
+  for (; 1;) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// CHECK-LABEL: @w(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:br label [[WHILE_BODY:%.*]]
+// CHECK:   while.body:
+// CHECK-NEXT:br label [[WHILE_BODY]], !llvm.loop [[LOOP4:!.]]
+//
+void w() {
+  while (1) {
+  }
+}
+
+// CHECK: Function Attrs: noinline nounwind optnone noprogress
+// 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:%.*]], !llvm.loop [[LOOP5:!.]]
+// CHECK:   do.end:
+// CHECK-NEXT:ret void
+//
+void d() {
+  do {
+
+  } while (1);
+}
+
+// CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[LOOP_MD:!.]]}
+// CHECK: [[LOOP_MD]] = !{!"llvm.loop.noprogress"}
+// CHECK: [[LOOP4]] = distinct !{[[LOOP4]], [[LOOP_MD]]}
+// CHECK: [[LOOP5]] = distinct !{[[LOOP5]], [[LOOP_MD]]}
Index: clang/lib/CodeGen/CGStmt.cpp
===
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -736,10 +736,26 @@
   JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
   EmitBlock(LoopHeader.getBlock());
 
+  // Evaluate the conditional in the while header.  C99 6.8.5.1: The
+  // evaluation of the controlling expression takes place before each
+  // execution of the loop body.
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+  // while(1) is common, avoid extra exit blocks.  Be sure
+  // t

[PATCH] D86841: [clang] Adds noprogress attribute deduction for infinite loops

2020-08-29 Thread Roman Lebedev via Phabricator via cfe-commits
lebedev.ri added a comment.

Does that wording apply to both the C and C++ (OpenCL?)?
Regardless, might be good to test that.




Comment at: clang/test/CodeGen/attr-noprogress.c:1-2
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | grep " noprogress " | count 1
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | grep llvm.loop.noprogress | count 1
+

Please just FileCheck the expected output. Bonus points for using 
`llvm/utils/update_cc_test_checks.py`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D86841

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D86841: [clang] Adds noprogress attribute deduction for infinite loops

2020-08-29 Thread Atmn Patel via Phabricator via cfe-commits
atmnpatel created this revision.
atmnpatel added reviewers: jdoerfert, aqjune, RalfJung.
Herald added subscribers: cfe-commits, danielkiss.
Herald added a project: clang.
atmnpatel requested review of this revision.

The `noprogress` LLVM IR attribute currently under discussion is deduced for 
functions that contain loops that have a constant non-zero conditional as per 
the C Spec. In addition, these particular loops have an additional bit of 
metadata `llvm.loop.noprogress` so llvm can differentiate between the loops 
that can be optimized out and ones that can't be optimized out. The changes to 
the LoopDeletion pass is incoming.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D86841

Files:
  clang/lib/CodeGen/CGLoopInfo.cpp
  clang/lib/CodeGen/CGLoopInfo.h
  clang/lib/CodeGen/CGStmt.cpp
  clang/test/CodeGen/attr-noprogress.c

Index: clang/test/CodeGen/attr-noprogress.c
===
--- /dev/null
+++ clang/test/CodeGen/attr-noprogress.c
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | grep " noprogress " | count 1
+// RUN: %clang_cc1 -S -emit-llvm %s -o - | grep llvm.loop.noprogress | count 1
+
+void f() {
+  for (; 1;) {
+  }
+}
+
+void w() {
+  while (1) {
+  }
+}
+
+void d() {
+  do {
+
+  } while (1);
+}
Index: clang/lib/CodeGen/CGStmt.cpp
===
--- clang/lib/CodeGen/CGStmt.cpp
+++ clang/lib/CodeGen/CGStmt.cpp
@@ -736,10 +736,26 @@
   JumpDest LoopHeader = getJumpDestInCurrentScope("while.cond");
   EmitBlock(LoopHeader.getBlock());
 
+  // Evaluate the conditional in the while header.  C99 6.8.5.1: The
+  // evaluation of the controlling expression takes place before each
+  // execution of the loop body.
+  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
+
+  // while(1) is common, avoid extra exit blocks.  Be sure
+  // to correctly handle break/continue though.
+  bool EmitBoolCondBranch = true;
+  bool NoProgress = false;
+  if (llvm::ConstantInt *C = dyn_cast(BoolCondVal))
+if (C->isOne()) {
+  EmitBoolCondBranch = false;
+  CurFn->addFnAttr(llvm::Attribute::NoProgress);
+  NoProgress = true;
+}
+
   const SourceRange &R = S.getSourceRange();
   LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(),
  WhileAttrs, SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()));
+ SourceLocToDebugLoc(R.getEnd()), NoProgress);
 
   // Create an exit block for when the condition fails, which will
   // also become the break target.
@@ -760,18 +776,6 @@
   if (S.getConditionVariable())
 EmitDecl(*S.getConditionVariable());
 
-  // Evaluate the conditional in the while header.  C99 6.8.5.1: The
-  // evaluation of the controlling expression takes place before each
-  // execution of the loop body.
-  llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
-
-  // while(1) is common, avoid extra exit blocks.  Be sure
-  // to correctly handle break/continue though.
-  bool EmitBoolCondBranch = true;
-  if (llvm::ConstantInt *C = dyn_cast(BoolCondVal))
-if (C->isOne())
-  EmitBoolCondBranch = false;
-
   // As long as the condition is true, go to the loop body.
   llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
   if (EmitBoolCondBranch) {
@@ -838,27 +842,33 @@
 
   EmitBlock(LoopCond.getBlock());
 
-  const SourceRange &R = S.getSourceRange();
-  LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
- SourceLocToDebugLoc(R.getBegin()),
- SourceLocToDebugLoc(R.getEnd()));
-
-  // C99 6.8.5.2: "The evaluation of the controlling expression takes place
-  // after each execution of the loop body."
-
   // Evaluate the conditional in the while header.
   // C99 6.8.5p2/p4: The first substatement is executed if the expression
   // compares unequal to 0.  The condition must be a scalar type.
   llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
 
-  BreakContinueStack.pop_back();
-
   // "do {} while (0)" is common in macros, avoid extra blocks.  Be sure
   // to correctly handle break/continue though.
   bool EmitBoolCondBranch = true;
-  if (llvm::ConstantInt *C = dyn_cast(BoolCondVal))
+  bool NoProgress = false;
+  if (llvm::ConstantInt *C = dyn_cast(BoolCondVal)) {
 if (C->isZero())
   EmitBoolCondBranch = false;
+if (C->isOne()) {
+  CurFn->addFnAttr(llvm::Attribute::NoProgress);
+  NoProgress = true;
+}
+  }
+
+  const SourceRange &R = S.getSourceRange();
+  LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs,
+ SourceLocToDebugLoc(R.getBegin()),
+ SourceLocToDebugLoc(R.getEnd()), NoProgress);
+
+  // C99 6.8.5.2: "The evaluation of the controlling expression takes place
+  // after each execution of the loop body."
+
+  BreakContinueStack.pop_back();
 
   // As long as the condition