[Mlir-commits] [flang] [mlir] [mlir][OpenMP] Add iterator support to map/motion clause (PR #197047)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed May 13 21:34:55 PDT 2026
https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/197047
>From 2fd3653cdf233e3db7498737ab7e7995b789ddbf Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Tue, 31 Mar 2026 01:06:43 -0500
Subject: [PATCH 1/6] [mlir][OpenMP] Add iterator support to motion clauses
Extend omp.target_data, omp.target_enter_data, omp.target_exit_data,
and omp.target_update to support `!omp.iterated<Ty>`.
This is part of feature work for #188061
Assisted with copilot
---
flang/lib/Lower/OpenMP/OpenMP.cpp | 3 +-
.../Optimizer/OpenMP/FunctionFiltering.cpp | 1 +
.../Optimizer/OpenMP/LowerWorkdistribute.cpp | 37 ++---
flang/lib/Utils/OpenMP.cpp | 3 +-
.../mlir/Dialect/OpenMP/OpenMPClauses.td | 13 +-
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 15 +-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 149 +++++++++++++++---
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 17 +-
mlir/test/Dialect/OpenMP/invalid.mlir | 42 ++++-
mlir/test/Dialect/OpenMP/ops.mlir | 101 +++++++++++-
mlir/test/Target/LLVMIR/openmp-todo.mlir | 83 ++++++++++
11 files changed, 403 insertions(+), 61 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index da44717c8b6ed..402c1ed3d6086 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4395,7 +4395,8 @@ genOpenMPDeclareMapperImpl(lower::AbstractConverter &converter,
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processMap(loc, stmtCtx, clauseOps);
- mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars);
+ mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars,
+ /*map_iterated=*/{});
}
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
diff --git a/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp b/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
index b78b33f31b142..70746b3612f76 100644
--- a/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
+++ b/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
@@ -311,6 +311,7 @@ class FunctionFilteringPass
targetOp.setDependKindsAttr(nullptr);
targetOp.getDependIteratedMutable().clear();
targetOp.setDependIteratedKindsAttr(nullptr);
+ targetOp.getMapIteratedMutable().clear();
targetOp.getDeviceMutable().clear();
targetOp.getIfExprMutable().clear();
targetOp.getDynGroupprivateSizeMutable().clear();
diff --git a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
index 1d98018ffbd05..4bd46ae4df204 100644
--- a/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
+++ b/flang/lib/Optimizer/OpenMP/LowerWorkdistribute.cpp
@@ -749,9 +749,9 @@ FailureOr<omp::TargetOp> splitTargetData(omp::TargetOp targetOp,
auto deviceAddrVars = targetOp.getHasDeviceAddrVars();
auto devicePtrVars = targetOp.getIsDevicePtrVars();
// Create the target data op
- auto targetDataOp =
- omp::TargetDataOp::create(rewriter, loc, device, ifExpr, outerMapInfos,
- deviceAddrVars, devicePtrVars);
+ auto targetDataOp = omp::TargetDataOp::create(
+ rewriter, loc, device, ifExpr, outerMapInfos,
+ /*map_iterated=*/{}, deviceAddrVars, devicePtrVars);
auto taregtDataBlock = rewriter.createBlock(&targetDataOp.getRegion());
mlir::omp::TerminatorOp::create(rewriter, loc);
rewriter.setInsertionPointToStart(taregtDataBlock);
@@ -767,9 +767,10 @@ FailureOr<omp::TargetOp> splitTargetData(omp::TargetOp targetOp,
targetOp.getHostEvalVars(), targetOp.getIfExpr(),
targetOp.getInReductionVars(), targetOp.getInReductionByrefAttr(),
targetOp.getInReductionSymsAttr(), targetOp.getIsDevicePtrVars(),
- innerMapInfos, targetOp.getNowaitAttr(), targetOp.getPrivateVars(),
- targetOp.getPrivateSymsAttr(), targetOp.getPrivateNeedsBarrierAttr(),
- targetOp.getThreadLimitVars(), targetOp.getPrivateMapsAttr());
+ innerMapInfos, targetOp.getMapIterated(), targetOp.getNowaitAttr(),
+ targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
+ targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimitVars(),
+ targetOp.getPrivateMapsAttr());
rewriter.inlineRegionBefore(targetOp.getRegion(), newTargetOp.getRegion(),
newTargetOp.getRegion().begin());
rewriter.replaceOp(targetOp, targetDataOp);
@@ -1489,10 +1490,10 @@ genPreTargetOp(omp::TargetOp targetOp, SmallVector<Value> &preMapOperands,
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
preHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
- targetOp.getIsDevicePtrVars(), preMapOperands, targetOp.getNowaitAttr(),
- targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
- targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimitVars(),
- targetOp.getPrivateMapsAttr());
+ targetOp.getIsDevicePtrVars(), preMapOperands, targetOp.getMapIterated(),
+ targetOp.getNowaitAttr(), targetOp.getPrivateVars(),
+ targetOp.getPrivateSymsAttr(), targetOp.getPrivateNeedsBarrierAttr(),
+ targetOp.getThreadLimitVars(), targetOp.getPrivateMapsAttr());
auto *preTargetBlock = rewriter.createBlock(
&preTargetOp.getRegion(), preTargetOp.getRegion().begin(), {}, {});
IRMapping preMapping;
@@ -1582,10 +1583,10 @@ genIsolatedTargetOp(omp::TargetOp targetOp, SmallVector<Value> &postMapOperands,
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
isolatedHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
- targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getNowaitAttr(),
- targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
- targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimitVars(),
- targetOp.getPrivateMapsAttr());
+ targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getMapIterated(),
+ targetOp.getNowaitAttr(), targetOp.getPrivateVars(),
+ targetOp.getPrivateSymsAttr(), targetOp.getPrivateNeedsBarrierAttr(),
+ targetOp.getThreadLimitVars(), targetOp.getPrivateMapsAttr());
auto *isolatedTargetBlock =
rewriter.createBlock(&isolatedTargetOp.getRegion(),
isolatedTargetOp.getRegion().begin(), {}, {});
@@ -1665,10 +1666,10 @@ static omp::TargetOp genPostTargetOp(omp::TargetOp targetOp,
targetOp.getDynGroupprivateSize(), targetOp.getHasDeviceAddrVars(),
postHostEvalVars, targetOp.getIfExpr(), targetOp.getInReductionVars(),
targetOp.getInReductionByrefAttr(), targetOp.getInReductionSymsAttr(),
- targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getNowaitAttr(),
- targetOp.getPrivateVars(), targetOp.getPrivateSymsAttr(),
- targetOp.getPrivateNeedsBarrierAttr(), targetOp.getThreadLimitVars(),
- targetOp.getPrivateMapsAttr());
+ targetOp.getIsDevicePtrVars(), postMapOperands, targetOp.getMapIterated(),
+ targetOp.getNowaitAttr(), targetOp.getPrivateVars(),
+ targetOp.getPrivateSymsAttr(), targetOp.getPrivateNeedsBarrierAttr(),
+ targetOp.getThreadLimitVars(), targetOp.getPrivateMapsAttr());
// Create the block for postTargetOp
auto *postTargetBlock = rewriter.createBlock(
&postTargetOp.getRegion(), postTargetOp.getRegion().begin(), {}, {});
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index cd6b7f310dd75..7d6356cd6d1df 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -256,7 +256,8 @@ mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
/*partialMap=*/true);
clauseMapVars.emplace_back(mapOp);
- mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars);
+ mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars,
+ /*map_iterated=*/{});
return mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(), mapperNameStr);
}
} // namespace Fortran::utils::openmp
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 2a2b695e77c0e..5f667af813178 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -903,20 +903,25 @@ class OpenMP_MapClauseSkip<
MapClauseOwningOpInterface
];
- let arguments = (ins
- Variadic<OpenMP_PointerLikeType>:$map_vars
- );
+ let arguments = (ins Variadic<OpenMP_PointerLikeType>:$map_vars,
+ Variadic<OpenMP_IteratedType>:$map_iterated);
// This assembly format should only be used by operations where `map` does not
// define entry block arguments. Otherwise, it must be printed and parsed
// together with the corresponding region.
let optAssemblyFormat = [{
- `map_entries` `(` $map_vars `:` type($map_vars) `)`
+ `map_entries` `(`
+ custom<MapEntryList>($map_vars, type($map_vars),
+ $map_iterated, type($map_iterated)) `)`
}];
let description = [{
The optional `map_vars` maps data from the current task's data environment
to the device data environment.
+
+ The optional `map_iterated` holds iterator-produced handles (from
+ `omp.iterator`) whose bodies create `omp.map.info` ops, specifying
+ map entries expanded at runtime via an iterator modifier.
}];
}
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index c8c233477c174..e827935306d51 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1650,12 +1650,13 @@ def TargetOp : OpenMP_Op<"target", traits = [
bool *hostEvalTripCount = nullptr);
}] # clausesExtraClassDeclaration;
- let assemblyFormat = clausesAssemblyFormat # [{
+ let assemblyFormat = clausesAssemblyFormat#[{
custom<TargetOpRegion>(
$region, $has_device_addr_vars, type($has_device_addr_vars),
$host_eval_vars, type($host_eval_vars), $in_reduction_vars,
type($in_reduction_vars), $in_reduction_byref, $in_reduction_syms,
- $map_vars, type($map_vars), $private_vars, type($private_vars),
+ $map_vars, type($map_vars), $map_iterated, type($map_iterated),
+ $private_vars, type($private_vars),
$private_syms, $private_needs_barrier, $private_maps) attr-dict
}];
@@ -2072,12 +2073,10 @@ def DeclareMapperOp : OpenMP_Op<"declare_mapper", [
let hasRegionVerifier = 1;
}
-def DeclareMapperInfoOp : OpenMP_Op<"declare_mapper.info", [
- HasParent<"DeclareMapperOp">,
- Terminator
- ], clauses = [
- OpenMP_MapClause
- ]> {
+def DeclareMapperInfoOp : OpenMP_Op<"declare_mapper.info",
+ [AttrSizedOperandSegments,
+ HasParent<"DeclareMapperOp">, Terminator],
+ clauses = [OpenMP_MapClause]> {
let summary = "declare mapper info";
let description = [{
This Op is used to capture the map information related to it's
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 89a104b2df67c..186f856110017 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1310,6 +1310,8 @@ static ParseResult parseTargetOpRegion(
DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms,
SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapVars,
SmallVectorImpl<Type> &mapTypes,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapIterated,
+ SmallVectorImpl<Type> &mapIteratedTypes,
llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars,
llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms,
UnitAttr &privateNeedsBarrier, DenseI64ArrayAttr &privateMaps) {
@@ -1321,7 +1323,26 @@ static ParseResult parseTargetOpRegion(
args.mapArgs.emplace(mapVars, mapTypes);
args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
privateNeedsBarrier, &privateMaps);
- return parseBlockArgRegion(parser, region, args);
+
+ if (parseBlockArgRegion(parser, region, args))
+ return failure();
+
+ // Parse optional map_iterated_entries (not block args).
+ if (succeeded(parser.parseOptionalKeyword("map_iterated_entries"))) {
+ if (parser.parseLParen() || parser.parseCommaSeparatedList([&]() {
+ OpAsmParser::UnresolvedOperand operand;
+ Type ty;
+ if (parser.parseOperand(operand) || parser.parseColonType(ty))
+ return failure();
+ mapIterated.push_back(operand);
+ mapIteratedTypes.push_back(ty);
+ return success();
+ }) ||
+ parser.parseRParen())
+ return failure();
+ }
+
+ return success();
}
static ParseResult parseInReductionPrivateRegion(
@@ -1574,8 +1595,9 @@ static void printTargetOpRegion(
ValueRange hostEvalVars, TypeRange hostEvalTypes,
ValueRange inReductionVars, TypeRange inReductionTypes,
DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms,
- ValueRange mapVars, TypeRange mapTypes, ValueRange privateVars,
- TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier,
+ ValueRange mapVars, TypeRange mapTypes, ValueRange mapIterated,
+ TypeRange mapIteratedTypes, ValueRange privateVars, TypeRange privateTypes,
+ ArrayAttr privateSyms, UnitAttr privateNeedsBarrier,
DenseI64ArrayAttr privateMaps) {
AllRegionPrintArgs args;
args.hasDeviceAddrArgs.emplace(hasDeviceAddrVars, hasDeviceAddrTypes);
@@ -1586,6 +1608,17 @@ static void printTargetOpRegion(
args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
privateNeedsBarrier, privateMaps);
printBlockArgRegion(p, op, region, args);
+
+ // Print map_iterated_entries if present (not block args).
+ if (!mapIterated.empty()) {
+ p << " map_iterated_entries(";
+ llvm::interleaveComma(llvm::zip(mapIterated, mapIteratedTypes), p,
+ [&](auto t) {
+ auto [val, ty] = t;
+ p << val << " : " << ty;
+ });
+ p << ")";
+ }
}
static void printInReductionPrivateRegion(
@@ -2228,6 +2261,56 @@ static void printMapClause(OpAsmPrinter &p, Operation *op,
}
}
+/// map-entry-list ::= map-entry
+/// | map-entry-list `,` map-entry
+/// map-entry ::= ssa-id `:` type
+/// | ssa-id `:` iterated-type
+static ParseResult
+parseMapEntryList(OpAsmParser &parser,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapVars,
+ SmallVectorImpl<Type> &mapVarTypes,
+ SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapIterated,
+ SmallVectorImpl<Type> &mapIteratedTypes) {
+ // Parse all operands first, then all types in grouped format:
+ // %v1, %v2 : type1, type2
+ SmallVector<OpAsmParser::UnresolvedOperand> operands;
+ SmallVector<Type> types;
+ if (parser.parseOperandList(operands) || parser.parseColonTypeList(types))
+ return failure();
+ if (operands.size() != types.size())
+ return parser.emitError(parser.getNameLoc(),
+ "expected same number of operands and types");
+ // Split iterator handles from regular map locators.
+ for (unsigned i = 0, e = operands.size(); i < e; ++i) {
+ if (llvm::isa<mlir::omp::IteratedType>(types[i])) {
+ mapIterated.push_back(operands[i]);
+ mapIteratedTypes.push_back(types[i]);
+ } else {
+ mapVars.push_back(operands[i]);
+ mapVarTypes.push_back(types[i]);
+ }
+ }
+ return success();
+}
+
+/// Print map_entries list with both plain and iterated entries.
+static void printMapEntryList(OpAsmPrinter &p, Operation *op,
+ OperandRange mapVars, TypeRange mapVarTypes,
+ OperandRange mapIterated,
+ TypeRange mapIteratedTypes) {
+ // Print all operands, then all types in grouped format:
+ // %v1, %v2 : type1, type2
+ llvm::interleaveComma(mapVars, p, [&](Value v) { p << v; });
+ if (!mapVars.empty() && !mapIterated.empty())
+ p << ", ";
+ llvm::interleaveComma(mapIterated, p, [&](Value v) { p << v; });
+ p << " : ";
+ llvm::interleaveComma(mapVarTypes, p, [&](Type t) { p << t; });
+ if (!mapVarTypes.empty() && !mapIteratedTypes.empty())
+ p << ", ";
+ llvm::interleaveComma(mapIteratedTypes, p, [&](Type t) { p << t; });
+}
+
static ParseResult parseMembersIndex(OpAsmParser &parser,
ArrayAttr &membersIdx) {
SmallVector<Attribute> values, memberIdxs;
@@ -2313,7 +2396,8 @@ static ParseResult parseCaptureType(OpAsmParser &parser,
return success();
}
-static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars) {
+static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars,
+ OperandRange mapIterated) {
llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> updateToVars;
llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> updateFromVars;
@@ -2379,6 +2463,26 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars) {
}
}
+ // Verify iterated map entries.
+ for (auto iterVal : mapIterated) {
+ auto iterOp = iterVal.getDefiningOp<mlir::omp::IteratorOp>();
+ if (!iterOp)
+ return op->emitOpError() << "'map_iterated' arguments must be defined by "
+ "'omp.iterator' ops";
+
+ // Check that the iterator body yields a value defined by omp.map.info.
+ auto ®ion = iterOp.getRegion();
+ if (!region.empty()) {
+ auto yieldOp = cast<mlir::omp::YieldOp>(region.front().getTerminator());
+ if (yieldOp.getNumOperands() > 0) {
+ auto yieldedVal = yieldOp.getOperand(0);
+ if (!yieldedVal.getDefiningOp<mlir::omp::MapInfoOp>())
+ return op->emitOpError() << "'map_iterated' iterator body must yield "
+ "a value defined by 'omp.map.info'";
+ }
+ }
+ }
+
return success();
}
@@ -2438,13 +2542,13 @@ LogicalResult MapInfoOp::verify() {
void TargetDataOp::build(OpBuilder &builder, OperationState &state,
const TargetDataOperands &clauses) {
TargetDataOp::build(builder, state, clauses.device, clauses.ifExpr,
- clauses.mapVars, clauses.useDeviceAddrVars,
- clauses.useDevicePtrVars);
+ clauses.mapVars, clauses.mapIterated,
+ clauses.useDeviceAddrVars, clauses.useDevicePtrVars);
}
LogicalResult TargetDataOp::verify() {
- if (getMapVars().empty() && getUseDevicePtrVars().empty() &&
- getUseDeviceAddrVars().empty()) {
+ if (getMapVars().empty() && getMapIterated().empty() &&
+ getUseDevicePtrVars().empty() && getUseDeviceAddrVars().empty()) {
return ::emitError(this->getLoc(),
"At least one of map, use_device_ptr_vars, or "
"use_device_addr_vars operand must be present");
@@ -2458,7 +2562,7 @@ LogicalResult TargetDataOp::verify() {
getUseDeviceAddrVars())))
return failure();
- return verifyMapClause(*this, getMapVars());
+ return verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2473,15 +2577,16 @@ void TargetEnterDataOp::build(
builder, state, makeArrayAttr(ctx, clauses.dependKinds),
clauses.dependVars, makeArrayAttr(ctx, clauses.dependIteratedKinds),
clauses.dependIterated, clauses.device, clauses.ifExpr, clauses.mapVars,
- clauses.nowait);
+ clauses.mapIterated, clauses.nowait);
}
LogicalResult TargetEnterDataOp::verify() {
LogicalResult verifyDependVars =
verifyDependVarList(*this, getDependKinds(), getDependVars(),
getDependIteratedKinds(), getDependIterated());
- return failed(verifyDependVars) ? verifyDependVars
- : verifyMapClause(*this, getMapVars());
+ return failed(verifyDependVars)
+ ? verifyDependVars
+ : verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2495,15 +2600,16 @@ void TargetExitDataOp::build(OpBuilder &builder, OperationState &state,
builder, state, makeArrayAttr(ctx, clauses.dependKinds),
clauses.dependVars, makeArrayAttr(ctx, clauses.dependIteratedKinds),
clauses.dependIterated, clauses.device, clauses.ifExpr, clauses.mapVars,
- clauses.nowait);
+ clauses.mapIterated, clauses.nowait);
}
LogicalResult TargetExitDataOp::verify() {
LogicalResult verifyDependVars =
verifyDependVarList(*this, getDependKinds(), getDependVars(),
getDependIteratedKinds(), getDependIterated());
- return failed(verifyDependVars) ? verifyDependVars
- : verifyMapClause(*this, getMapVars());
+ return failed(verifyDependVars)
+ ? verifyDependVars
+ : verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2517,15 +2623,16 @@ void TargetUpdateOp::build(OpBuilder &builder, OperationState &state,
clauses.dependVars,
makeArrayAttr(ctx, clauses.dependIteratedKinds),
clauses.dependIterated, clauses.device, clauses.ifExpr,
- clauses.mapVars, clauses.nowait);
+ clauses.mapVars, clauses.mapIterated, clauses.nowait);
}
LogicalResult TargetUpdateOp::verify() {
LogicalResult verifyDependVars =
verifyDependVarList(*this, getDependKinds(), getDependVars(),
getDependIteratedKinds(), getDependIterated());
- return failed(verifyDependVars) ? verifyDependVars
- : verifyMapClause(*this, getMapVars());
+ return failed(verifyDependVars)
+ ? verifyDependVars
+ : verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2546,7 +2653,7 @@ void TargetOp::build(OpBuilder &builder, OperationState &state,
clauses.hasDeviceAddrVars, clauses.hostEvalVars, clauses.ifExpr,
/*in_reduction_vars=*/{}, /*in_reduction_byref=*/nullptr,
/*in_reduction_syms=*/nullptr, clauses.isDevicePtrVars, clauses.mapVars,
- clauses.nowait, clauses.privateVars,
+ clauses.mapIterated, clauses.nowait, clauses.privateVars,
makeArrayAttr(ctx, clauses.privateSyms), clauses.privateNeedsBarrier,
clauses.threadLimitVars,
/*private_maps=*/nullptr);
@@ -2562,7 +2669,7 @@ LogicalResult TargetOp::verify() {
getHasDeviceAddrVars())))
return failure();
- if (failed(verifyMapClause(*this, getMapVars())))
+ if (failed(verifyMapClause(*this, getMapVars(), getMapIterated())))
return failure();
if (failed(verifyDynGroupprivateClause(
@@ -3423,7 +3530,7 @@ LogicalResult DistributeOp::verifyRegions() {
//===----------------------------------------------------------------------===//
LogicalResult DeclareMapperInfoOp::verify() {
- return verifyMapClause(*this, getMapVars());
+ return verifyMapClause(*this, getMapVars(), getMapIterated());
}
LogicalResult DeclareMapperOp::verifyRegions() {
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 6df55fbbece78..90edd8987e7cc 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -388,6 +388,10 @@ static LogicalResult checkImplementationStatus(Operation &op) {
if (op.hasThreadLimitMultiDim())
result = todo("thread_limit with multi-dimensional values");
};
+ auto checkMapIteratorModifier = [&todo](auto op, LogicalResult &result) {
+ if (!op.getMapIterated().empty())
+ result = todo("map/motion clause with iterator modifier");
+ };
auto checkDynGroupprivate = [&todo](auto op, LogicalResult &result) {
if (op.getDynGroupprivateSize())
@@ -450,15 +454,22 @@ static LogicalResult checkImplementationStatus(Operation &op) {
.Case([&](omp::SimdOp op) { checkReduction(op, result); })
.Case<omp::AtomicReadOp, omp::AtomicWriteOp, omp::AtomicUpdateOp,
omp::AtomicCaptureOp>([&](auto op) { checkHint(op, result); })
- .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>(
- [&](auto op) { checkDepend(op, result); })
- .Case([&](omp::TargetUpdateOp op) { checkDepend(op, result); })
+ .Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](auto op) {
+ checkDepend(op, result);
+ checkMapIteratorModifier(op, result);
+ })
+ .Case([&](omp::TargetUpdateOp op) {
+ checkDepend(op, result);
+ checkMapIteratorModifier(op, result);
+ })
.Case([&](omp::TargetOp op) {
checkAllocate(op, result);
checkBare(op, result);
checkInReduction(op, result);
+ checkMapIteratorModifier(op, result);
checkThreadLimit(op, result);
})
+ .Case([&](omp::TargetDataOp op) { checkMapIteratorModifier(op, result); })
.Default([](Operation &) {
// Assume all clauses for an operation can be translated unless they are
// checked above.
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 71b46a4baa0bc..18eb05dc57c5f 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -2394,7 +2394,7 @@ func.func @omp_target_enter_data(%map1: memref<?xi32>) {
func.func @omp_target_enter_data_depend(%a: memref<?xi32>) {
%0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
// expected-error @below {{op expected as many depend values as depend variables}}
- omp.target_enter_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0>}
+ omp.target_enter_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0>}
return
}
@@ -2412,7 +2412,7 @@ func.func @omp_target_exit_data(%map1: memref<?xi32>) {
func.func @omp_target_exit_data_depend(%a: memref<?xi32>) {
%0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(from) capture(ByRef) -> memref<?xi32>
// expected-error @below {{op expected as many depend values as depend variables}}
- omp.target_exit_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0>}
+ omp.target_exit_data map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0>}
return
}
@@ -2493,7 +2493,7 @@ llvm.mlir.global internal @_QFsubEx() : i32
func.func @omp_target_update_data_depend(%a: memref<?xi32>) {
%0 = omp.map.info var_ptr(%a: memref<?xi32>, tensor<?xi32>) map_clauses(to) capture(ByRef) -> memref<?xi32>
// expected-error @below {{op expected as many depend values as depend variables}}
- omp.target_update map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0>}
+ omp.target_update map_entries(%0: memref<?xi32> ) {operandSegmentSizes = array<i32: 1, 0, 0, 0, 0, 0>}
return
}
@@ -2595,7 +2595,7 @@ func.func @omp_target_depend(%data_var: memref<i32>) {
// expected-error @below {{op expected as many depend values as depend variables}}
"omp.target"(%data_var) ({
"omp.terminator"() : () -> ()
- }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
+ }) {depend_kinds = [], operandSegmentSizes = array<i32: 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>} : (memref<i32>) -> ()
"func.return"() : () -> ()
}
@@ -3947,6 +3947,39 @@ func.func @iterator_yield_type_mismatch(%lb : index, %ub : index, %st : index) {
}
// -----
+
+func.func @map_iterated_not_iterator(%it : !omp.iterated<!llvm.ptr>) {
+ // expected-error @below {{'omp.target_update' op 'map_iterated' arguments must be defined by 'omp.iterator' ops}}
+ omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ return
+}
+
+// -----
+
+func.func @map_iterated_yield_not_map_info(%lb : index, %ub : index, %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ omp.yield(%addr : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{'omp.target_enter_data' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
+ omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+func.func @map_iterated_yield_not_map_info_exit(%lb : index, %ub : index, %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ omp.yield(%addr : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{'omp.target_exit_data' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
+ omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
func.func @target_allocmem_invalid_uniq_name(%device : i32) -> () {
// expected-error @below {{op attribute 'uniq_name' failed to satisfy constraint: string attribute}}
%0 = omp.target_allocmem %device : i32, i64 {uniq_name=2}
@@ -3954,6 +3987,7 @@ func.func @target_allocmem_invalid_uniq_name(%device : i32) -> () {
}
// -----
+
func.func @target_allocmem_invalid_bindc_name(%device : i32) -> () {
// expected-error @below {{op attribute 'bindc_name' failed to satisfy constraint: string attribute}}
%0 = omp.target_allocmem %device : i32, i64 {bindc_name=2}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 826e36e3f7b19..2b8d278d31af9 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -871,7 +871,7 @@ func.func @omp_target(%if_cond : i1, %device : si32, %num_threads : i32, %devic
"omp.target"(%device, %if_cond, %num_threads) ({
// CHECK: omp.terminator
omp.terminator
- }) {nowait, operandSegmentSizes = array<i32: 0,0,0,0,1,0,0,0,1,0,0,0,0,1>} : ( si32, i1, i32 ) -> ()
+ }) {nowait, operandSegmentSizes = array<i32: 0,0,0,0,1,0,0,0,1,0,0,0,0,0,1>} : ( si32, i1, i32 ) -> ()
// Test with optional map clause.
// CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_1:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(always, to) capture(ByRef) -> memref<?xi32> {name = ""}
@@ -4018,3 +4018,102 @@ llvm.mlir.global internal @gp() : i32
llvm.mlir.global internal @any() : i32
llvm.mlir.global internal @host() : i32
llvm.mlir.global internal @nohost() : i32
+
+// -----
+
+// CHECK-LABEL: func.func @omp_target_update_map_iterated
+func.func @omp_target_update_map_iterated(%lb : index, %ub : index, %step : index,
+ %addr : !llvm.ptr) -> () {
+ // CHECK: %[[MAP:.*]] = omp.map.info var_ptr(%{{.*}} : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+
+ // CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%{{.*}} to %{{.*}} step %{{.*}}) {
+ // CHECK: %[[M:.*]] = omp.map.info var_ptr(%{{.*}} : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ // CHECK: omp.yield(%[[M]] : !llvm.ptr)
+ // CHECK: } -> !omp.iterated<!llvm.ptr>
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+
+ // CHECK: omp.target_update map_entries(%[[MAP]], %[[IT]] : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ omp.target_update map_entries(%map, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ return
+}
+
+// -----
+
+// CHECK-LABEL: func.func @omp_target_enter_data_map_iterated
+func.func @omp_target_enter_data_map_iterated(%lb : index, %ub : index, %step : index,
+ %addr : !llvm.ptr) -> () {
+ // CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%{{.*}} to %{{.*}} step %{{.*}}) {
+ // CHECK: omp.yield(%{{.*}} : !llvm.ptr)
+ // CHECK: } -> !omp.iterated<!llvm.ptr>
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+
+ // CHECK: omp.target_enter_data map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+// CHECK-LABEL: func.func @omp_target_exit_data_map_iterated
+func.func @omp_target_exit_data_map_iterated(%lb : index, %ub : index, %step : index,
+ %addr : !llvm.ptr) -> () {
+ // CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%{{.*}} to %{{.*}} step %{{.*}}) {
+ // CHECK: omp.yield(%{{.*}} : !llvm.ptr)
+ // CHECK: } -> !omp.iterated<!llvm.ptr>
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+
+ // CHECK: omp.target_exit_data map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+// CHECK-LABEL: func.func @omp_target_data_map_iterated
+func.func @omp_target_data_map_iterated(%lb : index, %ub : index, %step : index,
+ %addr : !llvm.ptr) -> () {
+ %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+
+ // CHECK: %[[IT:.*]] = omp.iterator
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+
+ // CHECK: omp.target_data map_entries(%{{.*}}, %[[IT]] : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ omp.target_data map_entries(%map, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+// CHECK-LABEL: func.func @omp_target_map_iterated
+func.func @omp_target_map_iterated(%lb : index, %ub : index, %step : index,
+ %addr : !llvm.ptr) -> () {
+ // CHECK: %[[MAP:.*]] = omp.map.info
+ %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+
+ // CHECK: %[[IT:.*]] = omp.iterator
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+
+ // CHECK: omp.target map_entries(%[[MAP]] -> %{{.*}} : !llvm.ptr) {
+ // CHECK: omp.terminator
+ // CHECK: } map_iterated_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target map_entries(%map -> %arg0 : !llvm.ptr) {
+ omp.terminator
+ } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ return
+}
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 295ba54dbfb38..03127b872937b 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -493,3 +493,86 @@ llvm.func @wsloop_order(%lb : i32, %ub : i32, %step : i32) {
}
llvm.return
}
+
+// -----
+
+llvm.func @target_enter_data_map_iterator(%addr : !llvm.ptr) {
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_enter_data operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target_enter_data}}
+ omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ llvm.return
+}
+
+// -----
+
+llvm.func @target_exit_data_map_iterator(%addr : !llvm.ptr) {
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_exit_data operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target_exit_data}}
+ omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ llvm.return
+}
+
+// -----
+
+llvm.func @target_update_map_iterator(%addr : !llvm.ptr) {
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_update operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target_update}}
+ omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ llvm.return
+}
+
+// -----
+
+llvm.func @target_data_map_iterator(%addr : !llvm.ptr) {
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_data operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target_data}}
+ omp.target_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ llvm.return
+}
+
+// -----
+
+llvm.func @target_map_iterator(%addr : !llvm.ptr) {
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target operation}}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target}}
+ omp.target map_entries(%map -> %arg0 : !llvm.ptr) {
+ omp.terminator
+ } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ llvm.return
+}
>From 536bfbfcacc668799840f0f01f3522eafda3cfab Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Mon, 11 May 2026 17:21:21 -0500
Subject: [PATCH 2/6] Add verifier check for iterated map info and tests for
declare mapper
---
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 139 ++++++++++--------
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 6 +
mlir/test/Dialect/OpenMP/invalid.mlir | 110 +++++++++++++-
mlir/test/Dialect/OpenMP/ops.mlir | 18 +++
mlir/test/Target/LLVMIR/openmp-todo.mlir | 24 +++
5 files changed, 236 insertions(+), 61 deletions(-)
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 186f856110017..f1bb1ed662d43 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2396,6 +2396,66 @@ static ParseResult parseCaptureType(OpAsmParser &parser,
return success();
}
+static LogicalResult verifyMapInfoForMapClause(
+ Operation *op, mlir::omp::MapInfoOp mapInfoOp,
+ llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> &updateToVars,
+ llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>>
+ &updateFromVars) {
+ mlir::omp::ClauseMapFlags mapTypeBits = mapInfoOp.getMapType();
+
+ bool to = mapTypeToBool(mapTypeBits, ClauseMapFlags::to);
+ bool from = mapTypeToBool(mapTypeBits, ClauseMapFlags::from);
+ bool del = mapTypeToBool(mapTypeBits, ClauseMapFlags::del);
+
+ bool always = mapTypeToBool(mapTypeBits, ClauseMapFlags::always);
+ bool close = mapTypeToBool(mapTypeBits, ClauseMapFlags::close);
+ bool implicit = mapTypeToBool(mapTypeBits, ClauseMapFlags::implicit);
+
+ if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
+ return emitError(op->getLoc(),
+ "to, from, tofrom and alloc map types are permitted");
+
+ if (isa<TargetEnterDataOp>(op) && (from || del))
+ return emitError(op->getLoc(), "to and alloc map types are permitted");
+
+ if (isa<TargetExitDataOp>(op) && to)
+ return emitError(op->getLoc(),
+ "from, release and delete map types are permitted");
+
+ if (isa<TargetUpdateOp>(op)) {
+ if (del) {
+ return emitError(op->getLoc(),
+ "at least one of to or from map types must be "
+ "specified, other map types are not permitted");
+ }
+
+ if (!to && !from) {
+ return emitError(op->getLoc(),
+ "at least one of to or from map types must be "
+ "specified, other map types are not permitted");
+ }
+
+ auto updateVar = mapInfoOp.getVarPtr();
+
+ if ((to && from) || (to && updateFromVars.contains(updateVar)) ||
+ (from && updateToVars.contains(updateVar))) {
+ return emitError(
+ op->getLoc(),
+ "either to or from map types can be specified, not both");
+ }
+
+ if (always || close || implicit) {
+ return emitError(
+ op->getLoc(),
+ "present, mapper and iterator map type modifiers are permitted");
+ }
+
+ to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
+ }
+
+ return success();
+}
+
static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars,
OperandRange mapIterated) {
llvm::DenseSet<mlir::TypedValue<mlir::omp::PointerLikeType>> updateToVars;
@@ -2406,57 +2466,9 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars,
return emitError(op->getLoc(), "missing map operation");
if (auto mapInfoOp = mapOp.getDefiningOp<mlir::omp::MapInfoOp>()) {
- mlir::omp::ClauseMapFlags mapTypeBits = mapInfoOp.getMapType();
-
- bool to = mapTypeToBool(mapTypeBits, ClauseMapFlags::to);
- bool from = mapTypeToBool(mapTypeBits, ClauseMapFlags::from);
- bool del = mapTypeToBool(mapTypeBits, ClauseMapFlags::del);
-
- bool always = mapTypeToBool(mapTypeBits, ClauseMapFlags::always);
- bool close = mapTypeToBool(mapTypeBits, ClauseMapFlags::close);
- bool implicit = mapTypeToBool(mapTypeBits, ClauseMapFlags::implicit);
-
- if ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
- return emitError(op->getLoc(),
- "to, from, tofrom and alloc map types are permitted");
-
- if (isa<TargetEnterDataOp>(op) && (from || del))
- return emitError(op->getLoc(), "to and alloc map types are permitted");
-
- if (isa<TargetExitDataOp>(op) && to)
- return emitError(op->getLoc(),
- "from, release and delete map types are permitted");
-
- if (isa<TargetUpdateOp>(op)) {
- if (del) {
- return emitError(op->getLoc(),
- "at least one of to or from map types must be "
- "specified, other map types are not permitted");
- }
-
- if (!to && !from) {
- return emitError(op->getLoc(),
- "at least one of to or from map types must be "
- "specified, other map types are not permitted");
- }
-
- auto updateVar = mapInfoOp.getVarPtr();
-
- if ((to && from) || (to && updateFromVars.contains(updateVar)) ||
- (from && updateToVars.contains(updateVar))) {
- return emitError(
- op->getLoc(),
- "either to or from map types can be specified, not both");
- }
-
- if (always || close || implicit) {
- return emitError(
- op->getLoc(),
- "present, mapper and iterator map type modifiers are permitted");
- }
-
- to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
- }
+ if (failed(verifyMapInfoForMapClause(op, mapInfoOp, updateToVars,
+ updateFromVars)))
+ return failure();
} else if (!isa<DeclareMapperInfoOp>(op)) {
return emitError(op->getLoc(),
"map argument is not a map entry operation");
@@ -2472,15 +2484,22 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars,
// Check that the iterator body yields a value defined by omp.map.info.
auto ®ion = iterOp.getRegion();
- if (!region.empty()) {
- auto yieldOp = cast<mlir::omp::YieldOp>(region.front().getTerminator());
- if (yieldOp.getNumOperands() > 0) {
- auto yieldedVal = yieldOp.getOperand(0);
- if (!yieldedVal.getDefiningOp<mlir::omp::MapInfoOp>())
- return op->emitOpError() << "'map_iterated' iterator body must yield "
- "a value defined by 'omp.map.info'";
- }
- }
+ if (region.empty())
+ continue;
+
+ auto yieldOp = dyn_cast<mlir::omp::YieldOp>(region.front().getTerminator());
+ if (!yieldOp || yieldOp.getNumOperands() == 0)
+ continue;
+
+ auto yieldedMapInfo =
+ yieldOp.getOperand(0).getDefiningOp<mlir::omp::MapInfoOp>();
+ if (!yieldedMapInfo)
+ return op->emitOpError() << "'map_iterated' iterator body must yield "
+ "a value defined by 'omp.map.info'";
+
+ if (failed(verifyMapInfoForMapClause(op, yieldedMapInfo, updateToVars,
+ updateFromVars)))
+ return failure();
}
return success();
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index 90edd8987e7cc..d67090a989218 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -470,6 +470,9 @@ static LogicalResult checkImplementationStatus(Operation &op) {
checkThreadLimit(op, result);
})
.Case([&](omp::TargetDataOp op) { checkMapIteratorModifier(op, result); })
+ .Case([&](omp::DeclareMapperInfoOp op) {
+ checkMapIteratorModifier(op, result);
+ })
.Default([](Operation &) {
// Assume all clauses for an operation can be translated unless they are
// checked above.
@@ -6213,6 +6216,9 @@ emitUserDefinedMapper(Operation *op, llvm::IRBuilderBase &builder,
"function only supported for host device codegen");
auto declMapperOp = cast<omp::DeclareMapperOp>(op);
auto declMapperInfoOp = declMapperOp.getDeclareMapperInfo();
+ if (failed(checkImplementationStatus(*declMapperInfoOp)))
+ return llvm::make_error<PreviouslyReportedError>();
+
DataLayout dl = DataLayout(declMapperOp->getParentOfType<ModuleOp>());
llvm::OpenMPIRBuilder *ompBuilder = moduleTranslation.getOpenMPBuilder();
llvm::Type *varType = moduleTranslation.convertType(declMapperOp.getType());
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 18eb05dc57c5f..25a46c1a80245 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3980,6 +3980,115 @@ func.func @map_iterated_yield_not_map_info_exit(%lb : index, %ub : index, %st :
// -----
+func.func @target_enter_data_map_iterated_invalid_from(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{to and alloc map types are permitted}}
+ omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+func.func @target_exit_data_map_iterated_invalid_to(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{from, release and delete map types are permitted}}
+ omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+func.func @target_update_map_iterated_invalid_delete(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(delete) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}}
+ omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ return
+}
+
+// -----
+
+func.func @target_update_map_iterated_invalid_conflict(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %mapv = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(to) capture(ByRef) -> !llvm.ptr {name = ""}
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(from) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{either to or from map types can be specified, not both}}
+ omp.target_update map_entries(%mapv, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ return
+}
+
+// -----
+
+func.func @target_data_map_iterated_invalid_delete(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(delete) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{to, from, tofrom and alloc map types are permitted}}
+ omp.target_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ return
+}
+
+// -----
+
+func.func @target_map_iterated_invalid_delete(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
+ %mapv = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(delete) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{to, from, tofrom and alloc map types are permitted}}
+ omp.target map_entries(%mapv -> %arg0 : !llvm.ptr) {
+ omp.terminator
+ } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ return
+}
+
+// -----
+
+omp.declare_mapper @declare_mapper_iterated_not_iterator : !llvm.struct<"mapper_type", (i32)> {
+^bb0(%arg: !llvm.ptr, %it: !omp.iterated<!llvm.ptr>):
+ // expected-error @below {{'omp.declare_mapper.info' op 'map_iterated' arguments must be defined by 'omp.iterator' ops}}
+ omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+}
+
+// -----
+
+omp.declare_mapper @declare_mapper_iterated_yield_not_map_info : !llvm.struct<"mapper_type", (i32)> {
+^bb0(%arg: !llvm.ptr):
+ %lb = arith.constant 0 : index
+ %ub = arith.constant 4 : index
+ %st = arith.constant 1 : index
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ omp.yield(%arg : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error @below {{'omp.declare_mapper.info' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
+ omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+}
+
+// -----
func.func @target_allocmem_invalid_uniq_name(%device : i32) -> () {
// expected-error @below {{op attribute 'uniq_name' failed to satisfy constraint: string attribute}}
%0 = omp.target_allocmem %device : i32, i64 {uniq_name=2}
@@ -3987,7 +4096,6 @@ func.func @target_allocmem_invalid_uniq_name(%device : i32) -> () {
}
// -----
-
func.func @target_allocmem_invalid_bindc_name(%device : i32) -> () {
// expected-error @below {{op attribute 'bindc_name' failed to satisfy constraint: string attribute}}
%0 = omp.target_allocmem %device : i32, i64 {bindc_name=2}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 2b8d278d31af9..4036e5b5e9ff5 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1001,6 +1001,24 @@ omp.declare_mapper @my_mapper : !llvm.struct<"my_type", (i32)> {
omp.declare_mapper.info map_entries(%decl_map_info : !llvm.ptr)
}
+// CHECK: omp.declare_mapper @my_mapper_iterated : !llvm.struct<"my_iter_type", (i32)>
+omp.declare_mapper @my_mapper_iterated : !llvm.struct<"my_iter_type", (i32)> {
+^bb0(%arg: !llvm.ptr):
+ %lb = arith.constant 0 : index
+ %ub = arith.constant 4 : index
+ %step = arith.constant 1 : index
+ // CHECK: %[[IT:.*]] = omp.iterator(%[[IV:.*]]: index) = (%{{.*}} to %{{.*}} step %{{.*}}) {
+ // CHECK: %[[DECL_MAP_INFO:.*]] = omp.map.info var_ptr(%{{.*}} : !llvm.ptr, !llvm.struct<"my_iter_type", (i32)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ // CHECK: omp.yield(%[[DECL_MAP_INFO]] : !llvm.ptr)
+ // CHECK: } -> !omp.iterated<!llvm.ptr>
+ %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
+ %decl_map_info = omp.map.info var_ptr(%arg : !llvm.ptr, !llvm.struct<"my_iter_type", (i32)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%decl_map_info : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // CHECK: omp.declare_mapper.info map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+}
+
// CHECK-LABEL: func @wsloop_reduction
func.func @wsloop_reduction(%lb : index, %ub : index, %step : index) {
%c1 = arith.constant 1 : i32
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 03127b872937b..c55117a81f7cc 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -576,3 +576,27 @@ llvm.func @target_map_iterator(%addr : !llvm.ptr) {
} map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
llvm.return
}
+
+// -----
+
+module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
+ omp.declare_mapper @mapper_with_iterator : !llvm.struct<"mapper_type", (i32)> {
+ ^bb0(%arg: !llvm.ptr):
+ %c0 = llvm.mlir.constant(0 : i64) : i64
+ %c10 = llvm.mlir.constant(10 : i64) : i64
+ %c1 = llvm.mlir.constant(1 : i64) : i64
+ %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
+ %m = omp.map.info var_ptr(%arg : !llvm.ptr, !llvm.struct<"mapper_type", (i32)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
+ omp.yield(%m : !llvm.ptr)
+ } -> !omp.iterated<!llvm.ptr>
+ // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.declare_mapper.info operation}}
+ omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+ }
+
+ llvm.func @target_data_mapper_iterator(%addr : !llvm.ptr) {
+ %map = omp.map.info var_ptr(%addr : !llvm.ptr, !llvm.struct<"mapper_type", (i32)>) map_clauses(tofrom) capture(ByRef) mapper(@mapper_with_iterator) -> !llvm.ptr {name = ""}
+ // expected-error at below {{LLVM Translation failed for operation: omp.target_data}}
+ omp.target_data map_entries(%map : !llvm.ptr) {}
+ llvm.return
+ }
+}
>From 6f65e888e37673a6ad03b3f254fc6ac1926ffff1 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 13 May 2026 12:12:59 -0500
Subject: [PATCH 3/6] Simplify map iterator clause assembly
- Split MLIR map syntax into separate map_entries(...) and map_iterated(...),
removing the custom MapEntryList parser/printer.
- Moved omp.target map_iterated out of TargetOpRegion
- it now prints before the target region instead of as map_iterated_entries(...) after the region.
- Renamed LLVMIR TODO helper to clause-style checkMap.
- Added DeclareMapperInfoOp builder from DeclareMapperInfoOperands
and updated Flang call sites so they do not need to spell out newly
added operands..
---
flang/lib/Lower/OpenMP/OpenMP.cpp | 3 +-
flang/lib/Utils/OpenMP.cpp | 6 +-
.../mlir/Dialect/OpenMP/OpenMPClauses.td | 5 +-
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 9 +-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 94 ++-----------------
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 14 ++-
mlir/test/Dialect/OpenMP/invalid.mlir | 24 ++---
mlir/test/Dialect/OpenMP/ops.mlir | 28 +++---
mlir/test/Target/LLVMIR/openmp-todo.mlir | 14 +--
9 files changed, 60 insertions(+), 137 deletions(-)
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 402c1ed3d6086..8d8d2cabcb94d 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4395,8 +4395,7 @@ genOpenMPDeclareMapperImpl(lower::AbstractConverter &converter,
List<Clause> clauses = makeClauses(construct.v.Clauses(), semaCtx);
ClauseProcessor cp(converter, semaCtx, clauses);
cp.processMap(loc, stmtCtx, clauseOps);
- mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps.mapVars,
- /*map_iterated=*/{});
+ mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps);
}
static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
diff --git a/flang/lib/Utils/OpenMP.cpp b/flang/lib/Utils/OpenMP.cpp
index 7d6356cd6d1df..87cb49c63270e 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -255,9 +255,9 @@ mlir::FlatSymbolRefAttr getOrGenImplicitDefaultDeclareMapper(
captureKind, declareOp.getType(0),
/*partialMap=*/true);
- clauseMapVars.emplace_back(mapOp);
- mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseMapVars,
- /*map_iterated=*/{});
+ mlir::omp::DeclareMapperInfoOperands clauseOps;
+ clauseOps.mapVars.emplace_back(mapOp);
+ mlir::omp::DeclareMapperInfoOp::create(firOpBuilder, loc, clauseOps);
return mlir::FlatSymbolRefAttr::get(firOpBuilder.getContext(), mapperNameStr);
}
} // namespace Fortran::utils::openmp
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
index 5f667af813178..71e66018bf10e 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPClauses.td
@@ -910,9 +910,8 @@ class OpenMP_MapClauseSkip<
// define entry block arguments. Otherwise, it must be printed and parsed
// together with the corresponding region.
let optAssemblyFormat = [{
- `map_entries` `(`
- custom<MapEntryList>($map_vars, type($map_vars),
- $map_iterated, type($map_iterated)) `)`
+ `map_entries` `(` $map_vars `:` type($map_vars) `)` |
+ `map_iterated` `(` $map_iterated `:` type($map_iterated) `)`
}];
let description = [{
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index e827935306d51..21b6b88c57192 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1650,13 +1650,13 @@ def TargetOp : OpenMP_Op<"target", traits = [
bool *hostEvalTripCount = nullptr);
}] # clausesExtraClassDeclaration;
- let assemblyFormat = clausesAssemblyFormat#[{
+ let assemblyFormat = clausesAssemblyFormat # [{
+ ( `map_iterated` `(` $map_iterated^ `:` type($map_iterated) `)` )?
custom<TargetOpRegion>(
$region, $has_device_addr_vars, type($has_device_addr_vars),
$host_eval_vars, type($host_eval_vars), $in_reduction_vars,
type($in_reduction_vars), $in_reduction_byref, $in_reduction_syms,
- $map_vars, type($map_vars), $map_iterated, type($map_iterated),
- $private_vars, type($private_vars),
+ $map_vars, type($map_vars), $private_vars, type($private_vars),
$private_syms, $private_needs_barrier, $private_maps) attr-dict
}];
@@ -2083,6 +2083,9 @@ def DeclareMapperInfoOp : OpenMP_Op<"declare_mapper.info",
parent DeclareMapperOp.
}] # clausesDescription;
+ let builders = [OpBuilder<(
+ ins CArg<"const DeclareMapperInfoOperands &">:$clauses)>];
+
let extraClassDeclaration = [{
// Override BlockArgOpenMPOpInterface method because `map` clauses have no
// associated entry block arguments in this operation.
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index f1bb1ed662d43..ae730e001e353 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1310,8 +1310,6 @@ static ParseResult parseTargetOpRegion(
DenseBoolArrayAttr &inReductionByref, ArrayAttr &inReductionSyms,
SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapVars,
SmallVectorImpl<Type> &mapTypes,
- SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapIterated,
- SmallVectorImpl<Type> &mapIteratedTypes,
llvm::SmallVectorImpl<OpAsmParser::UnresolvedOperand> &privateVars,
llvm::SmallVectorImpl<Type> &privateTypes, ArrayAttr &privateSyms,
UnitAttr &privateNeedsBarrier, DenseI64ArrayAttr &privateMaps) {
@@ -1324,25 +1322,7 @@ static ParseResult parseTargetOpRegion(
args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
privateNeedsBarrier, &privateMaps);
- if (parseBlockArgRegion(parser, region, args))
- return failure();
-
- // Parse optional map_iterated_entries (not block args).
- if (succeeded(parser.parseOptionalKeyword("map_iterated_entries"))) {
- if (parser.parseLParen() || parser.parseCommaSeparatedList([&]() {
- OpAsmParser::UnresolvedOperand operand;
- Type ty;
- if (parser.parseOperand(operand) || parser.parseColonType(ty))
- return failure();
- mapIterated.push_back(operand);
- mapIteratedTypes.push_back(ty);
- return success();
- }) ||
- parser.parseRParen())
- return failure();
- }
-
- return success();
+ return parseBlockArgRegion(parser, region, args);
}
static ParseResult parseInReductionPrivateRegion(
@@ -1595,9 +1575,8 @@ static void printTargetOpRegion(
ValueRange hostEvalVars, TypeRange hostEvalTypes,
ValueRange inReductionVars, TypeRange inReductionTypes,
DenseBoolArrayAttr inReductionByref, ArrayAttr inReductionSyms,
- ValueRange mapVars, TypeRange mapTypes, ValueRange mapIterated,
- TypeRange mapIteratedTypes, ValueRange privateVars, TypeRange privateTypes,
- ArrayAttr privateSyms, UnitAttr privateNeedsBarrier,
+ ValueRange mapVars, TypeRange mapTypes, ValueRange privateVars,
+ TypeRange privateTypes, ArrayAttr privateSyms, UnitAttr privateNeedsBarrier,
DenseI64ArrayAttr privateMaps) {
AllRegionPrintArgs args;
args.hasDeviceAddrArgs.emplace(hasDeviceAddrVars, hasDeviceAddrTypes);
@@ -1608,17 +1587,6 @@ static void printTargetOpRegion(
args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
privateNeedsBarrier, privateMaps);
printBlockArgRegion(p, op, region, args);
-
- // Print map_iterated_entries if present (not block args).
- if (!mapIterated.empty()) {
- p << " map_iterated_entries(";
- llvm::interleaveComma(llvm::zip(mapIterated, mapIteratedTypes), p,
- [&](auto t) {
- auto [val, ty] = t;
- p << val << " : " << ty;
- });
- p << ")";
- }
}
static void printInReductionPrivateRegion(
@@ -2261,56 +2229,6 @@ static void printMapClause(OpAsmPrinter &p, Operation *op,
}
}
-/// map-entry-list ::= map-entry
-/// | map-entry-list `,` map-entry
-/// map-entry ::= ssa-id `:` type
-/// | ssa-id `:` iterated-type
-static ParseResult
-parseMapEntryList(OpAsmParser &parser,
- SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapVars,
- SmallVectorImpl<Type> &mapVarTypes,
- SmallVectorImpl<OpAsmParser::UnresolvedOperand> &mapIterated,
- SmallVectorImpl<Type> &mapIteratedTypes) {
- // Parse all operands first, then all types in grouped format:
- // %v1, %v2 : type1, type2
- SmallVector<OpAsmParser::UnresolvedOperand> operands;
- SmallVector<Type> types;
- if (parser.parseOperandList(operands) || parser.parseColonTypeList(types))
- return failure();
- if (operands.size() != types.size())
- return parser.emitError(parser.getNameLoc(),
- "expected same number of operands and types");
- // Split iterator handles from regular map locators.
- for (unsigned i = 0, e = operands.size(); i < e; ++i) {
- if (llvm::isa<mlir::omp::IteratedType>(types[i])) {
- mapIterated.push_back(operands[i]);
- mapIteratedTypes.push_back(types[i]);
- } else {
- mapVars.push_back(operands[i]);
- mapVarTypes.push_back(types[i]);
- }
- }
- return success();
-}
-
-/// Print map_entries list with both plain and iterated entries.
-static void printMapEntryList(OpAsmPrinter &p, Operation *op,
- OperandRange mapVars, TypeRange mapVarTypes,
- OperandRange mapIterated,
- TypeRange mapIteratedTypes) {
- // Print all operands, then all types in grouped format:
- // %v1, %v2 : type1, type2
- llvm::interleaveComma(mapVars, p, [&](Value v) { p << v; });
- if (!mapVars.empty() && !mapIterated.empty())
- p << ", ";
- llvm::interleaveComma(mapIterated, p, [&](Value v) { p << v; });
- p << " : ";
- llvm::interleaveComma(mapVarTypes, p, [&](Type t) { p << t; });
- if (!mapVarTypes.empty() && !mapIteratedTypes.empty())
- p << ", ";
- llvm::interleaveComma(mapIteratedTypes, p, [&](Type t) { p << t; });
-}
-
static ParseResult parseMembersIndex(OpAsmParser &parser,
ArrayAttr &membersIdx) {
SmallVector<Attribute> values, memberIdxs;
@@ -3548,6 +3466,12 @@ LogicalResult DistributeOp::verifyRegions() {
// DeclareMapperOp / DeclareMapperInfoOp
//===----------------------------------------------------------------------===//
+void DeclareMapperInfoOp::build(OpBuilder &builder, OperationState &state,
+ const DeclareMapperInfoOperands &clauses) {
+ DeclareMapperInfoOp::build(builder, state, clauses.mapVars,
+ clauses.mapIterated);
+}
+
LogicalResult DeclareMapperInfoOp::verify() {
return verifyMapClause(*this, getMapVars(), getMapIterated());
}
diff --git a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
index d67090a989218..cae05a77a10a7 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.cpp
@@ -388,7 +388,7 @@ static LogicalResult checkImplementationStatus(Operation &op) {
if (op.hasThreadLimitMultiDim())
result = todo("thread_limit with multi-dimensional values");
};
- auto checkMapIteratorModifier = [&todo](auto op, LogicalResult &result) {
+ auto checkMap = [&todo](auto op, LogicalResult &result) {
if (!op.getMapIterated().empty())
result = todo("map/motion clause with iterator modifier");
};
@@ -456,23 +456,21 @@ static LogicalResult checkImplementationStatus(Operation &op) {
omp::AtomicCaptureOp>([&](auto op) { checkHint(op, result); })
.Case<omp::TargetEnterDataOp, omp::TargetExitDataOp>([&](auto op) {
checkDepend(op, result);
- checkMapIteratorModifier(op, result);
+ checkMap(op, result);
})
.Case([&](omp::TargetUpdateOp op) {
checkDepend(op, result);
- checkMapIteratorModifier(op, result);
+ checkMap(op, result);
})
.Case([&](omp::TargetOp op) {
checkAllocate(op, result);
checkBare(op, result);
checkInReduction(op, result);
- checkMapIteratorModifier(op, result);
+ checkMap(op, result);
checkThreadLimit(op, result);
})
- .Case([&](omp::TargetDataOp op) { checkMapIteratorModifier(op, result); })
- .Case([&](omp::DeclareMapperInfoOp op) {
- checkMapIteratorModifier(op, result);
- })
+ .Case([&](omp::TargetDataOp op) { checkMap(op, result); })
+ .Case([&](omp::DeclareMapperInfoOp op) { checkMap(op, result); })
.Default([](Operation &) {
// Assume all clauses for an operation can be translated unless they are
// checked above.
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 25a46c1a80245..3ac880c7817f3 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3950,7 +3950,7 @@ func.func @iterator_yield_type_mismatch(%lb : index, %ub : index, %st : index) {
func.func @map_iterated_not_iterator(%it : !omp.iterated<!llvm.ptr>) {
// expected-error @below {{'omp.target_update' op 'map_iterated' arguments must be defined by 'omp.iterator' ops}}
- omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.target_update map_iterated(%it : !omp.iterated<!llvm.ptr>)
return
}
@@ -3962,7 +3962,7 @@ func.func @map_iterated_yield_not_map_info(%lb : index, %ub : index, %st : index
omp.yield(%addr : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{'omp.target_enter_data' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
- omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_enter_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -3974,7 +3974,7 @@ func.func @map_iterated_yield_not_map_info_exit(%lb : index, %ub : index, %st :
omp.yield(%addr : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{'omp.target_exit_data' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
- omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_exit_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -3988,7 +3988,7 @@ func.func @target_enter_data_map_iterated_invalid_from(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{to and alloc map types are permitted}}
- omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_enter_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4002,7 +4002,7 @@ func.func @target_exit_data_map_iterated_invalid_to(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{from, release and delete map types are permitted}}
- omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_exit_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4016,7 +4016,7 @@ func.func @target_update_map_iterated_invalid_delete(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{at least one of to or from map types must be specified, other map types are not permitted}}
- omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.target_update map_iterated(%it : !omp.iterated<!llvm.ptr>)
return
}
@@ -4031,7 +4031,7 @@ func.func @target_update_map_iterated_invalid_conflict(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{either to or from map types can be specified, not both}}
- omp.target_update map_entries(%mapv, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ omp.target_update map_entries(%mapv : !llvm.ptr) map_iterated(%it : !omp.iterated<!llvm.ptr>)
return
}
@@ -4045,7 +4045,7 @@ func.func @target_data_map_iterated_invalid_delete(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{to, from, tofrom and alloc map types are permitted}}
- omp.target_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4060,9 +4060,9 @@ func.func @target_map_iterated_invalid_delete(%lb : index, %ub : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{to, from, tofrom and alloc map types are permitted}}
- omp.target map_entries(%mapv -> %arg0 : !llvm.ptr) {
+ omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%mapv -> %arg0 : !llvm.ptr) {
omp.terminator
- } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ }
return
}
@@ -4071,7 +4071,7 @@ func.func @target_map_iterated_invalid_delete(%lb : index, %ub : index,
omp.declare_mapper @declare_mapper_iterated_not_iterator : !llvm.struct<"mapper_type", (i32)> {
^bb0(%arg: !llvm.ptr, %it: !omp.iterated<!llvm.ptr>):
// expected-error @below {{'omp.declare_mapper.info' op 'map_iterated' arguments must be defined by 'omp.iterator' ops}}
- omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.declare_mapper.info map_iterated(%it : !omp.iterated<!llvm.ptr>)
}
// -----
@@ -4085,7 +4085,7 @@ omp.declare_mapper @declare_mapper_iterated_yield_not_map_info : !llvm.struct<"m
omp.yield(%arg : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error @below {{'omp.declare_mapper.info' op 'map_iterated' iterator body must yield a value defined by 'omp.map.info'}}
- omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.declare_mapper.info map_iterated(%it : !omp.iterated<!llvm.ptr>)
}
// -----
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 4036e5b5e9ff5..8d1ae7c832a1c 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -1015,8 +1015,8 @@ omp.declare_mapper @my_mapper_iterated : !llvm.struct<"my_iter_type", (i32)> {
%decl_map_info = omp.map.info var_ptr(%arg : !llvm.ptr, !llvm.struct<"my_iter_type", (i32)>) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.yield(%decl_map_info : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.declare_mapper.info map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
- omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+ // CHECK: omp.declare_mapper.info map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.declare_mapper.info map_iterated(%it : !omp.iterated<!llvm.ptr>)
}
// CHECK-LABEL: func @wsloop_reduction
@@ -4054,8 +4054,8 @@ func.func @omp_target_update_map_iterated(%lb : index, %ub : index, %step : inde
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.target_update map_entries(%[[MAP]], %[[IT]] : !llvm.ptr, !omp.iterated<!llvm.ptr>)
- omp.target_update map_entries(%map, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>)
+ // CHECK: omp.target_update map_entries(%[[MAP]] : !llvm.ptr) map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_update map_entries(%map : !llvm.ptr) map_iterated(%it : !omp.iterated<!llvm.ptr>)
return
}
@@ -4072,8 +4072,8 @@ func.func @omp_target_enter_data_map_iterated(%lb : index, %ub : index, %step :
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.target_enter_data map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
- omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ // CHECK: omp.target_enter_data map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_enter_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4090,8 +4090,8 @@ func.func @omp_target_exit_data_map_iterated(%lb : index, %ub : index, %step : i
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.target_exit_data map_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
- omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ // CHECK: omp.target_exit_data map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_exit_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4108,8 +4108,8 @@ func.func @omp_target_data_map_iterated(%lb : index, %ub : index, %step : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.target_data map_entries(%{{.*}}, %[[IT]] : !llvm.ptr, !omp.iterated<!llvm.ptr>)
- omp.target_data map_entries(%map, %it : !llvm.ptr, !omp.iterated<!llvm.ptr>) {}
+ // CHECK: omp.target_data map_entries(%{{.*}} : !llvm.ptr) map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>)
+ omp.target_data map_entries(%map : !llvm.ptr) map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
@@ -4127,11 +4127,11 @@ func.func @omp_target_map_iterated(%lb : index, %ub : index, %step : index,
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // CHECK: omp.target map_entries(%[[MAP]] -> %{{.*}} : !llvm.ptr) {
+ // CHECK: omp.target map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] -> %{{.*}} : !llvm.ptr) {
// CHECK: omp.terminator
- // CHECK: } map_iterated_entries(%[[IT]] : !omp.iterated<!llvm.ptr>)
- omp.target map_entries(%map -> %arg0 : !llvm.ptr) {
+ // CHECK: }
+ omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%map -> %arg0 : !llvm.ptr) {
omp.terminator
- } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ }
return
}
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index c55117a81f7cc..769a7652df797 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -506,7 +506,7 @@ llvm.func @target_enter_data_map_iterator(%addr : !llvm.ptr) {
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_enter_data operation}}
// expected-error at below {{LLVM Translation failed for operation: omp.target_enter_data}}
- omp.target_enter_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_enter_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
llvm.return
}
@@ -522,7 +522,7 @@ llvm.func @target_exit_data_map_iterator(%addr : !llvm.ptr) {
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_exit_data operation}}
// expected-error at below {{LLVM Translation failed for operation: omp.target_exit_data}}
- omp.target_exit_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_exit_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
llvm.return
}
@@ -538,7 +538,7 @@ llvm.func @target_update_map_iterator(%addr : !llvm.ptr) {
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_update operation}}
// expected-error at below {{LLVM Translation failed for operation: omp.target_update}}
- omp.target_update map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.target_update map_iterated(%it : !omp.iterated<!llvm.ptr>)
llvm.return
}
@@ -554,7 +554,7 @@ llvm.func @target_data_map_iterator(%addr : !llvm.ptr) {
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target_data operation}}
// expected-error at below {{LLVM Translation failed for operation: omp.target_data}}
- omp.target_data map_entries(%it : !omp.iterated<!llvm.ptr>) {}
+ omp.target_data map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
llvm.return
}
@@ -571,9 +571,9 @@ llvm.func @target_map_iterator(%addr : !llvm.ptr) {
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target operation}}
// expected-error at below {{LLVM Translation failed for operation: omp.target}}
- omp.target map_entries(%map -> %arg0 : !llvm.ptr) {
+ omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%map -> %arg0 : !llvm.ptr) {
omp.terminator
- } map_iterated_entries(%it : !omp.iterated<!llvm.ptr>)
+ }
llvm.return
}
@@ -590,7 +590,7 @@ module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
// expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.declare_mapper.info operation}}
- omp.declare_mapper.info map_entries(%it : !omp.iterated<!llvm.ptr>)
+ omp.declare_mapper.info map_iterated(%it : !omp.iterated<!llvm.ptr>)
}
llvm.func @target_data_mapper_iterator(%addr : !llvm.ptr) {
>From 756c517fe3100bdfe8f50e402f4cd4a4dd893cb7 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 13 May 2026 12:32:49 -0500
Subject: [PATCH 4/6] Require explicit yield in iterator op
Remove the implicit terminator trait from omp.iterator so iterator
modifiers must explicitly yield the value used to form the iterated list.
Add and update verfier and test accordingly.
---
mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td | 4 +---
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 13 +++++--------
mlir/test/Dialect/OpenMP/invalid.mlir | 9 +++++++++
mlir/test/Dialect/OpenMP/ops.mlir | 15 +++++++++++++++
4 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
index 21b6b88c57192..feaf3560ff566 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2503,9 +2503,7 @@ def AffinityEntryOp : OpenMP_Op<"affinity_entry", [Pure]> {
// Iterator Op
//===----------------------------------------------------------------------===//
-def IteratorOp : OpenMP_Op<"iterator",
- [AttrSizedOperandSegments,
- SingleBlockImplicitTerminator<"YieldOp">],
+def IteratorOp : OpenMP_Op<"iterator", [AttrSizedOperandSegments],
clauses = [OpenMP_LoopRelatedClause]> {
let summary = "OpenMP iterator modifier";
let description = [{
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index ae730e001e353..39cd776262441 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2401,16 +2401,13 @@ static LogicalResult verifyMapClause(Operation *op, OperandRange mapVars,
"'omp.iterator' ops";
// Check that the iterator body yields a value defined by omp.map.info.
- auto ®ion = iterOp.getRegion();
- if (region.empty())
- continue;
-
- auto yieldOp = dyn_cast<mlir::omp::YieldOp>(region.front().getTerminator());
- if (!yieldOp || yieldOp.getNumOperands() == 0)
+ auto yieldOp = dyn_cast<mlir::omp::YieldOp>(
+ iterOp.getRegion().front().getTerminator());
+ if (!yieldOp || yieldOp.getResults().empty())
continue;
auto yieldedMapInfo =
- yieldOp.getOperand(0).getDefiningOp<mlir::omp::MapInfoOp>();
+ yieldOp.getResults()[0].getDefiningOp<mlir::omp::MapInfoOp>();
if (!yieldedMapInfo)
return op->emitOpError() << "'map_iterated' iterator body must yield "
"a value defined by 'omp.map.info'";
@@ -5216,7 +5213,7 @@ LogicalResult IteratorOp::verify() {
}
Block &b = getRegion().front();
- auto yield = llvm::dyn_cast<omp::YieldOp>(b.getTerminator());
+ auto yield = b.empty() ? nullptr : llvm::dyn_cast<omp::YieldOp>(b.back());
if (!yield)
return emitOpError() << "region must be terminated by omp.yield";
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 3ac880c7817f3..212d318172fd1 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3928,6 +3928,15 @@ func.func @iterator_missing_yield(%lb : index, %ub : index, %st : index) {
// -----
+func.func @iterator_empty_body(%lb : index, %ub : index, %st : index) {
+ // expected-error at +1 {{region must be terminated by omp.yield}}
+ %0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
+ } -> !omp.iterated<index>
+ return
+}
+
+// -----
+
func.func @iterator_yield_wrong_num_operands(%lb : index, %ub : index, %st : index) {
// expected-error at +1 {{omp.yield in omp.iterator region must yield exactly one value}}
%0 = omp.iterator(%i: index) = (%lb to %ub step %st) {
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index 8d1ae7c832a1c..bb14954a66d21 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3863,6 +3863,21 @@ func.func @omp_iterator(%s2 : !llvm.struct<(ptr, i64)>) -> () {
return
}
+// CHECK-LABEL: func.func @omp_iterator_explicit_yield
+func.func @omp_iterator_explicit_yield(%value : index) -> () {
+ %lb = arith.constant 0 : index
+ %ub = arith.constant 4 : index
+ %st = arith.constant 1 : index
+
+ // CHECK: omp.iterator(%{{.*}}: index) = (%{{.*}} to %{{.*}} step %{{.*}}) {
+ // CHECK: omp.yield(%{{.*}} : index)
+ // CHECK: } -> !omp.iterated<index>
+ %0 = omp.iterator(%iv: index) = (%lb to %ub step %st) {
+ omp.yield(%value : index)
+ } -> !omp.iterated<index>
+ return
+}
+
// CHECK-LABEL: func.func @omp_iterator_2d
func.func @omp_iterator_2d(%s2 : !llvm.struct<(ptr, i64)>) -> () {
// CHECK: %[[IT:.*]] = omp.iterator(%[[IV0:.*]]: index, %[[IV1:.*]]: index) =
>From 9b5d10f761a62b054cdbbf0562d382ef0911d411 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 13 May 2026 13:12:21 -0500
Subject: [PATCH 5/6] Fix operandSegmentSizes mismatch after rebase
---
mlir/test/Dialect/OpenMP/invalid.mlir | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 212d318172fd1..32d90f1e81758 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3017,7 +3017,7 @@ func.func @target_private_count_mismatch(%arg0: !llvm.ptr) {
"omp.target"(%arg0) ({
^bb0(%arg1 : !llvm.ptr):
omp.terminator
- }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
+ }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
return
}
>From d9e26c45a583013ff5504d888ff6bda141212e92 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Wed, 13 May 2026 13:24:45 -0500
Subject: [PATCH 6/6] Reject target map iterators without captures
Reject target map iterators until the follow-up capture-binding
representation is added since currently map_iterated on omp.target
only represents the dynamic map list and does not consider the
target-region arguments required by IsolatedFromAbove.
---
.../Optimizer/OpenMP/FunctionFiltering.cpp | 1 -
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 5 ++++
mlir/test/Dialect/OpenMP/invalid.mlir | 10 ++++----
mlir/test/Dialect/OpenMP/ops.mlir | 23 -------------------
mlir/test/Target/LLVMIR/openmp-todo.mlir | 19 ---------------
5 files changed, 10 insertions(+), 48 deletions(-)
diff --git a/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp b/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
index 70746b3612f76..b78b33f31b142 100644
--- a/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
+++ b/flang/lib/Optimizer/OpenMP/FunctionFiltering.cpp
@@ -311,7 +311,6 @@ class FunctionFilteringPass
targetOp.setDependKindsAttr(nullptr);
targetOp.getDependIteratedMutable().clear();
targetOp.setDependIteratedKindsAttr(nullptr);
- targetOp.getMapIteratedMutable().clear();
targetOp.getDeviceMutable().clear();
targetOp.getIfExprMutable().clear();
targetOp.getDynGroupprivateSizeMutable().clear();
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 39cd776262441..04eb1c87e7b79 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2603,6 +2603,11 @@ LogicalResult TargetOp::verify() {
getHasDeviceAddrVars())))
return failure();
+ if (!getMapIterated().empty())
+ return emitOpError()
+ << "'map_iterated' is not yet supported on 'omp.target' without "
+ "target-region capture bindings";
+
if (failed(verifyMapClause(*this, getMapVars(), getMapIterated())))
return failure();
diff --git a/mlir/test/Dialect/OpenMP/invalid.mlir b/mlir/test/Dialect/OpenMP/invalid.mlir
index 32d90f1e81758..607b0a8f97268 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -4060,15 +4060,15 @@ func.func @target_data_map_iterated_invalid_delete(%lb : index, %ub : index,
// -----
-func.func @target_map_iterated_invalid_delete(%lb : index, %ub : index,
- %st : index,
- %addr : !llvm.ptr) {
+func.func @target_map_iterated_unsupported(%lb : index, %ub : index,
+ %st : index,
+ %addr : !llvm.ptr) {
%mapv = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
%it = omp.iterator(%iv: index) = (%lb to %ub step %st) {
- %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(delete) capture(ByRef) -> !llvm.ptr {name = ""}
+ %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
omp.yield(%m : !llvm.ptr)
} -> !omp.iterated<!llvm.ptr>
- // expected-error @below {{to, from, tofrom and alloc map types are permitted}}
+ // expected-error @below {{'map_iterated' is not yet supported on 'omp.target' without target-region capture bindings}}
omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%mapv -> %arg0 : !llvm.ptr) {
omp.terminator
}
diff --git a/mlir/test/Dialect/OpenMP/ops.mlir b/mlir/test/Dialect/OpenMP/ops.mlir
index bb14954a66d21..22d40c3ceb1b5 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -4127,26 +4127,3 @@ func.func @omp_target_data_map_iterated(%lb : index, %ub : index, %step : index,
omp.target_data map_entries(%map : !llvm.ptr) map_iterated(%it : !omp.iterated<!llvm.ptr>) {}
return
}
-
-// -----
-
-// CHECK-LABEL: func.func @omp_target_map_iterated
-func.func @omp_target_map_iterated(%lb : index, %ub : index, %step : index,
- %addr : !llvm.ptr) -> () {
- // CHECK: %[[MAP:.*]] = omp.map.info
- %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
-
- // CHECK: %[[IT:.*]] = omp.iterator
- %it = omp.iterator(%iv: index) = (%lb to %ub step %step) {
- %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
- omp.yield(%m : !llvm.ptr)
- } -> !omp.iterated<!llvm.ptr>
-
- // CHECK: omp.target map_iterated(%[[IT]] : !omp.iterated<!llvm.ptr>) map_entries(%[[MAP]] -> %{{.*}} : !llvm.ptr) {
- // CHECK: omp.terminator
- // CHECK: }
- omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%map -> %arg0 : !llvm.ptr) {
- omp.terminator
- }
- return
-}
diff --git a/mlir/test/Target/LLVMIR/openmp-todo.mlir b/mlir/test/Target/LLVMIR/openmp-todo.mlir
index 769a7652df797..6efb8005dbe29 100644
--- a/mlir/test/Target/LLVMIR/openmp-todo.mlir
+++ b/mlir/test/Target/LLVMIR/openmp-todo.mlir
@@ -560,25 +560,6 @@ llvm.func @target_data_map_iterator(%addr : !llvm.ptr) {
// -----
-llvm.func @target_map_iterator(%addr : !llvm.ptr) {
- %c0 = llvm.mlir.constant(0 : i64) : i64
- %c10 = llvm.mlir.constant(10 : i64) : i64
- %c1 = llvm.mlir.constant(1 : i64) : i64
- %map = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
- %it = omp.iterator(%iv: i64) = (%c0 to %c10 step %c1) {
- %m = omp.map.info var_ptr(%addr : !llvm.ptr, i32) map_clauses(tofrom) capture(ByRef) -> !llvm.ptr {name = ""}
- omp.yield(%m : !llvm.ptr)
- } -> !omp.iterated<!llvm.ptr>
- // expected-error at below {{not yet implemented: Unhandled clause map/motion clause with iterator modifier in omp.target operation}}
- // expected-error at below {{LLVM Translation failed for operation: omp.target}}
- omp.target map_iterated(%it : !omp.iterated<!llvm.ptr>) map_entries(%map -> %arg0 : !llvm.ptr) {
- omp.terminator
- }
- llvm.return
-}
-
-// -----
-
module attributes {omp.target_triples = ["amdgcn-amd-amdhsa"]} {
omp.declare_mapper @mapper_with_iterator : !llvm.struct<"mapper_type", (i32)> {
^bb0(%arg: !llvm.ptr):
More information about the Mlir-commits
mailing list