<div dir="ltr">Hi Raghu,<br><br>I see a warning with this change: <br>clang/lib/CodeGen/CGStmtOpenMP.cpp:6166:11: warning: enumeration value 'OMPC_cancellation_construct_type' not handled in switch [-Wswitch]<br>  switch (Kind) {<br>          ^<br>It also needs to be added to the switch statement for <span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;white-space:pre">emitOMPAtomicExpr</span>. Can you please also add it there.<br><br>Thanks,<br>Rumeet<br><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, May 2, 2022 at 10:24 AM Raghu Maddhipatla via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Raghu Maddhipatla<br>
Date: 2022-05-02T12:23:38-05:00<br>
New Revision: c685f8212689665968de47f8bd4b1146296e8cc2<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/c685f8212689665968de47f8bd4b1146296e8cc2" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/c685f8212689665968de47f8bd4b1146296e8cc2</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/c685f8212689665968de47f8bd4b1146296e8cc2.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/c685f8212689665968de47f8bd4b1146296e8cc2.diff</a><br>
<br>
LOG: [mlir][OpenMP] Add omp.cancel and omp.cancellationpoint.<br>
<br>
Reviewed By: kiranchandramohan, peixin, shraiysh<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D123828" rel="noreferrer" target="_blank">https://reviews.llvm.org/D123828</a><br>
<br>
Added: <br>
<br>
<br>
Modified: <br>
    flang/lib/Semantics/check-omp-structure.cpp<br>
    llvm/include/llvm/Frontend/OpenMP/OMP.td<br>
    mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td<br>
    mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp<br>
    mlir/test/Dialect/OpenMP/invalid.mlir<br>
    mlir/test/Dialect/OpenMP/ops.mlir<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp<br>
index cf56efb632d0f..83acaba367ffd 100644<br>
--- a/flang/lib/Semantics/check-omp-structure.cpp<br>
+++ b/flang/lib/Semantics/check-omp-structure.cpp<br>
@@ -1806,6 +1806,7 @@ CHECK_SIMPLE_CLAUSE(MemoryOrder, OMPC_memory_order)<br>
 CHECK_SIMPLE_CLAUSE(Bind, OMPC_bind)<br>
 CHECK_SIMPLE_CLAUSE(Align, OMPC_align)<br>
 CHECK_SIMPLE_CLAUSE(Compare, OMPC_compare)<br>
+CHECK_SIMPLE_CLAUSE(CancellationConstructType, OMPC_cancellation_construct_type)<br>
<br>
 CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)<br>
 CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)<br>
<br>
diff  --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td<br>
index e5a1dd3931247..9575f6df6caea 100644<br>
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td<br>
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td<br>
@@ -163,6 +163,25 @@ def OMPC_MemoryOrder : Clause<"memory_order"> {<br>
   ];<br>
 }<br>
<br>
+def OMP_CANCELLATION_CONSTRUCT_Parallel : ClauseVal<"parallel", 1, 1> {}<br>
+def OMP_CANCELLATION_CONSTRUCT_Loop : ClauseVal<"loop", 2, 1> {}<br>
+def OMP_CANCELLATION_CONSTRUCT_Sections : ClauseVal<"sections", 3, 1> {}<br>
+def OMP_CANCELLATION_CONSTRUCT_Taskgroup : ClauseVal<"taskgroup", 4, 1> {}<br>
+def OMP_CANCELLATION_CONSTRUCT_None : ClauseVal<"none", 5, 0> {<br>
+  let isDefault = 1;<br>
+}<br>
+<br>
+def OMPC_CancellationConstructType : Clause<"cancellation_construct_type"> {<br>
+  let enumClauseValue = "CancellationConstructType";<br>
+  let allowedClauseValues = [<br>
+    OMP_CANCELLATION_CONSTRUCT_Parallel,<br>
+    OMP_CANCELLATION_CONSTRUCT_Loop,<br>
+    OMP_CANCELLATION_CONSTRUCT_Sections,<br>
+    OMP_CANCELLATION_CONSTRUCT_Taskgroup,<br>
+    OMP_CANCELLATION_CONSTRUCT_None<br>
+  ];<br>
+}<br>
+<br>
 def OMPC_Ordered : Clause<"ordered"> {<br>
   let clangClass = "OMPOrderedClause";<br>
   let flangClass = "ScalarIntConstantExpr";<br>
<br>
diff  --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td<br>
index bc5a7ff89783f..e69891ec9abf3 100644<br>
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td<br>
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td<br>
@@ -998,6 +998,40 @@ def ThreadprivateOp : OpenMP_Op<"threadprivate"> {<br>
   }];<br>
 }<br>
