[Mlir-commits] [flang] [mlir] [Flang][OpenMP] Support iterator modifier in map and motion clauses (PR #197757)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Oct 15 22:50:21 PDT 2026


================
@@ -1913,6 +1953,90 @@ void ClauseProcessor::processMapObjects(
   }
 }
 
+// Lower iterator-dependent locators to mapIterated and other locators to
+// mapVars.
+void ClauseProcessor::processMapObjectsWithIterator(
+    lower::StatementContext &stmtCtx, mlir::Location clauseLocation,
+    const omp::ObjectList &objects,
+    llvm::ArrayRef<IteratorRange> iteratorRanges,
+    mlir::omp::ClauseMapFlags mapTypeBits,
+    std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices,
+    mlir::omp::MapClauseOps &result, llvm::SmallVectorImpl<Object> &mapObjects,
+    llvm::StringRef mapperIdNameRef, bool isMotionModifier,
+    llvm::omp::Directive directive) const {
+  if (iteratorRanges.empty()) {
+    processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
+                      parentMemberIndices, result.mapVars, mapObjects,
+                      mapperIdNameRef, isMotionModifier, directive);
+    return;
+  }
+
+  auto declareMapper = mlir::dyn_cast_if_present<mlir::omp::DeclareMapperOp>(
+      converter.getFirOpBuilder().getRegion().getParentOp());
+  auto isDeclareMapperVariable =
+      [&](const IteratorMapObjectAnalysis &analysis) {
+        if (!declareMapper || !analysis.rootSym)
+          return false;
+
+        mlir::Value rootAddress = converter.getSymbolAddress(*analysis.rootSym);
+        while (rootAddress) {
+          if (auto declare = rootAddress.getDefiningOp<hlfir::DeclareOp>()) {
+            rootAddress = declare.getMemref();
+            continue;
+          }
+          if (auto declare = rootAddress.getDefiningOp<fir::DeclareOp>()) {
+            rootAddress = declare.getMemref();
+            continue;
+          }
+          break;
+        }
+
+        return rootAddress == declareMapper.getRegion().front().getArgument(0);
+      };
+
+  constexpr mlir::omp::ClauseMapFlags unsupportedReferenceModifiers =
+      mlir::omp::ClauseMapFlags::ref_ptr | mlir::omp::ClauseMapFlags::ref_ptee |
+      mlir::omp::ClauseMapFlags::attach_always |
+      mlir::omp::ClauseMapFlags::attach_never |
+      mlir::omp::ClauseMapFlags::attach_auto;
+  bool hasUnsupportedReferenceModifier =
+      (mapTypeBits & unsupportedReferenceModifiers) !=
+      mlir::omp::ClauseMapFlags::none;
+
+  // Objects in an iterator-modified clause may independently reference
+  // iterator variables, so handle each object separately.
+  for (const omp::Object &object : objects) {
+    llvm::SmallVector<IteratorRange> objectRanges =
+        getIteratorRangesForObject(object, iteratorRanges);
+    if (!objectRanges.empty()) {
+      if (hasUnsupportedReferenceModifier)
+        TODO(clauseLocation,
+             "iterator modifier with reference or attach modifier");
+      IteratorMapObjectAnalysis analysis = analyzeIteratorMapObject(object);
+      bool isMapperVariable = isDeclareMapperVariable(analysis);
+      if (analysis.isDerivedTypeMember && !isMapperVariable)
+        TODO(clauseLocation, "iterator modifier with derived type member map");
+      if (declareMapper && analysis.rootSym && !isMapperVariable)
+        TODO(clauseLocation,
+             "iterator modifier with locator outside declare mapper variable");
+      if (!analysis.arrayRef)
+        TODO(clauseLocation, "object type not supported by iterator modifier");
+      if (const auto *symbol{object.sym()};
+          symbol && semantics::IsOptional(*symbol))
+        TODO(clauseLocation, "iterator modifier with optional locator");
+      result.mapIterated.push_back(buildIteratedMapEntry(
+          converter, semaCtx, clauseLocation, objectRanges, object,
+          *analysis.arrayRef, mapperIdNameRef, mapTypeBits, directive));
+      continue;
+    }
+
+    omp::ObjectList singleObj{object};
+    processMapObjects(stmtCtx, clauseLocation, singleObj, mapTypeBits,
----------------
MattPD wrote:

Confirmed, the posted case now gets the not-yet-implemented diagnostic.

The assertion `dyn_cast on a non-existent value` is still reachable when the module variable is in a later clause:

```fortran
module later_external
  integer :: tbl(1)
  type :: t
    integer :: a(1)
  end type
  !$omp declare mapper(m: t :: v) &
  !$omp& map(iterator(i=1:1), to: v%a(i)) map(to: tbl(1))
end module
```

This failure may not belong to this PR, though. The second clause has no iterator, and `map(to: v%a(1)) map(to: tbl(1))` fails the same assertion at the base commit 560cd8f. The base commit reports the not-yet-implemented diagnostic for the `later_external` module only because it stops at the first clause.

Other unsupported items in a later clause behave the same way. After an iterator clause on `target enter data`, `map(to: z%re)` stops with `LLVM ERROR: Unsupported type of OpenACC operand`. After an iterator `to` clause, `from(b([1,3]))` is lowered to an update of all of `b`, as it already is without the iterator.

To keep the earlier diagnostic, the checks for unsupported items could run on every clause of the directive or mapper once any clause has an iterator. Otherwise, these failures could be tracked as separate issues.

https://github.com/llvm/llvm-project/pull/197757


More information about the Mlir-commits mailing list