[llvm-branch-commits] [mlir] [MLIR][OpenMP] Explicit tagging of combined constructs (PR #198782)
Sergio Afonso via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Jun 16 05:52:57 PDT 2026
https://github.com/skatrak updated https://github.com/llvm/llvm-project/pull/198782
>From baacf10e84de0aae1c14085b391b968ba7afc82e Mon Sep 17 00:00:00 2001
From: Sergio Afonso <Sergio.AfonsoFumero at amd.com>
Date: Mon, 18 May 2026 13:27:14 +0100
Subject: [PATCH] [MLIR][OpenMP] Explicit tagging of combined constructs
Combined OpenMP constructs, such as `parallel do`, which represent
nests of constructs where each one contains a single other construct
without any other directives or statements in between, are currently not
marked in any way in the MLIR representation.
This works because they don't usually require any specific handling
other than what would be done for the included operations. However, the
handling of `target` regions needs to know whether it was part of a
combined construct in order to properly optimize for the SPMD case and
detect when certain clauses must be inconditionally evaluated in the
host.
So far, this has been achieved by having some MLIR pattern-matching
logic to infer whether a nest of operations could have potentially been
produced for a combined construct. This approach is error prone,
computationally expensive and it can't really work in the general case.
On the other hand, a compiler frontend can easily tell the difference
and tag MLIR operations accordingly.
This patch extends the `ComposableOpInterface` of the OpenMP dialect to
handle a new `omp.combined` attribute that must be set for all leafs
(except for the innermost one) on a combined construct. Verification
logic is added for this interface, which is added to all operations that
can be used as part of a combined construct, and the previous
`target`-related pattern-matching logic is removed.
This patch has to be followed up with Flang lowering changes.
---
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 62 ++--
.../Dialect/OpenMP/OpenMPOpsInterfaces.td | 45 ++-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 271 +++++++++---------
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 6 +-
.../OpenMPToLLVM/convert-to-llvmir.mlir | 4 +-
.../Dialect/OpenMP/invalid-interface.mlir | 106 +++++++
mlir/test/Dialect/OpenMP/invalid.mlir | 179 +++++++-----
mlir/test/Dialect/OpenMP/ops.mlir | 66 ++---
mlir/test/Dialect/OpenMP/stack-to-shared.mlir | 4 +-
.../LLVMIR/allocatable_gpu_reduction.mlir | 4 +-
.../allocatable_gpu_reduction_teams.mlir | 4 +-
.../LLVMIR/omptarget-debug-loop-loc.mlir | 4 +-
.../omptarget-memcpy-align-metadata.mlir | 4 +-
.../omptarget-multi-block-reduction.mlir | 4 +-
.../LLVMIR/omptarget-multi-reduction.mlir | 4 +-
.../Target/LLVMIR/omptarget-private-llvm.mlir | 4 +-
...distribute-reduction-array-descriptor.mlir | 8 +-
.../LLVMIR/openmp-data-target-device.mlir | 4 +-
.../openmp-nested-task-target-parallel.mlir | 4 +-
.../LLVMIR/openmp-target-generic-spmd.mlir | 8 +-
.../LLVMIR/openmp-target-launch-device.mlir | 4 +-
.../Target/LLVMIR/openmp-target-spmd.mlir | 8 +-
.../LLVMIR/openmp-taskloop-bounds-cast.mlir | 2 +-
.../Target/LLVMIR/openmp-taskloop-cancel.mlir | 6 +-
.../openmp-taskloop-cancellation-point.mlir | 4 +-
.../LLVMIR/openmp-taskloop-collapse.mlir | 12 +-
.../openmp-taskloop-context-alloca.mlir | 2 +-
.../Target/LLVMIR/openmp-taskloop-final.mlir | 2 +-
.../LLVMIR/openmp-taskloop-grainsize.mlir | 2 +-
.../Target/LLVMIR/openmp-taskloop-if.mlir | 2 +-
.../LLVMIR/openmp-taskloop-local-bounds.mlir | 4 +-
.../LLVMIR/openmp-taskloop-mergeable.mlir | 2 +-
.../openmp-taskloop-no-context-struct.mlir | 2 +-
.../LLVMIR/openmp-taskloop-nogroup.mlir | 2 +-
.../LLVMIR/openmp-taskloop-num_tasks.mlir | 2 +-
.../LLVMIR/openmp-taskloop-outer-bounds.mlir | 2 +-
.../LLVMIR/openmp-taskloop-priority.mlir | 2 +-
.../Target/LLVMIR/openmp-taskloop-untied.mlir | 4 +-
mlir/test/Target/LLVMIR/openmp-taskloop.mlir | 2 +-
.../openmp-teams-clauses-trunc-ext.mlir | 48 ++--
mlir/test/Target/LLVMIR/openmp-todo.mlir | 6 +-
41 files changed, 555 insertions(+), 360 deletions(-)
create mode 100644 mlir/test/Dialect/OpenMP/invalid-interface.mlir
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index c0c720fc610c6..33e918a068a77 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -238,7 +238,8 @@ def TerminatorOp : OpenMP_Op<"terminator", [Terminator, Pure]> {
// 2.7 teams Construct
//===----------------------------------------------------------------------===//
def TeamsOp : OpenMP_Op<"teams", traits = [
- AttrSizedOperandSegments, RecursiveMemoryEffects, OutlineableOpenMPOpInterface
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>,
+ RecursiveMemoryEffects, OutlineableOpenMPOpInterface
], clauses = [
OpenMP_AllocateClause, OpenMP_DynGroupprivateClause, OpenMP_IfClause,
OpenMP_NumTeamsClause, OpenMP_PrivateClause, OpenMP_ReductionClause,
@@ -294,7 +295,7 @@ def SectionOp : OpenMP_Op<"section", traits = [
}
def SectionsOp : OpenMP_Op<"sections", traits = [
- AttrSizedOperandSegments
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>
], clauses = [
OpenMP_AllocateClause, OpenMP_NowaitClause, OpenMP_PrivateClause,
OpenMP_ReductionClause
@@ -332,7 +333,7 @@ def SectionsOp : OpenMP_Op<"sections", traits = [
//===----------------------------------------------------------------------===//
def SingleOp : OpenMP_Op<"single", traits = [
- AttrSizedOperandSegments
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>
], clauses = [
OpenMP_AllocateClause, OpenMP_CopyprivateClause, OpenMP_NowaitClause,
OpenMP_PrivateClause
@@ -613,7 +614,7 @@ def FuseOp
//===----------------------------------------------------------------------===//
def WorkshareOp : OpenMP_Op<"workshare", traits = [
- RecursiveMemoryEffects,
+ DeclareOpInterfaceMethods<ComposableOpInterface>, RecursiveMemoryEffects
], clauses = [
OpenMP_NowaitClause,
], singleRegion = true> {
@@ -632,6 +633,7 @@ def WorkshareOp : OpenMP_Op<"workshare", traits = [
let builders = [
OpBuilder<(ins CArg<"const WorkshareOperands &">:$clauses)>
];
+ let hasVerifier = 1;
}
def WorkshareLoopWrapperOp : OpenMP_Op<"workshare.loop_wrapper", traits = [
@@ -959,18 +961,16 @@ def DistributeOp : OpenMP_Op<"distribute", traits = [
// 2.10.1 task Construct
//===----------------------------------------------------------------------===//
-def TaskOp
- : OpenMP_Op<"task",
- traits = [AttrSizedOperandSegments, AutomaticAllocationScope,
- OutlineableOpenMPOpInterface],
- clauses = [
- // TODO: Complete clause list (detach).
- OpenMP_AffinityClause, OpenMP_AllocateClause,
- OpenMP_DependClause, OpenMP_FinalClause, OpenMP_IfClause,
- OpenMP_InReductionClause, OpenMP_MergeableClause,
- OpenMP_PriorityClause, OpenMP_PrivateClause,
- OpenMP_UntiedClause, OpenMP_DetachClause],
- singleRegion = true> {
+def TaskOp : OpenMP_Op<"task", traits = [
+ AttrSizedOperandSegments, AutomaticAllocationScope,
+ DeclareOpInterfaceMethods<ComposableOpInterface>,
+ OutlineableOpenMPOpInterface
+ ], clauses = [
+ OpenMP_AffinityClause, OpenMP_AllocateClause, OpenMP_DependClause,
+ OpenMP_FinalClause, OpenMP_IfClause, OpenMP_InReductionClause,
+ OpenMP_MergeableClause, OpenMP_PriorityClause, OpenMP_PrivateClause,
+ OpenMP_UntiedClause, OpenMP_DetachClause
+ ], singleRegion = true> {
let summary = "task construct";
let description = [{
The task construct defines an explicit task.
@@ -1009,6 +1009,7 @@ def TaskOp
def TaskloopContextOp : OpenMP_Op<"taskloop.context", traits = [
AttrSizedOperandSegments, AutomaticAllocationScope,
RecursiveMemoryEffects, SingleBlock,
+ DeclareOpInterfaceMethods<ComposableOpInterface>,
DeclareOpInterfaceMethods<OutlineableOpenMPOpInterface>
], clauses = [
OpenMP_AllocateClause, OpenMP_FinalClause, OpenMP_GrainsizeClause,
@@ -1420,7 +1421,7 @@ def MapInfoOp : OpenMP_Op<"map.info", [AttrSizedOperandSegments]> {
//===---------------------------------------------------------------------===//
def TargetDataOp: OpenMP_Op<"target_data", traits = [
- AttrSizedOperandSegments
+ AttrSizedOperandSegments, DeclareOpInterfaceMethods<ComposableOpInterface>
], clauses = [
OpenMP_DeviceClause, OpenMP_IfClause, OpenMP_MapClause,
OpenMP_UseDeviceAddrClause, OpenMP_UseDevicePtrClause
@@ -1582,7 +1583,8 @@ def TargetUpdateOp: OpenMP_Op<"target_update", traits = [
//===----------------------------------------------------------------------===//
def TargetOp : OpenMP_Op<"target", traits = [
- AttrSizedOperandSegments, BlockArgOpenMPOpInterface, IsolatedFromAbove,
+ AttrSizedOperandSegments, BlockArgOpenMPOpInterface,
+ DeclareOpInterfaceMethods<ComposableOpInterface>, IsolatedFromAbove,
OutlineableOpenMPOpInterface
], clauses = [
// TODO: Complete clause list (defaultmap, uses_allocators).
@@ -1640,18 +1642,6 @@ def TargetOp : OpenMP_Op<"target", traits = [
return getMapVars()[mapInfoOpIdx];
}
- /// Returns the innermost OpenMP dialect operation captured by this target
- /// construct. For an operation to be detected as captured, it must be
- /// inside a (possibly multi-level) nest of OpenMP dialect operation's
- /// regions where none of these levels contain other operations considered
- /// not-allowed for these purposes (i.e. only terminator operations are
- /// allowed from the OpenMP dialect, and other dialect's operations are
- /// allowed as long as they don't have a memory write effect).
- ///
- /// If there are omp.loop_nest operations in the sequence of nested
- /// operations, the top level one will be the one captured.
- Operation *getInnermostCapturedOmpOp();
-
/// Returns whether this kernel requires host evaluation of loop trip count.
bool hasHostEvalTripCount();
}] # clausesExtraClassDeclaration;
@@ -1676,7 +1666,9 @@ def TargetOp : OpenMP_Op<"target", traits = [
//===----------------------------------------------------------------------===//
// 2.16 master Construct
//===----------------------------------------------------------------------===//
-def MasterOp : OpenMP_Op<"master", singleRegion = true> {
+def MasterOp : OpenMP_Op<"master", traits = [
+ DeclareOpInterfaceMethods<ComposableOpInterface>
+ ], singleRegion = true> {
let summary = "master construct";
let description = [{
The master construct specifies a structured block that is executed by
@@ -2273,7 +2265,9 @@ def DeclareReductionOp : OpenMP_Op<"declare_reduction", [IsolatedFromAbove,
//===----------------------------------------------------------------------===//
// [Spec 5.2] 10.5 masked Construct
//===----------------------------------------------------------------------===//
-def MaskedOp : OpenMP_Op<"masked", clauses = [
+def MaskedOp : OpenMP_Op<"masked", traits = [
+ DeclareOpInterfaceMethods<ComposableOpInterface>
+ ], clauses = [
OpenMP_FilterClause
], singleRegion = 1> {
let summary = "masked construct";
@@ -2484,7 +2478,9 @@ def FreeSharedMemOp : OpenMP_Op<"free_shared_mem", traits = [
// workdistribute Construct
//===----------------------------------------------------------------------===//
-def WorkdistributeOp : OpenMP_Op<"workdistribute"> {
+def WorkdistributeOp : OpenMP_Op<"workdistribute", traits = [
+ DeclareOpInterfaceMethods<ComposableOpInterface>
+ ]> {
let summary = "workdistribute directive";
let description = [{
workdistribute divides execution of the enclosed structured block into
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
index fd500134e10f9..51f925b17f47e 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOpsInterfaces.td
@@ -281,8 +281,9 @@ def LoopWrapperInterface : OpInterface<"LoopWrapperInterface"> {
def ComposableOpInterface : OpInterface<"ComposableOpInterface"> {
let description = [{
- OpenMP operations that can represent a single leaf of a composite OpenMP
- construct.
+ OpenMP operations that can represent a single leaf of a compound OpenMP
+ construct, or one leaf of a combined construct or equivalent immediate
+ nesting of constructs.
}];
let cppNamespace = "::mlir::omp";
@@ -311,8 +312,48 @@ def ComposableOpInterface : OpInterface<"ComposableOpInterface"> {
else
$_op->removeDiscardableAttr("omp.composite");
}]
+ >,
+ InterfaceMethod<
+ /*description=*/[{
+ Check whether the operation is representing a non-innermost child leaf
+ of a combined OpenMP construct or an equivalent immediate nesting of
+ constructs.
+ }],
+ /*retTy=*/"bool",
+ /*methodName=*/"isCombined",
+ (ins ), [{}], [{
+ return $_op->hasAttr("omp.combined");
+ }]
+ >,
+ InterfaceMethod<
+ /*description=*/[{
+ Mark the operation as a non-innermost child leaf of an OpenMP combined
+ construct or an equivalent immediate nesting of constructs.
+ }],
+ /*retTy=*/"void",
+ /*methodName=*/"setCombined",
+ (ins "bool":$val), [{}], [{
+ if (val)
+ $_op->setDiscardableAttr("omp.combined", mlir::UnitAttr::get($_op->getContext()));
+ else
+ $_op->removeDiscardableAttr("omp.combined");
+ }]
>
];
+
+ let extraClassDeclaration = [{
+ /// Follows the combined-composite chain of nested operations and returns
+ /// the deepest-nested one.
+ Operation *findCapturedOp();
+
+ /// Interface verifier implementation.
+ llvm::LogicalResult verifyImpl();
+ }];
+
+ let verify = [{
+ return ::llvm::cast<::mlir::omp::ComposableOpInterface>($_op).verifyImpl();
+ }];
+ let verifyWithRegions = 1;
}
def DeclareTargetInterface : OpInterface<"DeclareTargetInterface"> {
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 06028aac0d786..9fc47bcb5d894 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2605,7 +2605,8 @@ bool TargetOp::hasHostEvalTripCount() {
// If it represents a `target teams distribute` construct, also evaluate the
// `distribute` trip count on the host.
- Operation *capturedOp = getInnermostCapturedOmpOp();
+ Operation *capturedOp =
+ cast<ComposableOpInterface>(getOperation()).findCapturedOp();
if (auto loopNestOp = dyn_cast_if_present<LoopNestOp>(capturedOp)) {
SmallVector<LoopWrapperInterface> loopWrappers;
loopNestOp.gatherWrappers(loopWrappers);
@@ -2631,6 +2632,9 @@ bool TargetOp::hasHostEvalTripCount() {
}
LogicalResult TargetOp::verify() {
+ if (getKernelType() == TargetExecMode::bare && !isCombined())
+ return emitOpError() << "bare kernel requires 'omp.combined'";
+
if (failed(verifyDependVarList(*this, getDependKinds(), getDependVars(),
getDependIteratedKinds(),
getDependIterated())))
@@ -2660,21 +2664,17 @@ LogicalResult TargetOp::verifyRegions() {
if (numNestedTeams > 1)
return emitError("target containing multiple 'omp.teams' nested ops");
- if (numNestedTeams == 0 && getKernelType() == TargetExecMode::bare)
+ if (getKernelType() == TargetExecMode::bare && numNestedTeams == 0)
return emitOpError()
<< "bare kernel must contain a nested 'omp.teams' operation";
- if (getKernelType() == TargetExecMode::spmd ||
- getKernelType() == TargetExecMode::spmd_no_loop) {
- bool containsLoop = getRegion()
- .walk<WalkOrder::PreOrder>([](LoopNestOp loopOp) {
- return WalkResult::interrupt();
- })
- .wasInterrupted();
- if (!containsLoop)
- return emitOpError()
- << "SPMD kernel must contain a nested 'omp.loop_nest' operation";
- }
+ Operation *capturedOp =
+ cast<ComposableOpInterface>(getOperation()).findCapturedOp();
+ if ((getKernelType() == TargetExecMode::spmd ||
+ getKernelType() == TargetExecMode::spmd_no_loop) &&
+ !isa_and_present<LoopNestOp>(capturedOp))
+ return emitOpError()
+ << "SPMD kernel must capture an 'omp.loop_nest' operation";
bool isTargetDevice = false;
if (auto offloadMod = (*this)->getParentOfType<OffloadModuleInterface>())
@@ -2685,9 +2685,6 @@ LogicalResult TargetOp::verifyRegions() {
llvm::ArrayRef<BlockArgument> hostEvalBlockArgs =
cast<BlockArgOpenMPOpInterface>(getOperation()).getHostEvalBlockArgs();
- if (!hostEvalBlockArgs.empty() && isTargetDevice)
- emitOpError() << "'host_eval' is only supported during host compilation";
-
bool hostEvalTripCount = hasHostEvalTripCount();
for (Value hostEvalArg : hostEvalBlockArgs) {
for (Operation *user : hostEvalArg.getUsers()) {
@@ -2727,121 +2724,19 @@ LogicalResult TargetOp::verifyRegions() {
}
if (hostEvalTripCount && !isTargetDevice) {
- if (auto loopOp = dyn_cast<LoopNestOp>(getInnermostCapturedOmpOp())) {
- for (auto arg : llvm::concat<Value>(loopOp.getLoopLowerBounds(),
- loopOp.getLoopUpperBounds(),
- loopOp.getLoopSteps())) {
- if (!llvm::is_contained(hostEvalBlockArgs, arg))
- return emitOpError() << "nested 'omp.loop_nest' bounds expected to "
- "be host-evaluated";
- }
+ auto loopOp = cast<LoopNestOp>(capturedOp);
+ for (auto arg : llvm::concat<Value>(loopOp.getLoopLowerBounds(),
+ loopOp.getLoopUpperBounds(),
+ loopOp.getLoopSteps())) {
+ if (!llvm::is_contained(hostEvalBlockArgs, arg))
+ return emitOpError() << "nested 'omp.loop_nest' bounds expected to "
+ "be host-evaluated";
}
}
return success();
}
-static Operation *
-findCapturedOmpOp(Operation *rootOp, bool checkSingleMandatoryExec,
- llvm::function_ref<bool(Operation *)> siblingAllowedFn) {
- assert(rootOp && "expected valid operation");
-
- Dialect *ompDialect = rootOp->getDialect();
- Operation *capturedOp = nullptr;
- DominanceInfo domInfo;
-
- // Process in pre-order to check operations from outermost to innermost,
- // ensuring we only enter the region of an operation if it meets the criteria
- // for being captured. We stop the exploration of nested operations as soon as
- // we process a region holding no operations to be captured.
- rootOp->walk<WalkOrder::PreOrder>([&](Operation *op) {
- if (op == rootOp)
- return WalkResult::advance();
-
- // Ignore operations of other dialects or omp operations with no regions,
- // because these will only be checked if they are siblings of an omp
- // operation that can potentially be captured.
- bool isOmpDialect = op->getDialect() == ompDialect;
- bool hasRegions = op->getNumRegions() > 0;
- if (!isOmpDialect || !hasRegions)
- return WalkResult::skip();
-
- // This operation cannot be captured if it can be executed more than once
- // (i.e. its block's successors can reach it) or if it's not guaranteed to
- // be executed before all exits of the region (i.e. it doesn't dominate all
- // blocks with no successors reachable from the entry block).
- if (checkSingleMandatoryExec) {
- Region *parentRegion = op->getParentRegion();
- Block *parentBlock = op->getBlock();
-
- for (Block *successor : parentBlock->getSuccessors())
- if (successor->isReachable(parentBlock))
- return WalkResult::interrupt();
-
- for (Block &block : *parentRegion)
- if (domInfo.isReachableFromEntry(&block) && block.hasNoSuccessors() &&
- !domInfo.dominates(parentBlock, &block))
- return WalkResult::interrupt();
- }
-
- // Don't capture this op if it has a not-allowed sibling, and stop recursing
- // into nested operations.
- for (Operation &sibling : op->getParentRegion()->getOps())
- if (&sibling != op && !siblingAllowedFn(&sibling))
- return WalkResult::interrupt();
-
- // Don't continue capturing nested operations if we reach an omp.loop_nest.
- // Otherwise, process the contents of this operation.
- capturedOp = op;
- return llvm::isa<LoopNestOp>(op) ? WalkResult::interrupt()
- : WalkResult::advance();
- });
-
- return capturedOp;
-}
-
-Operation *TargetOp::getInnermostCapturedOmpOp() {
- // If this is an SPMD kernel, then just attempt to find the first available
- // omp.loop_nest. If the kernel type has been properly set, that must be the
- // captured loop.
- if (getKernelType() == TargetExecMode::spmd ||
- getKernelType() == TargetExecMode::spmd_no_loop) {
- Operation *spmdLoop = nullptr;
- getRegion().walk<WalkOrder::PreOrder>([&spmdLoop](LoopNestOp loopOp) {
- spmdLoop = loopOp.getOperation();
- return WalkResult::interrupt();
- });
- assert(spmdLoop && "SPMD target regions must contain a loop");
- return spmdLoop;
- }
-
- auto *ompDialect = getContext()->getLoadedDialect<omp::OpenMPDialect>();
-
- // Only allow OpenMP terminators and non-OpenMP ops that either have known
- // memory effects excluding memory write effects, or are pure.
- return findCapturedOmpOp(
- *this, /*checkSingleMandatoryExec=*/true, [&](Operation *sibling) {
- if (!sibling)
- return false;
-
- if (ompDialect == sibling->getDialect())
- return sibling->hasTrait<OpTrait::IsTerminator>();
-
- if (auto memOp = dyn_cast<MemoryEffectOpInterface>(sibling)) {
- SmallVector<SideEffects::EffectInstance<MemoryEffects::Effect>, 4>
- effects;
- memOp.getEffects(effects);
- return !llvm::any_of(
- effects, [&](MemoryEffects::EffectInstance &effect) {
- return isa<MemoryEffects::Write>(effect.getEffect()) &&
- isa<SideEffects::AutomaticAllocationScopeResource>(
- effect.getResource());
- });
- }
- return isPure(sibling);
- });
-}
-
//===----------------------------------------------------------------------===//
// ParallelOp
//===----------------------------------------------------------------------===//
@@ -3068,6 +2963,9 @@ void SectionsOp::build(OpBuilder &builder, OperationState &state,
}
LogicalResult SectionsOp::verify() {
+ if (isCombined())
+ return emitOpError() << "cannot be a non-innermost combined construct leaf";
+
if (getAllocateVars().size() != getAllocatorVars().size())
return emitError(
"expected equal sizes for allocate and allocator variables");
@@ -3149,6 +3047,13 @@ void WorkshareOp::build(OpBuilder &builder, OperationState &state,
WorkshareOp::build(builder, state, clauses.nowait);
}
+LogicalResult WorkshareOp::verify() {
+ if (isCombined())
+ return emitOpError() << "cannot be a non-innermost combined construct leaf";
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// WorkshareLoopWrapperOp
//===----------------------------------------------------------------------===//
@@ -3194,6 +3099,98 @@ LogicalResult LoopWrapperInterface::verifyImpl() {
return success();
}
+//===----------------------------------------------------------------------===//
+// ComposableOpInterface
+//===----------------------------------------------------------------------===//
+
+Operation *ComposableOpInterface::findCapturedOp() {
+ Operation *op = this->getOperation();
+
+ // Handle the composite case by returning the wrapped omp.loop_nest.
+ if (auto wrapperOp = dyn_cast<LoopWrapperInterface>(op))
+ return wrapperOp.getWrappedLoop();
+
+ // Do not look further if this op is not combined with any of its children.
+ // Need to check for composite for the omp.parallel case, which is not a loop
+ // wrapper itself.
+ if (!isCombined() && !isComposite())
+ return op;
+
+ Region ®ion = op->getRegion(0);
+ for (Operation &nestedOp : region.getOps()) {
+ if (auto wrapperOp = dyn_cast<LoopWrapperInterface>(&nestedOp))
+ return wrapperOp.getWrappedLoop();
+
+ if (auto composableOp = dyn_cast<ComposableOpInterface>(&nestedOp))
+ return composableOp.findCapturedOp();
+ }
+
+ // This can only be reached if the op has an omp.combined attribute but the
+ // corresponding nested composable op has been deleted. In that case, it's
+ // correct to return this operation.
+ return op;
+}
+
+LogicalResult ComposableOpInterface::verifyImpl() {
+ Operation *op = this->getOperation();
+
+ if (op->getNumRegions() != 1)
+ return emitOpError() << "composable ops must have a single region";
+
+ if (isComposite() && !isa<LoopWrapperInterface, ParallelOp>(op))
+ return emitOpError() << "non-loop wrapper cannot be composite";
+
+ // If combined, must have exactly one eligible nested op (composable or loop
+ // wrapper).
+ if (isCombined()) {
+ Operation *nestedOp = nullptr;
+ auto count = llvm::count_if(
+ op->getRegion(0).getOps(), [&nestedOp](mlir::Operation &op) {
+ if (isa<ComposableOpInterface, LoopWrapperInterface>(op)) {
+ nestedOp = &op;
+ return true;
+ }
+ return false;
+ });
+
+ // Make an exception for ops marked as omp.combined with no eligible nested
+ // ops: this situation should be disallowed, but it can be reached if an
+ // MLIR optimization pass find that the child operation has no side effects
+ // (many ComposableOpInterface ops have RecursiveMemoryEffects), so it gets
+ // deleted without updating the parent's attribute.
+ //
+ // Since there's a well defined way of handling that situation (treat it as
+ // non-combined), we relax the requirement here. Ensuring the parent is
+ // updated every time a pass that can potentially remove a child composable
+ // op runs is less preferable as a solution.
+ if (count == 0)
+ return success();
+
+ if (count > 1)
+ return emitOpError()
+ << "multiple eligible child ops found in combined op";
+
+ // This operation cannot be combined if its captured nested op can be
+ // executed more than once (i.e. its block's successors can reach it) or if
+ // it's not guaranteed to be executed before all exits of the region (i.e.
+ // it doesn't dominate all blocks with no successors reachable from the
+ // entry block).
+ DominanceInfo domInfo;
+ Block *parentBlock = nestedOp->getBlock();
+
+ for (Block *successor : parentBlock->getSuccessors())
+ if (successor->isReachable(parentBlock))
+ return emitOpError() << "nested combined child op is part of a loop";
+
+ for (Block &block : op->getRegion(0))
+ if (domInfo.isReachableFromEntry(&block) && block.hasNoSuccessors() &&
+ !domInfo.dominates(parentBlock, &block))
+ return emitOpError()
+ << "nested combined child op doesn't unconditionally execute";
+ }
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// LoopOp
//===----------------------------------------------------------------------===//
@@ -3617,6 +3614,7 @@ void TaskloopContextOp::build(OpBuilder &builder, OperationState &state,
clauses.privateNeedsBarrier, clauses.reductionMod, clauses.reductionVars,
makeDenseBoolArrayAttr(ctx, clauses.reductionByref),
makeArrayAttr(ctx, clauses.reductionSyms), clauses.untied);
+ state.addAttribute("omp.combined", UnitAttr::get(ctx));
}
TaskloopWrapperOp TaskloopContextOp::getLoopOp() {
@@ -3656,24 +3654,26 @@ LogicalResult TaskloopContextOp::verify() {
"may not appear on the same taskloop directive");
}
+ // Without this restriction, any compound construct including `taskloop` would
+ // fail to correctly identify the whole chain of operations (see
+ // ComposableOpInterface::findCapturedOp()), as well as failing to do so even
+ // for standalone `taskloop` constructs.
+ if (!isCombined())
+ return emitOpError("must always contain the 'omp.combined' attribute");
+
return success();
}
LogicalResult TaskloopContextOp::verifyRegions() {
Region ®ion = getRegion();
- if (region.empty())
- return emitOpError() << "expected non-empty region";
-
- auto count = llvm::count_if(region.front(), [](mlir::Operation &op) {
+ auto loopWrapperIt = llvm::find_if(region.front(), [](mlir::Operation &op) {
return isa<TaskloopWrapperOp>(op);
});
- if (count != 1)
+ if (loopWrapperIt == region.front().end())
return emitOpError()
- << "expected exactly 1 TaskloopWrapperOp directly nested in "
- "the region, but "
- << count << " were found";
- TaskloopWrapperOp loopWrapperOp = getLoopOp();
+ << "expected a TaskloopWrapperOp directly nested in the region";
+ auto loopWrapperOp = cast<TaskloopWrapperOp>(*loopWrapperIt);
auto loopNestOp = dyn_cast<LoopNestOp>(loopWrapperOp.getWrappedLoop());
// This will fail the verifier for TaskloopWrapperOp and print an error
// message there.
@@ -4980,6 +4980,9 @@ LogicalResult FreeSharedMemOp::verify() {
//===----------------------------------------------------------------------===//
LogicalResult WorkdistributeOp::verify() {
+ if (isCombined())
+ return emitOpError() << "cannot be a non-innermost combined construct leaf";
+
// Check that region exists and is not empty
Region ®ion = getRegion();
if (region.empty())
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index e98265c6787de..f53928a31b9a0 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -3876,7 +3876,8 @@ convertOmpWsloop(Operation &opInst, llvm::IRBuilderBase &builder,
omp::TargetOp targetOp = wsloopOp->getParentOfType<mlir::omp::TargetOp>();
if (targetOp &&
targetOp.getKernelType() == omp::TargetExecMode::spmd_no_loop) {
- Operation *targetCapturedOp = targetOp.getInnermostCapturedOmpOp();
+ Operation *targetCapturedOp =
+ cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
// We need this check because, without it, noLoopMode would be set to true
// for every omp.wsloop nested inside a no-loop SPMD target region, even if
// that loop is not the top-level SPMD one.
@@ -8026,7 +8027,8 @@ convertOmpTarget(Operation &opInst, llvm::IRBuilderBase &builder,
llvm::OpenMPIRBuilder::TargetKernelRuntimeAttrs runtimeAttrs;
llvm::OpenMPIRBuilder::TargetKernelDefaultAttrs defaultAttrs;
- Operation *targetCapturedOp = targetOp.getInnermostCapturedOmpOp();
+ Operation *targetCapturedOp =
+ cast<omp::ComposableOpInterface>(*targetOp).findCapturedOp();
initTargetDefaultAttrs(targetOp, targetCapturedOp, defaultAttrs,
isTargetDevice, isGPU);
diff --git a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
index 38ae1e82e971d..5be437b662b20 100644
--- a/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
+++ b/mlir/test/Conversion/OpenMPToLLVM/convert-to-llvmir.mlir
@@ -601,9 +601,9 @@ func.func @omp_taskloop(%arg0: index, %arg1 : memref<i32>) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
diff --git a/mlir/test/Dialect/OpenMP/invalid-interface.mlir b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
new file mode 100644
index 0000000000000..6fe64b0839e66
--- /dev/null
+++ b/mlir/test/Dialect/OpenMP/invalid-interface.mlir
@@ -0,0 +1,106 @@
+// RUN: mlir-opt -split-input-file -verify-diagnostics %s
+
+omp.private {type = private} @x.privatizer : i32
+
+func.func @blockarg(%x : i32) {
+ // expected-error @below {{op expected at least 2 entry block argument(s)}}
+ "omp.parallel" (%x, %x) ({
+ ^bb0(%arg0 : i32):
+ omp.terminator
+ }) {operandSegmentSizes = array<i32: 0,0,0,0,2,0>,
+ private_syms = [@x.privatizer, @x.privatizer]} : (i32, i32) -> ()
+ return
+}
+
+// -----
+
+func.func @loopwrapper_multiple(%x : i32) {
+ // expected-error @below {{op loop wrapper does not contain exactly one nested op}}
+ omp.wsloop {
+ omp.simd {
+ omp.loop_nest (%iv) : i32 = (%x) to (%x) step (%x) {
+ omp.yield
+ }
+ } {omp.composite}
+ llvm.call @foo() : () -> ()
+ } {omp.composite}
+ return
+}
+
+// -----
+
+func.func @loopwrapper_invalid() {
+ // expected-error @below {{op nested in loop wrapper is not another loop wrapper or `omp.loop_nest`}}
+ omp.wsloop {
+ omp.taskyield
+ }
+ return
+}
+
+// -----
+
+func.func @composable_ineligible_composite() {
+ // expected-error @below {{op non-loop wrapper cannot be composite}}
+ omp.task {
+ omp.terminator
+ } {omp.composite}
+ return
+}
+
+// -----
+
+func.func @composable_multiple_combined() {
+ // expected-error @below {{op multiple eligible child ops found in combined op}}
+ omp.teams {
+ omp.parallel {
+ omp.terminator
+ }
+ omp.single {
+ omp.terminator
+ }
+ omp.terminator
+ } {omp.combined}
+ return
+}
+
+// -----
+
+func.func @composable_loop_combined(%x : i32) {
+ // expected-error @below {{op nested combined child op is part of a loop}}
+ omp.parallel {
+ ^bb0:
+ llvm.br ^bb1
+ ^bb1:
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%x) to (%x) step (%x) {
+ omp.yield
+ }
+ }
+ %0 = arith.constant 0 : i1
+ llvm.cond_br %0, ^bb1, ^bb2
+ ^bb2:
+ omp.terminator
+ } {omp.combined}
+ return
+}
+
+// -----
+
+func.func @composable_conditional_combined(%x : i32) {
+ // expected-error @below {{op nested combined child op doesn't unconditionally execute}}
+ omp.parallel {
+ ^bb0:
+ %0 = arith.constant 0 : i1
+ llvm.cond_br %0, ^bb1, ^bb2
+ ^bb1:
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%x) to (%x) step (%x) {
+ omp.yield
+ }
+ }
+ llvm.br ^bb2
+ ^bb2:
+ omp.terminator
+ } {omp.combined}
+ return
+}
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index bb59a5f86a553..11fa4764f8a28 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -2193,6 +2193,19 @@ func.func @omp_sections() {
// -----
+func.func @omp_sections() {
+ // expected-error @below {{op cannot be a non-innermost combined construct leaf}}
+ omp.sections {
+ omp.section {
+ omp.terminator
+ }
+ omp.terminator
+ } {omp.combined}
+ return
+}
+
+// -----
+
omp.declare_reduction @add_f32 : f32
init {
^bb0(%arg: f32):
@@ -2637,7 +2650,7 @@ func.func @scan_test_2(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2653,7 +2666,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
+ }) {omp.combined, operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
return
}
@@ -2671,7 +2684,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>, reduction_syms = [@add_f32]} : (!llvm.ptr, !llvm.ptr) -> ()
+ }) {omp.combined, operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 2>, reduction_syms = [@add_f32]} : (!llvm.ptr, !llvm.ptr) -> ()
return
}
@@ -2688,7 +2701,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>, reduction_syms = [@add_f32, @add_f32]} : (!llvm.ptr) -> ()
+ }) {omp.combined, operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 1>, reduction_syms = [@add_f32, @add_f32]} : (!llvm.ptr) -> ()
return
}
@@ -2706,7 +2719,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }) {in_reduction_syms = [@add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 2, 0, 0, 0, 0>} : (!llvm.ptr, !llvm.ptr) -> ()
+ }) {omp.combined, in_reduction_syms = [@add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 2, 0, 0, 0, 0>} : (!llvm.ptr, !llvm.ptr) -> ()
return
}
@@ -2723,7 +2736,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }) {in_reduction_syms = [@add_f32, @add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 1, 0, 0, 0, 0>} : (!llvm.ptr) -> ()
+ }) {omp.combined, in_reduction_syms = [@add_f32, @add_f32], operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 1, 0, 0, 0, 0>} : (!llvm.ptr) -> ()
return
}
@@ -2752,7 +2765,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2780,7 +2793,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2796,7 +2809,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2812,7 +2825,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
// -----
@@ -2827,7 +2840,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
// -----
@@ -2839,7 +2852,7 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
%0 = arith.constant 0 : i32
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2856,6 +2869,21 @@ func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
}
} {omp.composite}
omp.terminator
+ } {omp.combined}
+ return
+}
+
+// -----
+
+func.func @taskloop(%lb: i32, %ub: i32, %step: i32) {
+ // expected-error @below {{op must always contain the 'omp.combined' attribute}}
+ omp.taskloop.context {
+ omp.taskloop.wrapper {
+ omp.loop_nest (%iv) : i32 = (%lb) to (%ub) step (%step) {
+ omp.yield
+ }
+ }
+ omp.terminator
}
return
}
@@ -3043,21 +3071,6 @@ func.func @omp_target_multiple_teams() {
// -----
-module attributes { omp.is_target_device = true } {
-func.func @omp_target_host_eval_target_device(%x: i32) {
- // expected-error @below {{op 'host_eval' is only supported during host compilation}}
- omp.target kernel_type(generic) host_eval(%x -> %arg0 : i32) {
- omp.teams num_teams(to %arg0 : i32) {
- omp.terminator
- }
- omp.terminator
- }
- return
-}
-}
-
-// -----
-
func.func @omp_target_host_eval(%x : !llvm.ptr) {
// expected-error @below {{op host_eval argument illegal use in 'llvm.load' operation}}
omp.target kernel_type(generic) host_eval(%x -> %arg0 : !llvm.ptr) {
@@ -3082,13 +3095,11 @@ func.func @omp_target_host_eval_teams(%x : i1) {
// -----
-func.func @omp_target_host_eval_loop1(%x : i32) {
- // expected-error @below {{op host_eval argument only legal as loop bounds and steps in 'omp.loop_nest' when trip count must be evaluated in the host}}
- omp.target kernel_type(generic) host_eval(%x -> %arg0 : i32) {
- omp.wsloop {
- omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
- omp.yield
- }
+func.func @omp_target_host_eval_parallel(%x : i1) {
+ // expected-error @below {{op host_eval argument only legal as 'num_threads' in 'omp.parallel'}}
+ omp.target kernel_type(generic) host_eval(%x -> %arg0 : i1) {
+ omp.parallel if(%arg0) {
+ omp.terminator
}
omp.terminator
}
@@ -3097,31 +3108,22 @@ func.func @omp_target_host_eval_loop1(%x : i32) {
// -----
-func.func @omp_target_host_eval_loop2(%x : i32) {
+func.func @omp_target_host_eval_loop1(%x : i32) {
// expected-error @below {{op host_eval argument only legal as loop bounds and steps in 'omp.loop_nest' when trip count must be evaluated in the host}}
omp.target kernel_type(generic) host_eval(%x -> %arg0 : i32) {
- omp.teams {
- ^bb0:
- %0 = arith.constant 0 : i1
- llvm.cond_br %0, ^bb1, ^bb2
- ^bb1:
- omp.distribute {
- omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
- omp.yield
- }
+ omp.wsloop {
+ omp.loop_nest (%iv) : i32 = (%arg0) to (%arg0) step (%arg0) {
+ omp.yield
}
- llvm.br ^bb2
- ^bb2:
- omp.terminator
}
omp.terminator
- }
+ } {omp.combined}
return
}
// -----
-func.func @omp_target_host_eval_loop3(%x : i32) {
+func.func @omp_target_host_eval_loop2(%x : i32) {
// expected-error @below {{op host_eval argument only legal as loop bounds and steps in 'omp.loop_nest' when trip count must be evaluated in the host}}
omp.target kernel_type(bare) host_eval(%x -> %arg0 : i32) {
omp.teams {
@@ -3131,9 +3133,9 @@ func.func @omp_target_host_eval_loop3(%x : i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -3150,17 +3152,33 @@ func.func @omp_target_host_eval_tripcount() {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
// -----
-func.func @omp_target_bare(%x : i32) {
+func.func @omp_target_bare1(%x : i32) {
// expected-error @below {{op bare kernel must contain a nested 'omp.teams' operation}}
omp.target kernel_type(bare) {
+ omp.parallel {
+ omp.terminator
+ }
+ omp.terminator
+ } {omp.combined}
+ return
+}
+
+// -----
+
+func.func @omp_target_bare2(%x : i32) {
+ // expected-error @below {{op bare kernel requires 'omp.combined'}}
+ omp.target kernel_type(bare) {
+ omp.teams {
+ omp.terminator
+ }
omp.terminator
}
return
@@ -3169,7 +3187,7 @@ func.func @omp_target_bare(%x : i32) {
// -----
func.func @omp_target_spmd() {
- // expected-error @below {{op SPMD kernel must contain a nested 'omp.loop_nest' operation}}
+ // expected-error @below {{op SPMD kernel must capture an 'omp.loop_nest' operation}}
omp.target kernel_type(spmd) {
omp.terminator
}
@@ -3179,7 +3197,7 @@ func.func @omp_target_spmd() {
// -----
func.func @omp_target_no_loop() {
- // expected-error @below {{op SPMD kernel must contain a nested 'omp.loop_nest' operation}}
+ // expected-error @below {{op SPMD kernel must capture an 'omp.loop_nest' operation}}
omp.target kernel_type(spmd_no_loop) {
omp.terminator
}
@@ -3198,9 +3216,9 @@ func.func @omp_target_no_loop_num_teams(%x : i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -4077,10 +4095,13 @@ func.func @omp_distribute_invalid_composite(%lb: index, %ub: index, %step: index
// -----
func.func @omp_taskloop_missing_loop() -> () {
- // expected-error @below {{'omp.taskloop.context' op expected exactly 1 TaskloopWrapperOp directly nested in the region, but 0 were found}}
+ // expected-error @below {{'omp.taskloop.context' op expected a TaskloopWrapperOp directly nested in the region}}
omp.taskloop.context {
+ omp.parallel {
+ omp.terminator
+ }
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -4091,13 +4112,13 @@ func.func @omp_taskloop_missing_context(%lb: index, %ub: index, %step: index) ->
omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
omp.yield
}
- }
+ } {omp.combined}
return
}
// -----
func.func @omp_taskloop_shared_context(%lb: index, %ub: index, %step: index) -> () {
- // expected-error @below {{'omp.taskloop.context' op expected exactly 1 TaskloopWrapperOp directly nested in the region, but 2 were found}}
+ // expected-error @below {{'omp.taskloop.context' op multiple eligible child ops found in combined op}}
omp.taskloop.context {
omp.taskloop.wrapper {
omp.loop_nest (%i) : index = (%lb) to (%ub) step (%step) {
@@ -4110,7 +4131,7 @@ func.func @omp_taskloop_shared_context(%lb: index, %ub: index, %step: index) ->
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -4125,7 +4146,7 @@ func.func @omp_taskloop_missing_composite(%lb: index, %ub: index, %step: index)
}
} {omp.composite}
}
- }
+ } {omp.combined}
return
}
@@ -4138,7 +4159,7 @@ func.func @omp_taskloop_invalid_composite(%lb: index, %ub: index, %step: index)
omp.yield
}
} {omp.composite}
- }
+ } {omp.combined}
return
}
@@ -4166,7 +4187,7 @@ func.func @omp_taskloop_local_loop_bounds_from_block_arg(%arg0: index) {
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -4254,6 +4275,18 @@ func.func @missing_workshare(%idx : index) {
return
}
+// -----
+func.func @omp_workshare() {
+ // expected-error @below {{op cannot be a non-innermost combined construct leaf}}
+ omp.workshare {
+ omp.parallel {
+ omp.terminator
+ }
+ omp.terminator
+ } {omp.combined}
+ return
+}
+
// -----
// expected-error @below {{op expected terminator to be a DeclareMapperInfoOp}}
omp.declare_mapper @missing_declareMapperInfo : !llvm.struct<"mytype", (array<1024 x i32>)> {
@@ -4394,6 +4427,20 @@ func.func @invalid_workdistribute() -> () {
return
}
+// -----
+func.func @invalid_workdistribute() {
+ omp.teams {
+ // expected-error @below {{op cannot be a non-innermost combined construct leaf}}
+ omp.workdistribute {
+ omp.parallel {
+ omp.terminator
+ }
+ omp.terminator
+ } {omp.combined}
+ omp.terminator
+ } {omp.combined}
+ return
+}
// -----
// expected-error @+1 {{'omp.declare_simd' op must be nested inside a function}}
omp.declare_simd
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 0b4d2997ef6d6..7621dd87eb152 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -901,7 +901,7 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %devic
omp.terminator
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.target kernel_type(spmd) host_eval({{.*}}) {
// CHECK: omp.parallel {
// CHECK: omp.wsloop {
@@ -914,9 +914,9 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %devic
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.target kernel_type(spmd_no_loop) host_eval({{.*}}) {
// CHECK: omp.parallel {
// CHECK: omp.wsloop {
@@ -929,9 +929,9 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %devic
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2525,7 +2525,7 @@ func.func @omp_taskloop_cancel_taskgroup(%lb : index, %ub : index, %step : index
}
}
omp.terminator
- }
+ } {omp.combined}
return
}
@@ -2770,7 +2770,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
%testbool = "test.bool"() : () -> (i1)
@@ -2784,7 +2784,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context final(%{{[^)]+}}) {
omp.taskloop.context final(%testbool) {
@@ -2796,7 +2796,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context untied {
omp.taskloop.context untied {
@@ -2808,7 +2808,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context mergeable {
omp.taskloop.context mergeable {
@@ -2820,7 +2820,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
%testf32 = "test.f32"() : () -> (!llvm.ptr)
%testf32_2 = "test.f32"() : () -> (!llvm.ptr)
@@ -2834,7 +2834,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// Checking byref attribute for in_reduction
// CHECK: omp.taskloop.context in_reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
@@ -2847,7 +2847,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context reduction(byref @add_f32 %{{.+}} -> %{{.+}}, @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
omp.taskloop.context reduction(byref @add_f32 %testf32 -> %arg0, @add_f32 %testf32_2 -> %arg1 : !llvm.ptr, !llvm.ptr) {
@@ -2859,7 +2859,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// check byref attrbute for reduction
// CHECK: omp.taskloop.context reduction(byref @add_f32 %{{.+}} -> %{{.+}}, byref @add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr, !llvm.ptr) {
@@ -2872,7 +2872,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context in_reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) reduction(@add_f32 %{{.+}} -> %{{.+}} : !llvm.ptr) {
omp.taskloop.context in_reduction(@add_f32 %testf32 -> %arg0 : !llvm.ptr) reduction(@add_f32 %testf32_2 -> %arg1 : !llvm.ptr) {
@@ -2884,7 +2884,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
%testi32 = "test.i32"() : () -> (i32)
// CHECK: omp.taskloop.context priority(%{{[^:]+}}: i32) {
@@ -2897,7 +2897,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
%testmemref = "test.memref"() : () -> (memref<i32>)
// CHECK: omp.taskloop.context allocate(%{{.+}} : memref<i32> -> %{{.+}} : memref<i32>) {
@@ -2910,7 +2910,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
%testi64 = "test.i64"() : () -> (i64)
// CHECK: omp.taskloop.context grainsize(%{{[^:]+}}: i64) {
@@ -2923,7 +2923,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context num_tasks(%{{[^:]+}}: i64) {
omp.taskloop.context num_tasks(%testi64: i64) {
@@ -2935,7 +2935,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context grainsize(strict, %{{[^:]+}}: i64) {
omp.taskloop.context grainsize(strict, %testi64: i64) {
@@ -2947,7 +2947,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context num_tasks(strict, %{{[^:]+}}: i64) {
omp.taskloop.context num_tasks(strict, %testi64: i64) {
@@ -2959,7 +2959,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context nogroup {
omp.taskloop.context nogroup {
@@ -2971,7 +2971,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context {
omp.taskloop.context {
@@ -2985,7 +2985,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
} {omp.composite}
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.taskloop.context {
omp.taskloop.context {
@@ -3004,7 +3004,7 @@ func.func @omp_taskloop(%lb: i32, %ub: i32, %step: i32) -> () {
}
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: return
return
@@ -3425,9 +3425,9 @@ func.func @omp_target_host_eval(%x : i32) {
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.target kernel_type(spmd) host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
// CHECK: omp.parallel num_threads(%[[HOST_ARG]] : i32) {
@@ -3441,9 +3441,9 @@ func.func @omp_target_host_eval(%x : i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.target kernel_type(generic) host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
// CHECK: omp.parallel num_threads(%[[HOST_ARG]] : i32) {
@@ -3466,9 +3466,9 @@ func.func @omp_target_host_eval(%x : i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
// CHECK: omp.target kernel_type(spmd) host_eval(%{{.*}} -> %[[HOST_ARG:.*]] : i32) {
// CHECK: omp.teams {
@@ -3482,9 +3482,9 @@ func.func @omp_target_host_eval(%x : i32) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
return
}
diff --git a/mlir/test/Dialect/OpenMP/stack-to-shared.mlir b/mlir/test/Dialect/OpenMP/stack-to-shared.mlir
index 730a67194ea1c..972d3fe39e7bc 100644
--- a/mlir/test/Dialect/OpenMP/stack-to-shared.mlir
+++ b/mlir/test/Dialect/OpenMP/stack-to-shared.mlir
@@ -139,9 +139,9 @@ llvm.func @target_spmd() {
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
// CHECK: return
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/allocatable_gpu_reduction.mlir b/mlir/test/Target/LLVMIR/allocatable_gpu_reduction.mlir
index 23c9667c34207..3a5ccec0d0c62 100644
--- a/mlir/test/Target/LLVMIR/allocatable_gpu_reduction.mlir
+++ b/mlir/test/Target/LLVMIR/allocatable_gpu_reduction.mlir
@@ -58,9 +58,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<"dlti.alloca_memory_space" = 5 :
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/allocatable_gpu_reduction_teams.mlir b/mlir/test/Target/LLVMIR/allocatable_gpu_reduction_teams.mlir
index 5e4249ead0fd9..60c4d45f8c84e 100644
--- a/mlir/test/Target/LLVMIR/allocatable_gpu_reduction_teams.mlir
+++ b/mlir/test/Target/LLVMIR/allocatable_gpu_reduction_teams.mlir
@@ -62,9 +62,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<"dlti.alloca_memory_space" = 5 :
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/omptarget-debug-loop-loc.mlir b/mlir/test/Target/LLVMIR/omptarget-debug-loop-loc.mlir
index fecc959b59d25..08f18a1f3d23b 100644
--- a/mlir/test/Target/LLVMIR/omptarget-debug-loop-loc.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-debug-loop-loc.mlir
@@ -33,9 +33,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
} loc(#loc9)
} loc(#loc9)
omp.terminator loc(#loc9)
- } loc(#loc9)
+ } {omp.combined} loc(#loc9)
omp.terminator loc(#loc9)
- } loc(#loc15)
+ } {omp.combined} loc(#loc15)
llvm.return loc(#loc9)
} loc(#loc14)
llvm.mlir.global internal @_QFEarray() {addr_space = 0 : i32} : !llvm.array<16384 x i32> {
diff --git a/mlir/test/Target/LLVMIR/omptarget-memcpy-align-metadata.mlir b/mlir/test/Target/LLVMIR/omptarget-memcpy-align-metadata.mlir
index fc2f17d8b217d..ec1a65bf059eb 100644
--- a/mlir/test/Target/LLVMIR/omptarget-memcpy-align-metadata.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-memcpy-align-metadata.mlir
@@ -44,9 +44,9 @@ module attributes {llvm.data_layout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:6
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
llvm.mlir.global internal @_QFEa() {addr_space = 0 : i32} : !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8, array<1 x array<3 x i64>>)> {
diff --git a/mlir/test/Target/LLVMIR/omptarget-multi-block-reduction.mlir b/mlir/test/Target/LLVMIR/omptarget-multi-block-reduction.mlir
index bc1022c27f3ae..6e21000031a2d 100644
--- a/mlir/test/Target/LLVMIR/omptarget-multi-block-reduction.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-multi-block-reduction.mlir
@@ -49,9 +49,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<"dlti.alloca_memory_space" = 5 :
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/omptarget-multi-reduction.mlir b/mlir/test/Target/LLVMIR/omptarget-multi-reduction.mlir
index bd17f68e00e35..19fc5893fb946 100644
--- a/mlir/test/Target/LLVMIR/omptarget-multi-reduction.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-multi-reduction.mlir
@@ -95,9 +95,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/omptarget-private-llvm.mlir b/mlir/test/Target/LLVMIR/omptarget-private-llvm.mlir
index 3c2fc422c2987..278266bd9c94b 100644
--- a/mlir/test/Target/LLVMIR/omptarget-private-llvm.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-private-llvm.mlir
@@ -38,9 +38,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/omptarget-teams-distribute-reduction-array-descriptor.mlir b/mlir/test/Target/LLVMIR/omptarget-teams-distribute-reduction-array-descriptor.mlir
index be1f7df00f317..66d156d88a4f0 100644
--- a/mlir/test/Target/LLVMIR/omptarget-teams-distribute-reduction-array-descriptor.mlir
+++ b/mlir/test/Target/LLVMIR/omptarget-teams-distribute-reduction-array-descriptor.mlir
@@ -41,9 +41,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<"dlti.alloca_memory_space" = 5 :
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
@@ -114,9 +114,9 @@ module attributes {llvm.target_triple = "nvptx64-nvidia-cuda", omp.is_gpu = true
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/openmp-data-target-device.mlir b/mlir/test/Target/LLVMIR/openmp-data-target-device.mlir
index 28d9e99a2eccd..e42223bba760b 100644
--- a/mlir/test/Target/LLVMIR/openmp-data-target-device.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-data-target-device.mlir
@@ -48,9 +48,9 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
}
llvm.return
diff --git a/mlir/test/Target/LLVMIR/openmp-nested-task-target-parallel.mlir b/mlir/test/Target/LLVMIR/openmp-nested-task-target-parallel.mlir
index 93b70258b0cee..0025769d91959 100644
--- a/mlir/test/Target/LLVMIR/openmp-nested-task-target-parallel.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-nested-task-target-parallel.mlir
@@ -43,9 +43,9 @@ omp.task private(@_QFEc_firstprivate_i32 %3 -> %arg0 : !llvm.ptr) {
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
}
llvm.return
diff --git a/mlir/test/Target/LLVMIR/openmp-target-generic-spmd.mlir b/mlir/test/Target/LLVMIR/openmp-target-generic-spmd.mlir
index a91abc6ff8719..ffa66bf4fae70 100644
--- a/mlir/test/Target/LLVMIR/openmp-target-generic-spmd.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-target-generic-spmd.mlir
@@ -25,9 +25,9 @@ module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-a
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
@@ -77,9 +77,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/openmp-target-launch-device.mlir b/mlir/test/Target/LLVMIR/openmp-target-launch-device.mlir
index 8cc221c898c69..54329d452f94c 100644
--- a/mlir/test/Target/LLVMIR/openmp-target-launch-device.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-target-launch-device.mlir
@@ -25,7 +25,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
omp.terminator
}
omp.terminator
- }
+ } {omp.combined}
// CHECK: define weak_odr protected amdgpu_kernel void @__omp_offloading_{{.*}}_main_l{{[0-9]+}}(ptr %[[KERNEL_ARGS:.*]]) #[[ATTRS2:[0-9]+]]
// CHECK: %{{.*}} = call i32 @__kmpc_target_init(ptr @[[KERNEL2_ENV]], ptr %[[KERNEL_ARGS]])
@@ -36,7 +36,7 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
omp.terminator
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/openmp-target-spmd.mlir b/mlir/test/Target/LLVMIR/openmp-target-spmd.mlir
index 60e1076d1edd0..190cd0ee48c99 100644
--- a/mlir/test/Target/LLVMIR/openmp-target-spmd.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-target-spmd.mlir
@@ -19,9 +19,9 @@ module attributes {omp.is_target_device = false, omp.target_triples = ["amdgcn-a
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
@@ -65,9 +65,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<"dlti.alloca_memo
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-bounds-cast.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-bounds-cast.mlir
index 317616be2c564..f32dfe2dcd1dc 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-bounds-cast.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-bounds-cast.mlir
@@ -22,7 +22,7 @@ llvm.func @_QPtest_taskloop_bounds() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-cancel.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-cancel.mlir
index a254403775b5b..d4c53b6d0c322 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-cancel.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-cancel.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest(%arg0: !llvm.ptr {fir.bindc_name = "arg", llvm.noalias, llvm.
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK-LABEL: define void @_QPtest(
@@ -164,7 +164,7 @@ llvm.func @_QPtest2(%arg0: !llvm.ptr {fir.bindc_name = "arg", llvm.noalias, llvm
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
}
llvm.return
@@ -305,7 +305,7 @@ llvm.func @_QPtest3(%arg0: !llvm.ptr {fir.bindc_name = "arg", llvm.noalias, llvm
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK-LABEL: define void @_QPtest3(
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-cancellation-point.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-cancellation-point.mlir
index d8723b4a52c6b..19e1674ba788e 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-cancellation-point.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-cancellation-point.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest(%arg0: !llvm.ptr {fir.bindc_name = "arg", llvm.noalias, llvm.
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK-LABEL: define void @_QPtest(
@@ -164,7 +164,7 @@ llvm.func @_QPtest2(%arg0: !llvm.ptr {fir.bindc_name = "arg", llvm.noalias, llvm
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
}
llvm.return
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-collapse.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-collapse.mlir
index 43d95f915fcbd..aa02df28cd947 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-collapse.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-collapse.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -87,7 +87,7 @@ llvm.func @_QPtest2() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -147,7 +147,7 @@ llvm.func @_QPtest3() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -207,7 +207,7 @@ llvm.func @_QPtest4() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -269,7 +269,7 @@ llvm.func @_QPtest5() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -327,7 +327,7 @@ llvm.func @_QPtest6() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-context-alloca.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-context-alloca.mlir
index 555563cde369f..6b80698292911 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-context-alloca.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-context-alloca.mlir
@@ -28,7 +28,7 @@ llvm.func @_QPtest_taskloop(%arg0: !llvm.ptr) {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-final.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-final.mlir
index f0132670e4661..875ab566d392e 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-final.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-final.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-grainsize.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-grainsize.mlir
index 79bfe52e2d35b..de15c7e7052ae 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-grainsize.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-grainsize.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-if.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-if.mlir
index dd720dc3b6488..9ca692abafdd2 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-if.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-if.mlir
@@ -34,7 +34,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-local-bounds.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-local-bounds.mlir
index 8868423b9b194..5791be8888767 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-local-bounds.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-local-bounds.mlir
@@ -22,7 +22,7 @@ llvm.func @_QPtest_taskloop_local_constants() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -57,7 +57,7 @@ llvm.func @_QPtest_taskloop_local_derived_bound() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-mergeable.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-mergeable.mlir
index bd981307ad49e..339e7aa865319 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-mergeable.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-mergeable.mlir
@@ -31,7 +31,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-no-context-struct.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-no-context-struct.mlir
index 8cee203c9f595..6aa7e936973fb 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-no-context-struct.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-no-context-struct.mlir
@@ -21,7 +21,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK-LABEL: define void @_QPtest() {
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-nogroup.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-nogroup.mlir
index a1773764dcb82..11ac7f8a9075e 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-nogroup.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-nogroup.mlir
@@ -31,7 +31,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-num_tasks.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-num_tasks.mlir
index e52d0ba559cef..fd11bbf55dd6c 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-num_tasks.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-num_tasks.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-outer-bounds.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-outer-bounds.mlir
index 7e0b6d6f00c49..f24c40eb4b3ab 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-outer-bounds.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-outer-bounds.mlir
@@ -30,7 +30,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-priority.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-priority.mlir
index 77d0853fb4951..b283948058606 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-priority.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-priority.mlir
@@ -32,7 +32,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop-untied.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop-untied.mlir
index 4527fe12eeacc..089b73a564796 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop-untied.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop-untied.mlir
@@ -31,7 +31,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -61,7 +61,7 @@ llvm.func @_QPtest_tied() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-taskloop.mlir b/mlir/test/Target/LLVMIR/openmp-taskloop.mlir
index 81ec361239ce0..30dd881f10467 100644
--- a/mlir/test/Target/LLVMIR/openmp-taskloop.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-taskloop.mlir
@@ -31,7 +31,7 @@ llvm.func @_QPtest() {
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-teams-clauses-trunc-ext.mlir b/mlir/test/Target/LLVMIR/openmp-teams-clauses-trunc-ext.mlir
index 4a88a14d7d753..1f6b5abbdc6e0 100644
--- a/mlir/test/Target/LLVMIR/openmp-teams-clauses-trunc-ext.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-teams-clauses-trunc-ext.mlir
@@ -31,9 +31,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_teams_const_8_l{{.*}}(i32 %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -57,9 +57,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_teams_arg_8_l{{.*}}(i32 %{{.*}}, i64 %[[ARG:.*]], ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -84,9 +84,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_teams_const_2_l{{.*}}(i32 %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -110,9 +110,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_teams_arg_2_l{{.*}}(i32 %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -137,9 +137,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPthread_limit_const_8_l{{.*}}(i32 %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -163,9 +163,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPthread_limit_arg_8_l{{.*}}(i32 %{{.*}}, ptr %[[ARG:[^,]+]], ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -190,9 +190,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPthread_limit_const_2_l{{.*}}(i32 %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -216,9 +216,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
}
}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPthread_limit_arg_2_l{{.*}}(i32 %{{.*}}, ptr %[[ARG:[^,]+]], ptr %{{.*}}, ptr %{{.*}}, ptr %{{.*}})
@@ -248,9 +248,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_threads_const_8_l{{.*}}..omp_par.{{.*}}
@@ -280,9 +280,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_threads_arg_8_l{{.*}}..omp_par.{{.*}}
@@ -311,9 +311,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_threads_const_2_l{{.*}}..omp_par.{{.*}}
@@ -342,9 +342,9 @@ module attributes {dlti.dl_spec = #dlti.dl_spec<!llvm.ptr<270> = dense<32> : vec
omp.terminator
} {omp.composite}
omp.terminator
- }
+ } {omp.combined}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
// CHECK: @__omp_offloading_{{.*}}_{{.*}}__QPnum_threads_arg_2_l{{.*}}..omp_par.{{.*}}
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 84022e082074c..98dbe869f9b81 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -321,7 +321,7 @@ llvm.func @taskloop_allocate(%lb : i32, %ub : i32, %step : i32, %x : !llvm.ptr)
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -346,7 +346,7 @@ llvm.func @taskloop_inreduction(%lb : i32, %ub : i32, %step : i32, %x : !llvm.pt
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
@@ -371,7 +371,7 @@ llvm.func @taskloop_reduction(%lb : i32, %ub : i32, %step : i32, %x : !llvm.ptr)
}
}
omp.terminator
- }
+ } {omp.combined}
llvm.return
}
More information about the llvm-branch-commits
mailing list