[Mlir-commits] [flang] [mlir] [mlir][OpenMP] Add iterator support to map/motion clause (PR #197047)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu May 14 20:19:35 PDT 2026
https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/197047
>From e2bdf2c22334fb1f38e8081e364d1eef14dbf5a5 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 fc40e650d9538..687bce4850b39 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);
@@ -1490,10 +1491,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;
@@ -1583,10 +1584,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(), {}, {});
@@ -1666,10 +1667,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 834ced682a34d..75cf051a1e908 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -263,7 +263,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 ff880755b63a6..dc8af31e9d8ae 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1656,12 +1656,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
}];
@@ -2078,12 +2079,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 ecf71480201f7..2634a5db73893 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(
@@ -2223,6 +2256,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;
@@ -2308,7 +2391,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;
@@ -2389,6 +2473,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();
}
@@ -2448,13 +2552,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");
@@ -2468,7 +2572,7 @@ LogicalResult TargetDataOp::verify() {
getUseDeviceAddrVars())))
return failure();
- return verifyMapClause(*this, getMapVars());
+ return verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2483,15 +2587,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());
}
//===----------------------------------------------------------------------===//
@@ -2505,15 +2610,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());
}
//===----------------------------------------------------------------------===//
@@ -2527,15 +2633,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());
}
//===----------------------------------------------------------------------===//
@@ -2556,7 +2663,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);
@@ -2572,7 +2679,7 @@ LogicalResult TargetOp::verify() {
getHasDeviceAddrVars())))
return failure();
- if (failed(verifyMapClause(*this, getMapVars())))
+ if (failed(verifyMapClause(*this, getMapVars(), getMapIterated())))
return failure();
if (failed(verifyDynGroupprivateClause(
@@ -3433,7 +3540,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 8a7735ba4ae30..0b4f2f727cfb6 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 f22b05c6c9a46..56a3dcd94bb5c 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
}
@@ -2504,7 +2504,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
}
@@ -2606,7 +2606,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"() : () -> ()
}
@@ -3958,6 +3958,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}
@@ -3965,6 +3998,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 cbfa62c575a04..af09c77606338 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 = ""}
@@ -4016,3 +4016,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 096bae0c90a6b312124979682561a721a9861463 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 | 167 ++++++++++--------
.../OpenMP/OpenMPToLLVMIRTranslation.cpp | 6 +
mlir/test/Dialect/OpenMP/invalid.mlir | 116 +++++++++++-
mlir/test/Dialect/OpenMP/ops.mlir | 18 ++
mlir/test/Target/LLVMIR/openmp-todo.mlir | 24 +++
5 files changed, 252 insertions(+), 79 deletions(-)
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 2634a5db73893..c605fc2216b2c 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2391,82 +2391,92 @@ static ParseResult parseCaptureType(OpAsmParser &parser,
return success();
}
-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;
-
- for (auto mapOp : mapVars) {
- if (!mapOp.getDefiningOp())
- 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);
- bool attach = mapTypeToBool(mapTypeBits, ClauseMapFlags::attach);
+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);
+ bool attach = mapTypeToBool(mapTypeBits, ClauseMapFlags::attach);
+
+ 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 ((isa<TargetDataOp>(op) || isa<TargetOp>(op)) && del)
- return emitError(op->getLoc(),
- "to, from, tofrom and alloc map types are permitted");
+ if (!to && !from && !attach) {
+ return emitError(
+ op->getLoc(),
+ "at least one of to or from or attach map types must be "
+ "specified, other map types are not permitted");
+ }
- if (isa<TargetEnterDataOp>(op) && (from || del))
- return emitError(op->getLoc(), "to and alloc map types are permitted");
+ auto updateVar = mapInfoOp.getVarPtr();
- if (isa<TargetExitDataOp>(op) && to)
- return emitError(op->getLoc(),
- "from, release and delete map types are permitted");
+ 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 (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 (always || close || implicit) {
+ return emitError(
+ op->getLoc(),
+ "present, mapper and iterator map type modifiers are permitted");
+ }
- if (!to && !from && !attach) {
- return emitError(
- op->getLoc(),
- "at least one of to or from or attach map types must be "
- "specified, other map types are not permitted");
- }
+ // It's possible we have an attach map, in which case if there is no to
+ // or from tied to it, we skip insertion.
+ if (to || from) {
+ to ? updateToVars.insert(updateVar) : updateFromVars.insert(updateVar);
+ }
+ }
- auto updateVar = mapInfoOp.getVarPtr();
+ if ((mapInfoOp.getVarPtrPtr() && !mapInfoOp.getVarPtrPtrType()) ||
+ (!mapInfoOp.getVarPtrPtr() && mapInfoOp.getVarPtrPtrType())) {
+ return emitError(op->getLoc(),
+ "if varPtrPtr or varPtrPtrType is specified, then both "
+ "must be present");
+ }
- 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");
- }
+ return success();
+}
- if (always || close || implicit) {
- return emitError(
- op->getLoc(),
- "present, mapper and iterator map type modifiers are permitted");
- }
+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;
- // It's possible we have an attach map, in which case if there is no to
- // or from tied to it, we skip insertion.
- if (to || from) {
- to ? updateToVars.insert(updateVar)
- : updateFromVars.insert(updateVar);
- }
- }
+ for (auto mapOp : mapVars) {
+ if (!mapOp.getDefiningOp())
+ return emitError(op->getLoc(), "missing map operation");
- if ((mapInfoOp.getVarPtrPtr() && !mapInfoOp.getVarPtrPtrType()) ||
- (!mapInfoOp.getVarPtrPtr() && mapInfoOp.getVarPtrPtrType())) {
- return emitError(
- op->getLoc(),
- "if varPtrPtr or varPtrPtrType is specified, then both "
- "must be present");
- }
+ if (auto mapInfoOp = mapOp.getDefiningOp<mlir::omp::MapInfoOp>()) {
+ 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");
@@ -2482,15 +2492,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 0b4f2f727cfb6..58936c933b4aa 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.
@@ -6308,6 +6311,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 56a3dcd94bb5c..00412db35e8f9 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3025,11 +3025,11 @@ func.func @target_undefined_privatizer(%arg0: index) {
func.func @target_private_count_mismatch(%arg0: !llvm.ptr) {
// expected-error @below {{inconsistent number of private variables and privatizer op symbols, private vars: 1 vs. privatizer op symbols: 2}}
- "omp.target"(%arg0) ({
+ "omp.target"(%arg0) <{operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
+ private_syms = [@x.privatizer, @y.privatizer]}> ({
^bb0(%arg1 : !llvm.ptr):
omp.terminator
- }) {operandSegmentSizes = array<i32: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0>,
- private_syms = [@x.privatizer, @y.privatizer]} : (!llvm.ptr) -> ()
+ }) : (!llvm.ptr) -> ()
return
}
@@ -3991,6 +3991,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}
@@ -3998,7 +4107,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 af09c77606338..c79c1dc551eef 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 7fab3586720b16bc163f481051affc6df871f18d 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 | 7 +-
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 101 +++---------------
.../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, 62 insertions(+), 140 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 75cf051a1e908..2d4a570493171 100644
--- a/flang/lib/Utils/OpenMP.cpp
+++ b/flang/lib/Utils/OpenMP.cpp
@@ -262,9 +262,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 dc8af31e9d8ae..bf4bc7d945802 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -1657,12 +1657,12 @@ def TargetOp : OpenMP_Op<"target", traits = [
}] # clausesExtraClassDeclaration;
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
}];
@@ -2089,6 +2089,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 c605fc2216b2c..128e29541e0d2 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(
@@ -2256,56 +2224,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;
@@ -2426,10 +2344,9 @@ static LogicalResult verifyMapInfoForMapClause(
}
if (!to && !from && !attach) {
- return emitError(
- op->getLoc(),
- "at least one of to or from or attach map types must be "
- "specified, other map types are not permitted");
+ return emitError(op->getLoc(),
+ "at least one of to or from or attach map types must be "
+ "specified, other map types are not permitted");
}
auto updateVar = mapInfoOp.getVarPtr();
@@ -3556,6 +3473,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 58936c933b4aa..83c55bebabff9 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 00412db35e8f9..76167c12e24a0 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3961,7 +3961,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
}
@@ -3973,7 +3973,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
}
@@ -3985,7 +3985,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
}
@@ -3999,7 +3999,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
}
@@ -4013,7 +4013,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
}
@@ -4027,7 +4027,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
}
@@ -4042,7 +4042,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
}
@@ -4056,7 +4056,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
}
@@ -4071,9 +4071,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
}
@@ -4082,7 +4082,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>)
}
// -----
@@ -4096,7 +4096,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 c79c1dc551eef..4910937758163 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
@@ -4052,8 +4052,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
}
@@ -4070,8 +4070,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
}
@@ -4088,8 +4088,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
}
@@ -4106,8 +4106,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
}
@@ -4125,11 +4125,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 3620ec1ec41de2321e99971de1562de0011428bd 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 bf4bc7d945802..bd5f387f54316 100644
--- a/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
+++ b/mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td
@@ -2509,9 +2509,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 128e29541e0d2..0319acb81bc30 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2408,16 +2408,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'";
@@ -5223,7 +5220,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 76167c12e24a0..16a556f78eaaf 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3939,6 +3939,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 4910937758163..fc04ad3ea26f1 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -3861,6 +3861,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 5d5a373372d44054373ccdd1f9f6d0b639cf5020 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 5/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 0319acb81bc30..858fd7c39cb84 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -2610,6 +2610,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 16a556f78eaaf..ee65e257312b4 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -4071,15 +4071,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 fc04ad3ea26f1..60d9810823faf 100644
--- a/mlir/test/Dialect/OpenMP/ops.mlir
+++ b/mlir/test/Dialect/OpenMP/ops.mlir
@@ -4125,26 +4125,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):
>From 26491bb52d940b3c4a80eb232dd7821fdaef1ed3 Mon Sep 17 00:00:00 2001
From: "Chi Chun, Chen" <chichun.chen at hpe.com>
Date: Thu, 14 May 2026 00:21:31 -0500
Subject: [PATCH 6/6] Remove unrelated empty line
---
mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
index 858fd7c39cb84..902336ddd64bb 100644
--- a/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
+++ b/mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
@@ -1321,7 +1321,6 @@ static ParseResult parseTargetOpRegion(
args.mapArgs.emplace(mapVars, mapTypes);
args.privateArgs.emplace(privateVars, privateTypes, privateSyms,
privateNeedsBarrier, &privateMaps);
-
return parseBlockArgRegion(parser, region, args);
}
More information about the Mlir-commits
mailing list