<br>
+//===----------------------------------------------------------------------===//<br>
+// 2.18.1 Cancel Construct<br>
+//===----------------------------------------------------------------------===//<br>
+def CancelOp : OpenMP_Op<"cancel"> {<br>
+  let summary = "cancel directive";<br>
+  let description = [{<br>
+    The cancel construct activates cancellation of the innermost enclosing<br>
+    region of the type specified.<br>
+  }];<br>
+  let arguments = (ins CancellationConstructTypeAttr:$cancellation_construct_type_val,<br>
+                       Optional<I1>:$if_expr);<br>
+  let assemblyFormat = [{ `cancellation_construct_type` `(`<br>
+                          custom<ClauseAttr>($cancellation_construct_type_val) `)`<br>
+                          ( `if` `(` $if_expr^ `)` )? attr-dict}];<br>
+  let hasVerifier = 1;<br>
+}<br>
+<br>
+//===----------------------------------------------------------------------===//<br>
+// 2.18.2 Cancellation Point Construct<br>
+//===----------------------------------------------------------------------===//<br>
+def CancellationPointOp : OpenMP_Op<"cancellationpoint"> {<br>
+  let summary = "cancellation point directive";<br>
+  let description = [{<br>
+    The cancellation point construct introduces a user-defined cancellation<br>
+    point at which implicit or explicit tasks check if cancellation of the<br>
+    innermost enclosing region of the type specified has been activated.<br>
+  }];<br>
+  let arguments = (ins CancellationConstructTypeAttr:$cancellation_construct_type_val);<br>
+  let assemblyFormat = [{ `cancellation_construct_type` `(`<br>
+                           custom<ClauseAttr>($cancellation_construct_type_val) `)`<br>
+                           attr-dict}];<br>
+  let hasVerifier = 1;<br>
+}<br>
+<br>
 //===----------------------------------------------------------------------===//<br>
 // 2.19.5.7 declare reduction Directive<br>
 //===----------------------------------------------------------------------===//<br>
<br>
diff  --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp<br>
index fa2becae7e637..5540eec8f3005 100644<br>
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp<br>
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp<br>
@@ -950,6 +950,80 @@ LogicalResult AtomicCaptureOp::verifyRegions() {<br>
   return success();<br>
 }<br>
