[flang-commits] [flang] [llvm] [Flang][OpenMP] Enable declare_mapper support for target update (PR #182681)

via flang-commits flang-commits at lists.llvm.org
Sat Feb 21 06:53:47 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics

Author: None (agozillon)

<details>
<summary>Changes</summary>

Currently update from and to don't support declare_mapper usage, this patch just hooks up the pre-existing mapper support to target update so that it can be utilised as it is in regular map cases.

---
Full diff: https://github.com/llvm/llvm-project/pull/182681.diff


4 Files Affected:

- (modified) flang/lib/Lower/OpenMP/ClauseProcessor.cpp (+18-6) 
- (modified) flang/lib/Semantics/resolve-names.cpp (+47-24) 
- (modified) flang/test/Lower/OpenMP/declare-mapper.f90 (+25) 
- (added) offload/test/offloading/fortran/declare-mapper-target-update.f90 (+37) 


``````````diff
diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index e62395676a696..083f63d84a4aa 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1616,12 +1616,23 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
 
   auto callbackFn = [&](const auto &clause, const parser::CharBlock &source) {
     mlir::Location clauseLocation = converter.genLocation(source);
-    const auto &[expectation, mapper, iterator, objects] = clause.t;
+    const auto &[expectation, mappers, iterator, objects] = clause.t;
 
-    // TODO Support motion modifiers: mapper, iterator.
-    if (mapper) {
-      TODO(clauseLocation, "Mapper modifier is not supported yet");
-    } else if (iterator) {
+    std::string mapperIdName = "";
+    if (mappers) {
+      assert(mappers->size() == 1 && "more than one mapper");
+      const semantics::Symbol *mapperSym = mappers->front().v.id().symbol;
+      mapperIdName = mapperSym->name().ToString();
+      if (mapperIdName != "default") {
+        // Mangle with the ultimate owner so that use-associated mapper
+        // identifiers resolve to the same symbol as their defining scope.
+        const semantics::Symbol &ultimate = mapperSym->GetUltimate();
+        mapperIdName = converter.mangleName(mapperIdName, ultimate.owner());
+      }
+    }
+
+    // TODO Support motion modifiers: iterator.
+    if (iterator) {
       TODO(clauseLocation, "Iterator modifier is not supported yet");
     }
 
@@ -1632,7 +1643,8 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
     if (expectation && *expectation == omp::clause::To::Expectation::Present)
       mapTypeBits |= mlir::omp::ClauseMapFlags::present;
     processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
-                      parentMemberIndices, result.mapVars, mapSymbols);
+                      parentMemberIndices, result.mapVars, mapSymbols,
+                      mapperIdName);
   };
 
   bool clauseFound = findRepeatableClause<omp::clause::To>(callbackFn);
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 9036defa0c711..0e5e5d97c5638 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1652,6 +1652,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return true;
   }
   bool Pre(const parser::OmpMapClause &);
+  bool Pre(const parser::OmpFromClause &);
+  bool Pre(const parser::OmpToClause &);
 
   bool Pre(const parser::OpenMPSectionsConstruct &x) {
     PushScopeWithSource(Scope::Kind::OtherConstruct, x.source);
@@ -1804,6 +1806,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
       const parser::OmpClauseList &clauses);
 
   void ResolveCriticalName(const parser::OmpArgument &arg);
+  void ResolveMapperNames(const parser::OmpMapper &mapper);
 
   std::vector<const parser::OpenMPDeclarativeConstruct *> declaratives_;
 };
@@ -1872,33 +1875,53 @@ void OmpVisitor::Post(const parser::OmpStylizedInstance &x) { //
   PopScope();
 }
 
+void OmpVisitor::ResolveMapperNames(const parser::OmpMapper &mapper) {
+  if (auto *symbol{FindSymbol(currScope(), mapper.v)}) {
+    // TODO: Do we need a specific flag or type here, to distinghuish against
+    // other ConstructName things? Leaving this for the full implementation
+    // of mapper lowering.
+    auto &ultimate{symbol->GetUltimate()};
+    auto *misc{ultimate.detailsIf<MiscDetails>()};
+    auto *md{ultimate.detailsIf<MapperDetails>()};
+    if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
+      context().Say(mapper.v.source,
+          "Name '%s' should be a mapper name"_err_en_US, mapper.v.source);
+    else
+      mapper.v.symbol = symbol;
+  } else {
+    // Allow the special 'default' mapper identifier without prior
+    // declaration so lowering can recognize and handle it. Emit an
+    // error for any other missing mapper identifier.
+    if (mapper.v.source.ToString() == "default") {
+      mapper.v.symbol =
+          &MakeSymbol(mapper.v, MiscDetails{MiscDetails::Kind::ConstructName});
+    } else {
+      context().Say(
+          mapper.v.source, "'%s' not declared"_err_en_US, mapper.v.source);
+    }
+  }
+}
+
 bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
   auto &mods{OmpGetModifiers(x)};
   if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
