[flang-commits] [flang] [mlir] [mlir][OpenMP] Add iterator support to map/motion clause (PR #197047)
via flang-commits
flang-commits at lists.llvm.org
Mon May 11 16:54:37 PDT 2026
https://github.com/chichunchen updated https://github.com/llvm/llvm-project/pull/197047
>From 71929a16cbc61eb9b54daac56cbc3ad6798d7eaa 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/2] [mlir][OpenMP] Add iterator support to map/motion clause
Extend map/motion clause to support `!omp.iterated<Ty>` handles
alongside map/motion locators.
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 fb5014f3394be..de47786572b75 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -4371,7 +4371,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 40ccff7405799..6d2b8f4b46d5c 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();
}
@@ -2435,13 +2539,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");
@@ -2455,7 +2559,7 @@ LogicalResult TargetDataOp::verify() {
getUseDeviceAddrVars())))
return failure();
- return verifyMapClause(*this, getMapVars());
+ return verifyMapClause(*this, getMapVars(), getMapIterated());
}
//===----------------------------------------------------------------------===//
@@ -2470,15 +2574,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());
}
//===----------------------------------------------------------------------===//
@@ -2492,15 +2597,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());
}
//===----------------------------------------------------------------------===//
@@ -2514,15 +2620,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());
}
//===----------------------------------------------------------------------===//
@@ -2543,7 +2650,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);
@@ -2559,7 +2666,7 @@ LogicalResult TargetOp::verify() {
getHasDeviceAddrVars())))
return failure();
- if (failed(verifyMapClause(*this, getMapVars())))
+ if (failed(verifyMapClause(*this, getMapVars(), getMapIterated())))
return failure();
if (failed(verifyDynGroupprivateClause(
@@ -3401,7 +3508,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 04725a69c8559..c5c1bb1340616 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"() : () -> ()
}
@@ -3512,6 +3512,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}
@@ -3519,6 +3552,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 1d1453e21f9a1f4440fd356f0508942e5f0ac2f9 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/2] 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 6d2b8f4b46d5c..a4d333ffe7940 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 c5c1bb1340616..5acedf3f3cf16 100644
--- a/mlir/test/Dialect/OpenMP/invalid.mlir
+++ b/mlir/test/Dialect/OpenMP/invalid.mlir
@@ -3545,6 +3545,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}
@@ -3552,7 +3661,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
+ }
+}
More information about the flang-commits
mailing list