<br>
+//===----------------------------------------------------------------------===//<br>
+// Verifier for CancelOp<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+LogicalResult CancelOp::verify() {<br>
+  ClauseCancellationConstructType cct = cancellation_construct_type_val();<br>
+  Operation *parentOp = (*this)->getParentOp();<br>
+<br>
+  if (!parentOp) {<br>
+    return emitOpError() << "must be used within a region supporting "<br>
+                            "cancel directive";<br>
+  }<br>
+<br>
+  if ((cct == ClauseCancellationConstructType::Parallel) &&<br>
+      !isa<ParallelOp>(parentOp)) {<br>
+    return emitOpError() << "cancel parallel must appear "<br>
+                         << "inside a parallel region";<br>
+  } else if (cct == ClauseCancellationConstructType::Loop) {<br>
+    if (!isa<WsLoopOp>(parentOp)) {<br>
+      return emitOpError() << "cancel loop must appear "<br>
+                           << "inside a worksharing-loop region";<br>
+    } else {<br>
+      if (cast<WsLoopOp>(parentOp).nowaitAttr()) {<br>
+        return emitError() << "A worksharing construct that is canceled "<br>
+                           << "must not have a nowait clause";<br>
+      } else if (cast<WsLoopOp>(parentOp).ordered_valAttr()) {<br>
+        return emitError() << "A worksharing construct that is canceled "<br>
+                           << "must not have an ordered clause";<br>
+      }<br>
+    }<br>
+  } else if (cct == ClauseCancellationConstructType::Sections) {<br>
+    if (!(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {<br>
+      return emitOpError() << "cancel sections must appear "<br>
+                           << "inside a sections region";<br>
+    }<br>
+    if (parentOp->getParentOp() && isa<SectionsOp>(parentOp->getParentOp()) &&<br>
+        cast<SectionsOp>(parentOp->getParentOp()).nowaitAttr()) {<br>
+      return emitError() << "A sections construct that is canceled "<br>
+                         << "must not have a nowait clause";<br>
+    }<br>
+  }<br>
+  // TODO : Add more when we support taskgroup.<br>
+  return success();<br>
+}<br>
+//===----------------------------------------------------------------------===//<br>
+// Verifier for CancelOp<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+LogicalResult CancellationPointOp::verify() {<br>
+  ClauseCancellationConstructType cct = cancellation_construct_type_val();<br>
+  Operation *parentOp = (*this)->getParentOp();<br>
+<br>
+  if (!parentOp) {<br>
+    return emitOpError() << "must be used within a region supporting "<br>
+                            "cancellation point directive";<br>
+  }<br>
+<br>
+  if ((cct == ClauseCancellationConstructType::Parallel) &&<br>
+      !(isa<ParallelOp>(parentOp))) {<br>
+    return emitOpError() << "cancellation point parallel must appear "<br>
+                         << "inside a parallel region";<br>
+  } else if ((cct == ClauseCancellationConstructType::Loop) &&<br>
+             !isa<WsLoopOp>(parentOp)) {<br>
+    return emitOpError() << "cancellation point loop must appear "<br>
+                         << "inside a worksharing-loop region";<br>
+  } else if ((cct == ClauseCancellationConstructType::Sections) &&<br>
+             !(isa<SectionsOp>(parentOp) || isa<SectionOp>(parentOp))) {<br>
+    return emitOpError() << "cancellation point sections must appear "<br>
+                         << "inside a sections region";<br>
+  }<br>
+  // TODO : Add more when we support taskgroup.<br>
+  return success();<br>
+}<br>
+<br>
 #define GET_ATTRDEF_CLASSES<br>
 #include "mlir/Dialect/OpenMP/OpenMPOpsAttributes.cpp.inc"<br>