-    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
-      // TODO: Do we need a specific flag or type here, to distinghuish against
-      // other ConstructName things? Leaving this for the full implementation
-      // of mapper lowering.
-      auto &ultimate{symbol->GetUltimate()};
-      auto *misc{ultimate.detailsIf<MiscDetails>()};
-      auto *md{ultimate.detailsIf<MapperDetails>()};
-      if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
-        context().Say(mapper->v.source,
-            "Name '%s' should be a mapper name"_err_en_US, mapper->v.source);
-      else
-        mapper->v.symbol = symbol;
-    } else {
-      // Allow the special 'default' mapper identifier without prior
-      // declaration so lowering can recognize and handle it. Emit an
-      // error for any other missing mapper identifier.
-      if (mapper->v.source.ToString() == "default") {
-        mapper->v.symbol = &MakeSymbol(
-            mapper->v, MiscDetails{MiscDetails::Kind::ConstructName});
-      } else {
-        context().Say(
-            mapper->v.source, "'%s' not declared"_err_en_US, mapper->v.source);
-      }
-    }
+    ResolveMapperNames(*mapper);
+  }
+  return true;
+}
+
+bool OmpVisitor::Pre(const parser::OmpFromClause &x) {
+  auto &mods{OmpGetModifiers(x)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    ResolveMapperNames(*mapper);
+  }
+  return true;
+}
+
+bool OmpVisitor::Pre(const parser::OmpToClause &x) {
+  auto &mods{OmpGetModifiers(x)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    ResolveMapperNames(*mapper);
   }
   return true;
 }
diff --git a/flang/test/Lower/OpenMP/declare-mapper.f90 b/flang/test/Lower/OpenMP/declare-mapper.f90
index 7eda1a4c497be..291787ea8fa0e 100644
--- a/flang/test/Lower/OpenMP/declare-mapper.f90
+++ b/flang/test/Lower/OpenMP/declare-mapper.f90
@@ -11,6 +11,7 @@
 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -J %t %t/omp-declare-mapper-7.use.f90 -o - | FileCheck %t/omp-declare-mapper-7.use.f90
 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -module-dir %t %t/omp-declare-mapper-8.mod.f90 -o - >/dev/null
 ! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -J %t %t/omp-declare-mapper-8.use.f90 -o - | FileCheck %t/omp-declare-mapper-8.use.f90
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %t/omp-declare-mapper-9.f90 -o - | FileCheck %t/omp-declare-mapper-9.f90
 
 !--- omp-declare-mapper-1.f90
 subroutine declare_mapper_1
@@ -360,3 +361,27 @@ program use_module_default_mapper
     a%x = 8
   !$omp end target
 end program use_module_default_mapper
+
+!--- omp-declare-mapper-9.f90
+
+subroutine declare_mapper_9
+   type my_type
+      integer              :: x, y
+   end type
+
+   !CHECK: omp.declare_mapper @[[MY_TYPE_MAPPER2:_QQFdeclare_mapper_9map_y]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_9Tmy_type\{x:i32,y:i32\}>]]
+   !CHECK: omp.declare_mapper @[[MY_TYPE_MAPPER1:_QQFdeclare_mapper_9map_x]] : [[MY_TYPE:!fir\.type<_QFdeclare_mapper_9Tmy_type\{x:i32,y:i32\}>]]
+   !$omp declare mapper (map_x : my_type :: var) map (var%x)
+   !$omp declare mapper (map_y : my_type :: var) map (var%y)
+
+   type(my_type) :: instance
+
+   !CHECK: %[[DECLARE_MAPPER_ENTRY:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(to) capture(ByRef) mapper(@[[MY_TYPE_MAPPER1]]) -> !fir.ref<[[MY_TYPE]]> {name = "instance"}
+   !CHECK: omp.target_update map_entries(%[[DECLARE_MAPPER_ENTRY]] : !fir.ref<[[MY_TYPE]]>)
+
+   !$omp target update to(mapper(map_x) : instance)
+
+   !CHECK: %[[DECLARE_MAPPER_ENTRY2:.*]] = omp.map.info var_ptr(%{{.*}} : !fir.ref<[[MY_TYPE]]>, [[MY_TYPE]]) map_clauses(from) capture(ByRef) mapper(@[[MY_TYPE_MAPPER2]]) -> !fir.ref<[[MY_TYPE]]> {name = "instance"}
+   !CHECK: omp.target_update map_entries(%[[DECLARE_MAPPER_ENTRY2]] : !fir.ref<[[MY_TYPE]]>)
+   !$omp target update from(mapper(map_y) : instance)
+end subroutine declare_mapper_9
\ No newline at end of file
diff --git a/offload/test/offloading/fortran/declare-mapper-target-update.f90 b/offload/test/offloading/fortran/declare-mapper-target-update.f90
new file mode 100644
index 0000000000000..995e7d3c57716
--- /dev/null
+++ b/offload/test/offloading/fortran/declare-mapper-target-update.f90
@@ -0,0 +1,37 @@
+! Test we can correctly utilise declare mapper with update to/from
+! REQUIRES: flang, amdgpu
+
+! RUN: %libomptarget-compile-fortran-run-and-check-generic
+program declare_mapper_update
+   type my_type
+      integer              :: x, y
+   end type
+
+   !$omp declare mapper (map_x : my_type :: var) map (var%x)
+   !$omp declare mapper (map_y : my_type :: var) map (var%y)
+
+   type(my_type) :: instance
+
+   instance%x = 10
+   instance%y = 20
+
+   !$omp target enter data map(to: instance)
+
+   instance%x = 30
+   instance%y = 40
+
+   ! Only update x
+   !$omp target update to(mapper(map_x) : instance)
+
+   ! Pull both x and y back seperately, and print, we 
+   ! should have 30 for x, and 20 for y. As the previous
+   ! update should only have written to x.
+   !$omp target update from(mapper(map_x) : instance)
+   !$omp target update from(mapper(map_y) : instance)
+
+    print *, instance%x
+    print *, instance%y
+end program
+
+!CHECK: 30
+!CHECK: 20

``````````

</details>


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


More information about the flang-commits mailing list