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

via flang-commits flang-commits at lists.llvm.org
Mon Jul 6 16:52:26 PDT 2026


================
@@ -1350,6 +1350,215 @@ void collectEnclosingConstructTraits(
   std::reverse(constructTraits.begin(), constructTraits.end());
 }
 
+// Lower the stable base entity for an iterator map/motion locator.
+//
+// MapInfoOp stores this base in var_ptr and represents the iterator-selected
+// elements or sections with map bounds computed inside the omp.iterator body.
+// For component array locators such as v%a(i) or v%a(i:i+1), return v%a so each
+// iteration maps offsets from the same base instead of lowering the subscripted
+// component address as the var_ptr.
+static std::optional<hlfir::Entity>
+getIteratorMapEntity(Fortran::lower::AbstractConverter &converter,
+                     fir::FirOpBuilder &builder,
+                     Fortran::semantics::SemanticsContext &semaCtx,
+                     Fortran::lower::StatementContext &stmtCtx,
+                     const omp::Object &object, mlir::Location loc) {
+  const semantics::Symbol *sym = object.sym();
+  assert(sym && "expected symbol for iterator object");
+
+  mlir::Value addr;
+  if (!sym->owner().IsDerivedType()) {
+    // Keep the same base address as ordinary map lowering for non-component
+    // objects.
+    fir::factory::AddrAndBoundsInfo info =
+        Fortran::lower::getDataOperandBaseAddr(converter, builder, *sym, loc,
+                                               /*unwrapFirBox=*/false);
+    addr = info.addr;
+  } else {
+    const std::optional<ExprTy> &ref = object.ref();
+    if (!ref)
+      return std::nullopt;
+
+    auto arrayRef = Fortran::lower::detail::getRef<evaluate::ArrayRef>(*ref);
+    if (!arrayRef)
+      return std::nullopt;
+
+    evaluate::ExpressionAnalyzer ea{semaCtx};
+    std::optional<ExprTy> arrayBase;
+    const evaluate::NamedEntity &base = arrayRef->base();
+    // Component array references carry the component base separately from the
+    // subscript list. Lower that base, e.g. v%a in v%a(i), and leave the
+    // subscript-dependent part to the iterator-local map bounds below.
+    if (const semantics::SymbolRef *symRef = base.UnwrapSymbolRef())
+      arrayBase = ea.Designate(evaluate::DataRef{*symRef});
+    else if (const evaluate::Component *component = base.UnwrapComponent())
+      arrayBase = ea.Designate(evaluate::DataRef{*component});
+    else
+      llvm_unreachable("unexpected NamedEntity");
+
+    assert(arrayBase);
+    // Use mutable-box lowering for allocatable and pointer bases. The shared
+    // descriptor load below turns the box address into a box value.
+    fir::ExtendedValue dataExv;
+    if (semantics::IsAllocatableOrPointer(base.GetLastSymbol()))
+      dataExv = converter.genExprMutableBox(loc, *arrayBase);
+    else
+      dataExv = converter.genExprAddr(loc, *arrayBase, stmtCtx);
+    addr = fir::getBase(dataExv);
+  }
+
+  // Allocatable and pointer locators yield a descriptor address
+  // (!fir.ref<!fir.box<...>>) for both whole objects and components. Load the
+  // descriptor so var_ptr maps the array data, not the descriptor.
+  // Assumed-shape arrays and non-allocatable components are already box values
+  // or plain addresses and need no load.
+  if (fir::isBoxAddress(addr.getType()))
+    addr = fir::LoadOp::create(builder, loc, addr);
----------------
MattPD wrote:

The semantic check and the lowering seem to disagree for descriptor iterator maps. For an assumed-shape `a` with `map(iterator(i=1:n), to: a(i))`, semantics emits a `-Wopenmp-usage` warning:

```
warning: The map of 'a' may include a descriptor that is created locally. Mapping this descriptor without an appropriate TARGET EXIT DATA in the same scope may result in the device retaining an invalid descriptor reference [-Wopenmp-usage]
```

But the lowering here maps only raw data, with no descriptor:

```mlir
%15 = fir.box_addr %1#0 : (!fir.box<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
%16 = omp.map.info var_ptr(%15 : !fir.ref<!fir.array<?xi32>>, i32) map_clauses(to) ... -> !llvm.ptr {name = ""}
```

Is the warning correct for this construct, or should it be adjusted for data-only iterator descriptor maps?

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


More information about the flang-commits mailing list