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

via flang-commits flang-commits at lists.llvm.org
Wed Oct 14 21:22:16 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:

Items not referencing an iterator take the ordinary `processMapObjects` path, which skips the check that the locator is rooted in the declare mapper variable. A module variable among those items then has no address inside the mapper region:

```fortran
module mixed_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), tbl(1))
end module
```

Save this as `repro.f90` and run `flang -c -fopenmp -fopenmp-version=52 repro.f90`. At e3eaf33, Flang fails the assertion `dyn_cast on a non-existent value` in `getDataOperandBaseAddr`. At the base commit 560cd8f, Flang reports the not-yet-implemented diagnostic instead. Without the iterator, `map(to: v%a(1), tbl(1))` fails the same assertion at both commits.

The `external-array` case in `declare-mapper-iterator-unsupported.f90` uses `tbl(i)`, which takes the checked iterator path.

Could the non-iterator items of an iterator-modified mapper clause get the same check? Items rooted in `v` already lower in such a clause.

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


More information about the flang-commits mailing list