[Mlir-commits] [mlir] 8338a3c - [mlir][OpenMP] Convert omp.cancellation_point to LLVMIR (#137205)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu May 8 03:09:16 PDT 2025
Author: Tom Eccles
Date: 2025-05-08T11:09:13+01:00
New Revision: 8338a3c92ba08cf409a75adbfb212aa06ca66f31
URL: https://github.com/llvm/llvm-project/commit/8338a3c92ba08cf409a75adbfb212aa06ca66f31
DIFF: https://github.com/llvm/llvm-project/commit/8338a3c92ba08cf409a75adbfb212aa06ca66f31.diff
LOG: [mlir][OpenMP] Convert omp.cancellation_point to LLVMIR (#137205)
This is basically identical to cancel except without the if clause.
taskgroup will be implemented in a followup PR.
Added:
mlir/test/Target/LLVMIR/openmp-cancellation-point.mlir
Modified:
llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
mlir/test/Target/LLVMIR/openmp-todo.mlir
Removed:
################################################################################
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
index a483b0a6cfdc5..ffc0fd0a0bdac 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPIRBuilder.h
@@ -686,6 +686,16 @@ class OpenMPIRBuilder {
Value *IfCondition,
omp::Directive CanceledDirective);
+ /// Generator for '#omp cancellation point'
+ ///
+ /// \param Loc The location where the directive was encountered.
+ /// \param CanceledDirective The kind of directive that is cancled.
+ ///
+ /// \returns The insertion point after the barrier.
+ InsertPointOrErrorTy
+ createCancellationPoint(const LocationDescription &Loc,
+ omp::Directive CanceledDirective);
+
/// Generator for '#omp parallel'
///
/// \param Loc The insert and source location description.
diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
index 7c1b64677a011..a1268ca76b2d5 100644
--- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
+++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp
@@ -1096,6 +1096,57 @@ OpenMPIRBuilder::createCancel(const LocationDescription &Loc,
return Builder.saveIP();
}
+OpenMPIRBuilder::InsertPointOrErrorTy
+OpenMPIRBuilder::createCancellationPoint(const LocationDescription &Loc,
+ omp::Directive CanceledDirective) {
+ if (!updateToLocation(Loc))
+ return Loc.IP;
+
+ // LLVM utilities like blocks with terminators.
+ auto *UI = Builder.CreateUnreachable();
+ Builder.SetInsertPoint(UI);
+
+ Value *CancelKind = nullptr;
+ switch (CanceledDirective) {
+#define OMP_CANCEL_KIND(Enum, Str, DirectiveEnum, Value) \
+ case DirectiveEnum: \
+ CancelKind = Builder.getInt32(Value); \
+ break;
+#include "llvm/Frontend/OpenMP/OMPKinds.def"
+ default:
+ llvm_unreachable("Unknown cancel kind!");
+ }
+
+ uint32_t SrcLocStrSize;
+ Constant *SrcLocStr = getOrCreateSrcLocStr(Loc, SrcLocStrSize);
+ Value *Ident = getOrCreateIdent(SrcLocStr, SrcLocStrSize);
+ Value *Args[] = {Ident, getOrCreateThreadID(Ident), CancelKind};
+ Value *Result = Builder.CreateCall(
+ getOrCreateRuntimeFunctionPtr(OMPRTL___kmpc_cancellationpoint), Args);
+ auto ExitCB = [this, CanceledDirective, Loc](InsertPointTy IP) -> Error {
+ if (CanceledDirective == OMPD_parallel) {
+ IRBuilder<>::InsertPointGuard IPG(Builder);
+ Builder.restoreIP(IP);
+ return createBarrier(LocationDescription(Builder.saveIP(), Loc.DL),
+ omp::Directive::OMPD_unknown,
+ /* ForceSimpleCall */ false,
+ /* CheckCancelFlag */ false)
+ .takeError();
+ }
+ return Error::success();
+ };
+
+ // The actual cancel logic is shared with others, e.g., cancel_barriers.
+ if (Error Err = emitCancelationCheckImpl(Result, CanceledDirective, ExitCB))
+ return Err;
+
+ // Update the insertion point and remove the terminator we introduced.
+ Builder.SetInsertPoint(UI->getParent());
+ UI->eraseFromParent();
+
+ return Builder.saveIP();
+}
+
OpenMPIRBuilder::InsertPointTy OpenMPIRBuilder::emitTargetKernel(
const LocationDescription &Loc, InsertPointTy AllocaIP, Value *&Return,
Value *Ident, Value *DeviceID, Value *NumTeams, Value *NumThreads,
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index d9c0c2024c94b..2e8e5a6ca5c2a 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -241,6 +241,9 @@ static LogicalResult checkImplementationStatus(Operation &op) {
LogicalResult result = success();
llvm::TypeSwitch<Operation &>(op)
.Case([&](omp::CancelOp op) { checkCancelDirective(op, result); })
+ .Case([&](omp::CancellationPointOp op) {
+ checkCancelDirective(op, result);
+ })
.Case([&](omp::DistributeOp op) {
checkAllocate(op, result);
checkDistSchedule(op, result);
@@ -1576,11 +1579,12 @@ cleanupPrivateVars(llvm::IRBuilderBase &builder,
/// Returns true if the construct contains omp.cancel or omp.cancellation_point
static bool constructIsCancellable(Operation *op) {
- // omp.cancel must be "closely nested" so it will be visible and not inside of
- // funcion calls. This is enforced by the verifier.
+ // omp.cancel and omp.cancellation_point must be "closely nested" so they will
+ // be visible and not inside of function calls. This is enforced by the
+ // verifier.
return op
->walk([](Operation *child) {
- if (mlir::isa<omp::CancelOp>(child))
+ if (mlir::isa<omp::CancelOp, omp::CancellationPointOp>(child))
return WalkResult::interrupt();
return WalkResult::advance();
})
@@ -3080,6 +3084,30 @@ convertOmpCancel(omp::CancelOp op, llvm::IRBuilderBase &builder,
return success();
}
+static LogicalResult
+convertOmpCancellationPoint(omp::CancellationPointOp op,
+ llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ llvm::OpenMPIRBuilder::LocationDescription ompLoc(builder);
+ llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
+
+ if (failed(checkImplementationStatus(*op.getOperation())))
+ return failure();
+
+ llvm::omp::Directive cancelledDirective =
+ convertCancellationConstructType(op.getCancelDirective());
+
+ llvm::OpenMPIRBuilder::InsertPointOrErrorTy afterIP =
+ ompBuilder->createCancellationPoint(ompLoc, cancelledDirective);
+
+ if (failed(handleError(afterIP, *op.getOperation())))
+ return failure();
+
+ builder.restoreIP(afterIP.get());
+
+ return success();
+}
+
/// Converts an OpenMP Threadprivate operation into LLVM IR using
/// OpenMPIRBuilder.
static LogicalResult
@@ -5519,6 +5547,9 @@ convertHostOrTargetOperation(Operation *op, llvm::IRBuilderBase &builder,
.Case([&](omp::CancelOp op) {
return convertOmpCancel(op, builder, moduleTranslation);
})
+ .Case([&](omp::CancellationPointOp op) {
+ return convertOmpCancellationPoint(op, builder, moduleTranslation);
+ })
.Case([&](omp::SectionsOp) {
return convertOmpSections(*op, builder, moduleTranslation);
})
diff --git a/mlir/test/Target/LLVMIR/openmp-cancellation-point.mlir b/mlir/test/Target/LLVMIR/openmp-cancellation-point.mlir
new file mode 100644
index 0000000000000..bbb313c113567
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/openmp-cancellation-point.mlir
@@ -0,0 +1,188 @@
+// RUN: mlir-translate --mlir-to-llvmir %s | FileCheck %s
+
+llvm.func @cancellation_point_parallel() {
+ omp.parallel {
+ omp.cancellation_point cancellation_construct_type(parallel)
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK-LABEL: define internal void @cancellation_point_parallel..omp_par
+// CHECK: omp.par.entry:
+// CHECK: %[[VAL_5:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_6:.*]] = load i32, ptr %[[VAL_7:.*]], align 4
+// CHECK: store i32 %[[VAL_6]], ptr %[[VAL_5]], align 4
+// CHECK: %[[VAL_8:.*]] = load i32, ptr %[[VAL_5]], align 4
+// CHECK: br label %[[VAL_9:.*]]
+// CHECK: omp.region.after_alloca: ; preds = %[[VAL_10:.*]]
+// CHECK: br label %[[VAL_11:.*]]
+// CHECK: omp.par.region: ; preds = %[[VAL_9]]
+// CHECK: br label %[[VAL_12:.*]]
+// CHECK: omp.par.region1: ; preds = %[[VAL_11]]
+// CHECK: %[[VAL_13:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: %[[VAL_14:.*]] = call i32 @__kmpc_cancellationpoint(ptr @1, i32 %[[VAL_13]], i32 1)
+// CHECK: %[[VAL_15:.*]] = icmp eq i32 %[[VAL_14]], 0
+// CHECK: br i1 %[[VAL_15]], label %[[VAL_16:.*]], label %[[VAL_17:.*]]
+// CHECK: omp.par.region1.cncl: ; preds = %[[VAL_12]]
+// CHECK: %[[VAL_18:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: %[[VAL_19:.*]] = call i32 @__kmpc_cancel_barrier(ptr @2, i32 %[[VAL_18]])
+// CHECK: br label %[[VAL_20:.*]]
+// CHECK: omp.par.region1.split: ; preds = %[[VAL_12]]
+// CHECK: br label %[[VAL_21:.*]]
+// CHECK: omp.region.cont: ; preds = %[[VAL_16]]
+// CHECK: br label %[[VAL_22:.*]]
+// CHECK: omp.par.pre_finalize: ; preds = %[[VAL_21]]
+// CHECK: br label %[[VAL_20]]
+// CHECK: omp.par.exit.exitStub: ; preds = %[[VAL_22]], %[[VAL_17]]
+// CHECK: ret void
+
+llvm.func @cancellation_point_sections() {
+ omp.sections {
+ omp.section {
+ omp.cancellation_point cancellation_construct_type(sections)
+ omp.terminator
+ }
+ omp.terminator
+ }
+ llvm.return
+}
+// CHECK-LABEL: define void @cancellation_point_sections
+// CHECK: %[[VAL_23:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_24:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_25:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_26:.*]] = alloca i32, align 4
+// CHECK: br label %[[VAL_27:.*]]
+// CHECK: entry: ; preds = %[[VAL_28:.*]]
+// CHECK: br label %[[VAL_29:.*]]
+// CHECK: omp_section_loop.preheader: ; preds = %[[VAL_27]]
+// CHECK: store i32 0, ptr %[[VAL_24]], align 4
+// CHECK: store i32 0, ptr %[[VAL_25]], align 4
+// CHECK: store i32 1, ptr %[[VAL_26]], align 4
+// CHECK: %[[VAL_30:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: call void @__kmpc_for_static_init_4u(ptr @1, i32 %[[VAL_30]], i32 34, ptr %[[VAL_23]], ptr %[[VAL_24]], ptr %[[VAL_25]], ptr %[[VAL_26]], i32 1, i32 0)
+// CHECK: %[[VAL_31:.*]] = load i32, ptr %[[VAL_24]], align 4
+// CHECK: %[[VAL_32:.*]] = load i32, ptr %[[VAL_25]], align 4
+// CHECK: %[[VAL_33:.*]] = sub i32 %[[VAL_32]], %[[VAL_31]]
+// CHECK: %[[VAL_34:.*]] = add i32 %[[VAL_33]], 1
+// CHECK: br label %[[VAL_35:.*]]
+// CHECK: omp_section_loop.header: ; preds = %[[VAL_36:.*]], %[[VAL_29]]
+// CHECK: %[[VAL_37:.*]] = phi i32 [ 0, %[[VAL_29]] ], [ %[[VAL_38:.*]], %[[VAL_36]] ]
+// CHECK: br label %[[VAL_39:.*]]
+// CHECK: omp_section_loop.cond: ; preds = %[[VAL_35]]
+// CHECK: %[[VAL_40:.*]] = icmp ult i32 %[[VAL_37]], %[[VAL_34]]
+// CHECK: br i1 %[[VAL_40]], label %[[VAL_41:.*]], label %[[VAL_42:.*]]
+// CHECK: omp_section_loop.body: ; preds = %[[VAL_39]]
+// CHECK: %[[VAL_43:.*]] = add i32 %[[VAL_37]], %[[VAL_31]]
+// CHECK: %[[VAL_44:.*]] = mul i32 %[[VAL_43]], 1
+// CHECK: %[[VAL_45:.*]] = add i32 %[[VAL_44]], 0
+// CHECK: switch i32 %[[VAL_45]], label %[[VAL_46:.*]] [
+// CHECK: i32 0, label %[[VAL_47:.*]]
+// CHECK: ]
+// CHECK: omp_section_loop.body.case: ; preds = %[[VAL_41]]
+// CHECK: br label %[[VAL_48:.*]]
+// CHECK: omp.section.region: ; preds = %[[VAL_47]]
+// CHECK: %[[VAL_49:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: %[[VAL_50:.*]] = call i32 @__kmpc_cancellationpoint(ptr @1, i32 %[[VAL_49]], i32 3)
+// CHECK: %[[VAL_51:.*]] = icmp eq i32 %[[VAL_50]], 0
+// CHECK: br i1 %[[VAL_51]], label %[[VAL_52:.*]], label %[[VAL_53:.*]]
+// CHECK: omp.section.region.split: ; preds = %[[VAL_48]]
+// CHECK: br label %[[VAL_54:.*]]
+// CHECK: omp.region.cont: ; preds = %[[VAL_52]]
+// CHECK: br label %[[VAL_46]]
+// CHECK: omp_section_loop.body.sections.after: ; preds = %[[VAL_54]], %[[VAL_41]]
+// CHECK: br label %[[VAL_36]]
+// CHECK: omp_section_loop.inc: ; preds = %[[VAL_46]]
+// CHECK: %[[VAL_38]] = add nuw i32 %[[VAL_37]], 1
+// CHECK: br label %[[VAL_35]]
+// CHECK: omp_section_loop.exit: ; preds = %[[VAL_53]], %[[VAL_39]]
+// CHECK: call void @__kmpc_for_static_fini(ptr @1, i32 %[[VAL_30]])
+// CHECK: %[[VAL_55:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: call void @__kmpc_barrier(ptr @2, i32 %[[VAL_55]])
+// CHECK: br label %[[VAL_56:.*]]
+// CHECK: omp_section_loop.after: ; preds = %[[VAL_42]]
+// CHECK: br label %[[VAL_57:.*]]
+// CHECK: omp_section_loop.aftersections.fini: ; preds = %[[VAL_56]]
+// CHECK: ret void
+// CHECK: omp.section.region.cncl: ; preds = %[[VAL_48]]
+// CHECK: br label %[[VAL_42]]
+
+llvm.func @cancellation_point_wsloop(%lb : i32, %ub : i32, %step : i32) {
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.cancellation_point cancellation_construct_type(loop)
+ omp.yield
+ }
+ }
+ llvm.return
+}
+// CHECK-LABEL: define void @cancellation_point_wsloop
+// CHECK: %[[VAL_58:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_59:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_60:.*]] = alloca i32, align 4
+// CHECK: %[[VAL_61:.*]] = alloca i32, align 4
+// CHECK: br label %[[VAL_62:.*]]
+// CHECK: omp.region.after_alloca: ; preds = %[[VAL_63:.*]]
+// CHECK: br label %[[VAL_64:.*]]
+// CHECK: entry: ; preds = %[[VAL_62]]
+// CHECK: br label %[[VAL_65:.*]]
+// CHECK: omp.wsloop.region: ; preds = %[[VAL_64]]
+// CHECK: %[[VAL_66:.*]] = icmp slt i32 %[[VAL_67:.*]], 0
+// CHECK: %[[VAL_68:.*]] = sub i32 0, %[[VAL_67]]
+// CHECK: %[[VAL_69:.*]] = select i1 %[[VAL_66]], i32 %[[VAL_68]], i32 %[[VAL_67]]
+// CHECK: %[[VAL_70:.*]] = select i1 %[[VAL_66]], i32 %[[VAL_71:.*]], i32 %[[VAL_72:.*]]
+// CHECK: %[[VAL_73:.*]] = select i1 %[[VAL_66]], i32 %[[VAL_72]], i32 %[[VAL_71]]
+// CHECK: %[[VAL_74:.*]] = sub nsw i32 %[[VAL_73]], %[[VAL_70]]
+// CHECK: %[[VAL_75:.*]] = icmp sle i32 %[[VAL_73]], %[[VAL_70]]
+// CHECK: %[[VAL_76:.*]] = sub i32 %[[VAL_74]], 1
+// CHECK: %[[VAL_77:.*]] = udiv i32 %[[VAL_76]], %[[VAL_69]]
+// CHECK: %[[VAL_78:.*]] = add i32 %[[VAL_77]], 1
+// CHECK: %[[VAL_79:.*]] = icmp ule i32 %[[VAL_74]], %[[VAL_69]]
+// CHECK: %[[VAL_80:.*]] = select i1 %[[VAL_79]], i32 1, i32 %[[VAL_78]]
+// CHECK: %[[VAL_81:.*]] = select i1 %[[VAL_75]], i32 0, i32 %[[VAL_80]]
+// CHECK: br label %[[VAL_82:.*]]
+// CHECK: omp_loop.preheader: ; preds = %[[VAL_65]]
+// CHECK: store i32 0, ptr %[[VAL_59]], align 4
+// CHECK: %[[VAL_83:.*]] = sub i32 %[[VAL_81]], 1
+// CHECK: store i32 %[[VAL_83]], ptr %[[VAL_60]], align 4
+// CHECK: store i32 1, ptr %[[VAL_61]], align 4
+// CHECK: %[[VAL_84:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: call void @__kmpc_for_static_init_4u(ptr @1, i32 %[[VAL_84]], i32 34, ptr %[[VAL_58]], ptr %[[VAL_59]], ptr %[[VAL_60]], ptr %[[VAL_61]], i32 1, i32 0)
+// CHECK: %[[VAL_85:.*]] = load i32, ptr %[[VAL_59]], align 4
+// CHECK: %[[VAL_86:.*]] = load i32, ptr %[[VAL_60]], align 4
+// CHECK: %[[VAL_87:.*]] = sub i32 %[[VAL_86]], %[[VAL_85]]
+// CHECK: %[[VAL_88:.*]] = add i32 %[[VAL_87]], 1
+// CHECK: br label %[[VAL_89:.*]]
+// CHECK: omp_loop.header: ; preds = %[[VAL_90:.*]], %[[VAL_82]]
+// CHECK: %[[VAL_91:.*]] = phi i32 [ 0, %[[VAL_82]] ], [ %[[VAL_92:.*]], %[[VAL_90]] ]
+// CHECK: br label %[[VAL_93:.*]]
+// CHECK: omp_loop.cond: ; preds = %[[VAL_89]]
+// CHECK: %[[VAL_94:.*]] = icmp ult i32 %[[VAL_91]], %[[VAL_88]]
+// CHECK: br i1 %[[VAL_94]], label %[[VAL_95:.*]], label %[[VAL_96:.*]]
+// CHECK: omp_loop.body: ; preds = %[[VAL_93]]
+// CHECK: %[[VAL_97:.*]] = add i32 %[[VAL_91]], %[[VAL_85]]
+// CHECK: %[[VAL_98:.*]] = mul i32 %[[VAL_97]], %[[VAL_67]]
+// CHECK: %[[VAL_99:.*]] = add i32 %[[VAL_98]], %[[VAL_72]]
+// CHECK: br label %[[VAL_100:.*]]
+// CHECK: omp.loop_nest.region: ; preds = %[[VAL_95]]
+// CHECK: %[[VAL_101:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: %[[VAL_102:.*]] = call i32 @__kmpc_cancellationpoint(ptr @1, i32 %[[VAL_101]], i32 2)
+// CHECK: %[[VAL_103:.*]] = icmp eq i32 %[[VAL_102]], 0
+// CHECK: br i1 %[[VAL_103]], label %[[VAL_104:.*]], label %[[VAL_105:.*]]
+// CHECK: omp.loop_nest.region.split: ; preds = %[[VAL_100]]
+// CHECK: br label %[[VAL_106:.*]]
+// CHECK: omp.region.cont1: ; preds = %[[VAL_104]]
+// CHECK: br label %[[VAL_90]]
+// CHECK: omp_loop.inc: ; preds = %[[VAL_106]]
+// CHECK: %[[VAL_92]] = add nuw i32 %[[VAL_91]], 1
+// CHECK: br label %[[VAL_89]]
+// CHECK: omp_loop.exit: ; preds = %[[VAL_105]], %[[VAL_93]]
+// CHECK: call void @__kmpc_for_static_fini(ptr @1, i32 %[[VAL_84]])
+// CHECK: %[[VAL_107:.*]] = call i32 @__kmpc_global_thread_num(ptr @1)
+// CHECK: call void @__kmpc_barrier(ptr @2, i32 %[[VAL_107]])
+// CHECK: br label %[[VAL_108:.*]]
+// CHECK: omp_loop.after: ; preds = %[[VAL_96]]
+// CHECK: br label %[[VAL_109:.*]]
+// CHECK: omp.region.cont: ; preds = %[[VAL_108]]
+// CHECK: ret void
+// CHECK: omp.loop_nest.region.cncl: ; preds = %[[VAL_100]]
+// CHECK: br label %[[VAL_96]]
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 5f9eb9cfc9a37..a67c61f23631f 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -43,12 +43,16 @@ llvm.func @cancel_taskgroup() {
// -----
-llvm.func @cancellation_point() {
- // expected-error at below {{LLVM Translation failed for operation: omp.parallel}}
- omp.parallel {
- // expected-error at below {{not yet implemented: omp.cancellation_point}}
- // expected-error at below {{LLVM Translation failed for operation: omp.cancellation_point}}
- omp.cancellation_point cancellation_construct_type(parallel)
+llvm.func @cancellation_point_taskgroup() {
+ // expected-error at below {{LLVM Translation failed for operation: omp.taskgroup}}
+ omp.taskgroup {
+ // expected-error at below {{LLVM Translation failed for operation: omp.task}}
+ omp.task {
+ // expected-error at below {{not yet implemented: Unhandled clause cancel directive construct type not yet supported in omp.cancellation_point operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.cancellation_point}}
+ omp.cancellation_point cancellation_construct_type(taskgroup)
+ omp.terminator
+ }
omp.terminator
}
llvm.return
More information about the Mlir-commits
mailing list