<br>
<br>
diff  --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir<br>
index e88c7c4b70597..61e44b04593bd 100644<br>
--- a/mlir/test/Dialect/OpenMP/invalid.mlir<br>
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir<br>
@@ -1143,3 +1143,116 @@ func.func @omp_task(%mem: memref<1xf32>) {<br>
   }<br>
   return<br>
 }<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel() {<br>
+  omp.sections {<br>
+    // expected-error @below {{cancel parallel must appear inside a parallel region}}<br>
+    omp.cancel cancellation_construct_type(parallel)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel1() {<br>
+  omp.parallel {<br>
+    // expected-error @below {{cancel sections must appear inside a sections region}}<br>
+    omp.cancel cancellation_construct_type(sections)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel2() {<br>
+  omp.sections {<br>
+    // expected-error @below {{cancel loop must appear inside a worksharing-loop region}}<br>
+    omp.cancel cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel3(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {<br>
+  omp.wsloop nowait<br>
+    for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {<br>
+    // expected-error @below {{A worksharing construct that is canceled must not have a nowait clause}}<br>
+    omp.cancel cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel4(%arg1 : i32, %arg2 : i32, %arg3 : i32) -> () {<br>
+  omp.wsloop ordered(1)<br>
+    for (%0) : i32 = (%arg1) to (%arg2) step (%arg3) {<br>
+    // expected-error @below {{A worksharing construct that is canceled must not have an ordered clause}}<br>
+    omp.cancel cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancel5() -> () {<br>
+  omp.sections nowait {<br>
+    omp.section {<br>
+      // expected-error @below {{A sections construct that is canceled must not have a nowait clause}}<br>
+      omp.cancel cancellation_construct_type(sections)<br>
+      omp.terminator<br>
+    }<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancellationpoint() {<br>
+  omp.sections {<br>
+    // expected-error @below {{cancellation point parallel must appear inside a parallel region}}<br>
+    omp.cancellationpoint cancellation_construct_type(parallel)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancellationpoint1() {<br>
+  omp.parallel {<br>
+    // expected-error @below {{cancellation point sections must appear inside a sections region}}<br>
+    omp.cancellationpoint cancellation_construct_type(sections)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+// -----<br>
+<br>
+func @omp_cancellationpoint2() {<br>
+  omp.sections {<br>
+    // expected-error @below {{cancellation point loop must appear inside a worksharing-loop region}}<br>
+    omp.cancellationpoint cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
<br>
diff  --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir<br>
index 15ec6f796b880..9dd76c4dfc2ac 100644<br>
--- a/mlir/test/Dialect/OpenMP/ops.mlir<br>
+++ b/mlir/test/Dialect/OpenMP/ops.mlir<br>
@@ -1276,3 +1276,77 @@ func.func @omp_threadprivate() {<br>
 }<br>
<br>
 llvm.mlir.global internal @_QFsubEx() : i32<br>
+<br>
+func @omp_cancel_parallel(%if_cond : i1) -> () {<br>
+  // Test with optional operand; if_expr.<br>
+  omp.parallel {<br>
+    // CHECK: omp.cancel cancellation_construct_type(parallel) if(%{{.*}})<br>
+    omp.cancel cancellation_construct_type(parallel) if(%if_cond)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+func @omp_cancel_wsloop(%lb : index, %ub : index, %step : index) {<br>
+  omp.wsloop<br>
+  for (%iv) : index = (%lb) to (%ub) step (%step) {<br>
+    // CHECK: omp.cancel cancellation_construct_type(loop)<br>
+    omp.cancel cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+func @omp_cancel_sections() -> () {<br>
+  omp.sections {<br>
+    omp.section {<br>
+      // CHECK: omp.cancel cancellation_construct_type(sections)<br>
+      omp.cancel cancellation_construct_type(sections)<br>
+      omp.terminator<br>
+    }<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+func @omp_cancellationpoint_parallel() -> () {<br>
+  omp.parallel {<br>
+    // CHECK: omp.cancellationpoint cancellation_construct_type(parallel)<br>
+    omp.cancellationpoint cancellation_construct_type(parallel)<br>
+    // CHECK: omp.cancel cancellation_construct_type(parallel)<br>
+    omp.cancel cancellation_construct_type(parallel)<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+func @omp_cancellationpoint_wsloop(%lb : index, %ub : index, %step : index) {<br>
+  omp.wsloop<br>
+  for (%iv) : index = (%lb) to (%ub) step (%step) {<br>
+    // CHECK: omp.cancellationpoint cancellation_construct_type(loop)<br>
+    omp.cancellationpoint cancellation_construct_type(loop)<br>
+    // CHECK: omp.cancel cancellation_construct_type(loop)<br>
+    omp.cancel cancellation_construct_type(loop)<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
+<br>
+func @omp_cancellationpoint_sections() -> () {<br>
+  omp.sections {<br>
+    omp.section {<br>
+      // CHECK: omp.cancellationpoint cancellation_construct_type(sections)<br>
+      omp.cancellationpoint cancellation_construct_type(sections)<br>
+      // CHECK: omp.cancel cancellation_construct_type(sections)<br>
+      omp.cancel cancellation_construct_type(sections)<br>
+      omp.terminator<br>
+    }<br>
+    // CHECK: omp.terminator<br>
+    omp.terminator<br>
+  }<br>
+  return<br>
+}<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>