[flang-commits] [flang] [flang][OpenMP] Support custom mappers in target update to/from clauses (PR #169673)

Krish Gupta via flang-commits flang-commits at lists.llvm.org
Thu Nov 27 11:02:56 PST 2025


https://github.com/KrxGu updated https://github.com/llvm/llvm-project/pull/169673

>From b2a07c5763d28c9bb20a948433223c98fedc200e Mon Sep 17 00:00:00 2001
From: Krish Gupta <krishgupta at Krishs-MacBook-Air.local>
Date: Wed, 26 Nov 2025 21:43:27 +0530
Subject: [PATCH 1/3] [flang][OpenMP] Support mappers in target update to/from

Fixes #168701
---
 flang/lib/Semantics/resolve-names.cpp         | 60 +++++++++++++++++++
 .../Lower/OpenMP/target-update-mapper.f90     | 52 ++++++++++++++++
 .../Semantics/OpenMP/target-update-mapper.f90 | 54 +++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 flang/test/Lower/OpenMP/target-update-mapper.f90
 create mode 100644 flang/test/Semantics/OpenMP/target-update-mapper.f90

diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 2a487a6d39d51..ca17767dce924 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1631,6 +1631,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
     return true;
   }
   bool Pre(const parser::OmpMapClause &);
+  bool Pre(const parser::OmpClause::To &);
+  bool Pre(const parser::OmpClause::From &);
 
   bool Pre(const parser::OpenMPSectionsConstruct &) {
     PushScope(Scope::Kind::OtherConstruct, nullptr);
@@ -1876,6 +1878,64 @@ bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
   return true;
 }
 
+bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
+  // Resolve mapper names in "to" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      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);
+      }
+    }
+  }
+  return true;
+}
+
+bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
+  // Resolve mapper names in "from" clauses (e.g., for target update)
+  auto &mods{OmpGetModifiers(x.v)};
+  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
+    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
+      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);
+      }
+    }
+  }
+  return true;
+}
+
 void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
     const parser::OmpClauseList &clauses) {
   // This "manually" walks the tree of the construct, because we need
diff --git a/flang/test/Lower/OpenMP/target-update-mapper.f90 b/flang/test/Lower/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..d49ad51343679
--- /dev/null
+++ b/flang/test/Lower/OpenMP/target-update-mapper.f90
@@ -0,0 +1,52 @@
+! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  ! CHECK-LABEL: omp.declare_mapper @_QQFcustom : !fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
+
+  type(typ) :: t
+
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Test target update to with custom mapper
+  ! CHECK: %[[T_VAR:.*]] = fir.declare %{{.*}} {uniq_name = "_QFtarget_update_mapperEt"} : (!fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
+  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[T_VAR]] : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO]] : {{.*}})
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Test target update from with custom mapper
+  ! CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO2]] : {{.*}})
+  !$omp target update from(mapper(custom): t)
+
+  ! Test target update to with default mapper
+  ! CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtyp_omp_default_mapper) -> {{.*}}
+  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO3]] : {{.*}})
+  !$omp target update to(mapper(default): t)
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+end program target_update_mapper
diff --git a/flang/test/Semantics/OpenMP/target-update-mapper.f90 b/flang/test/Semantics/OpenMP/target-update-mapper.f90
new file mode 100644
index 0000000000000..f03496e155568
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/target-update-mapper.f90
@@ -0,0 +1,54 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
+
+! Test mapper usage in target update to/from clauses
+
+program target_update_mapper
+  implicit none
+
+  integer, parameter :: n = 4
+
+  type :: typ
+    integer, allocatable :: a(:)
+    integer, allocatable :: b(:)
+  end type typ
+
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  type(typ) :: t
+  integer :: not_a_mapper
+  allocate(t%a(n), source=1)
+  allocate(t%b(n), source=2)
+
+  !$omp target enter data map(alloc: t)
+
+  ! Valid: using custom mapper with target update to
+  t%a = 42
+  !$omp target update to(mapper(custom): t)
+
+  !$omp target
+    t%a(:) = t%a(:) / 2
+    t%b(:) = -1
+  !$omp end target
+
+  ! Valid: using custom mapper with target update from
+  !$omp target update from(mapper(custom): t)
+
+  ! Valid: using default mapper explicitly
+  !$omp target update to(mapper(default): t)
+
+  print*, t%a
+  print*, t%b
+
+  !$omp target exit data map(delete: t)
+  deallocate(t%a)
+  deallocate(t%b)
+
+  ! Test error case: undefined mapper
+  !ERROR: 'undefined_mapper' not declared
+  !$omp target update to(mapper(undefined_mapper): t)
+
+  ! Test error case: wrong kind of symbol
+  !ERROR: Name 'not_a_mapper' should be a mapper name
+  !$omp target update from(mapper(not_a_mapper): t)
+
+end program target_update_mapper

>From f3782239b434b9fd8b1219bfebc8e3a1dfbeaeba Mon Sep 17 00:00:00 2001
From: Krish Gupta <krishgupta at Krishs-MacBook-Air.local>
Date: Wed, 26 Nov 2025 22:37:45 +0530
Subject: [PATCH 2/3] [flang][OpenMP] Implement mapper lowering for target
 update

Support mapper modifier in processMotionClauses for to/from clauses
---
 flang/lib/Lower/OpenMP/ClauseProcessor.cpp    | 29 ++++++++++++++-----
 .../Lower/OpenMP/target-update-mapper.f90     |  9 +++---
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
index dd0cb3c42ba26..f9490555644b2 100644
--- a/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/ClauseProcessor.cpp
@@ -1548,21 +1548,34 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
     mlir::Location clauseLocation = converter.genLocation(source);
     const auto &[expectation, mapper, iterator, objects] = clause.t;
 
-    // TODO Support motion modifiers: mapper, iterator.
-    if (mapper) {
-      TODO(clauseLocation, "Mapper modifier is not supported yet");
-    } else if (iterator) {
-      TODO(clauseLocation, "Iterator modifier is not supported yet");
-    }
-
     mlir::omp::ClauseMapFlags mapTypeBits =
         std::is_same_v<llvm::remove_cvref_t<decltype(clause)>, omp::clause::To>
             ? mlir::omp::ClauseMapFlags::to
             : mlir::omp::ClauseMapFlags::from;
     if (expectation && *expectation == omp::clause::To::Expectation::Present)
       mapTypeBits |= mlir::omp::ClauseMapFlags::present;
+
+    // Support motion modifiers: mapper, iterator.
+    std::string mapperIdName = "__implicit_mapper";
+    if (mapper) {
+      // Only one mapper is allowed by the parser here.
+      assert(mapper->size() == 1 && "more than one mapper");
+      const semantics::Symbol *mapperSym = mapper->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());
+      }
+    }
+    if (iterator) {
+      TODO(clauseLocation, "Iterator modifier is not supported yet");
+    }
+
     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/test/Lower/OpenMP/target-update-mapper.f90 b/flang/test/Lower/OpenMP/target-update-mapper.f90
index d49ad51343679..df23ea79c08f2 100644
--- a/flang/test/Lower/OpenMP/target-update-mapper.f90
+++ b/flang/test/Lower/OpenMP/target-update-mapper.f90
@@ -24,9 +24,8 @@ program target_update_mapper
   !$omp target enter data map(alloc: t)
 
   ! Test target update to with custom mapper
-  ! CHECK: %[[T_VAR:.*]] = fir.declare %{{.*}} {uniq_name = "_QFtarget_update_mapperEt"} : (!fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>) -> !fir.ref<!fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>>
-  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%[[T_VAR]] : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
-  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO]] : {{.*}})
+  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
+  ! CHECK: omp.target_update map_entries(%[[MAP_INFO]] : {{.*}})
   t%a = 42
   !$omp target update to(mapper(custom): t)
 
@@ -37,12 +36,12 @@ program target_update_mapper
 
   ! Test target update from with custom mapper
   ! CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
-  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO2]] : {{.*}})
+  ! CHECK: omp.target_update map_entries(%[[MAP_INFO2]] : {{.*}})
   !$omp target update from(mapper(custom): t)
 
   ! Test target update to with default mapper
   ! CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtyp_omp_default_mapper) -> {{.*}}
-  ! CHECK: omp.target_update motion_entries(%[[MAP_INFO3]] : {{.*}})
+  ! CHECK: omp.target_update map_entries(%[[MAP_INFO3]] : {{.*}})
   !$omp target update to(mapper(default): t)
 
   !$omp target exit data map(delete: t)

>From d17b0ca8204a209ba2e55fa92a0cfe62e3982a21 Mon Sep 17 00:00:00 2001
From: Krish Gupta <krishgupta at Krishs-MacBook-Air.local>
Date: Fri, 28 Nov 2025 00:32:22 +0530
Subject: [PATCH 3/3] [flang][OpenMP] Refactor mapper resolution per review

Extract ResolveMapperModifier helper and simplify tests
---
 flang/lib/Semantics/resolve-names.cpp         | 94 ++++++-------------
 flang/test/Lower/OpenMP/declare-mapper.f90    | 34 +++++++
 .../Lower/OpenMP/target-update-mapper.f90     | 51 ----------
 .../Semantics/OpenMP/target-update-mapper.f90 | 36 ++-----
 4 files changed, 67 insertions(+), 148 deletions(-)
 delete mode 100644 flang/test/Lower/OpenMP/target-update-mapper.f90

diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index ca17767dce924..a870d821e830f 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1779,6 +1779,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
   }
 
 private:
+  void ResolveMapperModifier(parser::OmpMapper &mapper);
   void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
       const parser::OmpClauseList &clauses);
   void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec,
@@ -1850,90 +1851,49 @@ void OmpVisitor::Post(const parser::OmpStylizedInstance &x) { //
 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);
-      }
-    }
+    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
   }
   return true;
 }
 
 bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
-  // Resolve mapper names in "to" clauses (e.g., for target update)
   auto &mods{OmpGetModifiers(x.v)};
   if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
-    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
-      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);
-      }
-    }
+    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
   }
   return true;
 }
 
 bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
-  // Resolve mapper names in "from" clauses (e.g., for target update)
   auto &mods{OmpGetModifiers(x.v)};
   if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
-    if (auto *symbol{FindSymbol(currScope(), mapper->v)}) {
-      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;
+    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
+  }
+  return true;
+}
+
+void OmpVisitor::ResolveMapperModifier(parser::OmpMapper &mapper) {
+  if (auto *symbol{FindSymbol(currScope(), mapper.v)}) {
+    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 {
-      // 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);
-      }
+      context().Say(
+          mapper.v.source, "'%s' not declared"_err_en_US, mapper.v.source);
     }
   }
-  return true;
 }
 
 void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
diff --git a/flang/test/Lower/OpenMP/declare-mapper.f90 b/flang/test/Lower/OpenMP/declare-mapper.f90
index 7eda1a4c497be..a2f228811e8f9 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=52 %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,36 @@ program use_module_default_mapper
     a%x = 8
   !$omp end target
 end program use_module_default_mapper
+
+!--- omp-declare-mapper-9.f90
+! Test mapper usage in target update to/from clauses
+program target_update_mapper
+  type :: typ
+    integer :: a
+    integer :: b
+  end type typ
+
+  !CHECK: omp.declare_mapper @_QQFtarget_update_mapperFtyp_omp_default_mapper : !fir.type<_QFtarget_update_mapperTtyp{a:i32,b:i32}>
+  !CHECK: omp.declare_mapper @_QQFtarget_update_mapperFcustom : !fir.type<_QFtarget_update_mapperTtyp{a:i32,b:i32}>
+
+  !$omp declare mapper(typ :: t) map(t%a, t%b)
+  !$omp declare mapper(custom: typ :: t) map(t%a)
+
+  type(typ) :: t
+
+  ! Test target update to with custom mapper
+  !CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtarget_update_mapperFcustom) -> {{.*}}
+  !CHECK: omp.target_update map_entries(%[[MAP_INFO]] : {{.*}})
+  !$omp target update to(mapper(custom): t)
+
+  ! Test target update from with custom mapper
+  !CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFtarget_update_mapperFcustom) -> {{.*}}
+  !CHECK: omp.target_update map_entries(%[[MAP_INFO2]] : {{.*}})
+  !$omp target update from(mapper(custom): t)
+
+  ! Test target update to with default mapper
+  !CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtarget_update_mapperFtyp_omp_default_mapper) -> {{.*}}
+  !CHECK: omp.target_update map_entries(%[[MAP_INFO3]] : {{.*}})
+  !$omp target update to(mapper(default): t)
+
+end program target_update_mapper
diff --git a/flang/test/Lower/OpenMP/target-update-mapper.f90 b/flang/test/Lower/OpenMP/target-update-mapper.f90
deleted file mode 100644
index df23ea79c08f2..0000000000000
--- a/flang/test/Lower/OpenMP/target-update-mapper.f90
+++ /dev/null
@@ -1,51 +0,0 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
-
-! Test mapper usage in target update to/from clauses
-
-program target_update_mapper
-  implicit none
-
-  integer, parameter :: n = 4
-
-  type :: typ
-    integer, allocatable :: a(:)
-    integer, allocatable :: b(:)
-  end type typ
-
-  !$omp declare mapper(custom: typ :: t) map(t%a)
-
-  ! CHECK-LABEL: omp.declare_mapper @_QQFcustom : !fir.type<_QFTtyp{a:!fir.box<!fir.heap<!fir.array<?xi32>>>,b:!fir.box<!fir.heap<!fir.array<?xi32>>>}>
-
-  type(typ) :: t
-
-  allocate(t%a(n), source=1)
-  allocate(t%b(n), source=2)
-
-  !$omp target enter data map(alloc: t)
-
-  ! Test target update to with custom mapper
-  ! CHECK: %[[MAP_INFO:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
-  ! CHECK: omp.target_update map_entries(%[[MAP_INFO]] : {{.*}})
-  t%a = 42
-  !$omp target update to(mapper(custom): t)
-
-  !$omp target
-    t%a(:) = t%a(:) / 2
-    t%b(:) = -1
-  !$omp end target
-
-  ! Test target update from with custom mapper
-  ! CHECK: %[[MAP_INFO2:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(from) capture(ByRef) mapper(@_QQFcustom) -> {{.*}}
-  ! CHECK: omp.target_update map_entries(%[[MAP_INFO2]] : {{.*}})
-  !$omp target update from(mapper(custom): t)
-
-  ! Test target update to with default mapper
-  ! CHECK: %[[MAP_INFO3:.*]] = omp.map.info var_ptr(%{{.*}} : {{.*}}, {{.*}}) map_clauses(to) capture(ByRef) mapper(@_QQFtyp_omp_default_mapper) -> {{.*}}
-  ! CHECK: omp.target_update map_entries(%[[MAP_INFO3]] : {{.*}})
-  !$omp target update to(mapper(default): t)
-
-  !$omp target exit data map(delete: t)
-  deallocate(t%a)
-  deallocate(t%b)
-
-end program target_update_mapper
diff --git a/flang/test/Semantics/OpenMP/target-update-mapper.f90 b/flang/test/Semantics/OpenMP/target-update-mapper.f90
index f03496e155568..f37d288670594 100644
--- a/flang/test/Semantics/OpenMP/target-update-mapper.f90
+++ b/flang/test/Semantics/OpenMP/target-update-mapper.f90
@@ -1,53 +1,29 @@
 ! RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52
 
-! Test mapper usage in target update to/from clauses
+! Test mapper name resolution in target update to/from clauses
 
 program target_update_mapper
-  implicit none
-
-  integer, parameter :: n = 4
-
   type :: typ
-    integer, allocatable :: a(:)
-    integer, allocatable :: b(:)
+    integer :: a
   end type typ
 
   !$omp declare mapper(custom: typ :: t) map(t%a)
 
   type(typ) :: t
   integer :: not_a_mapper
-  allocate(t%a(n), source=1)
-  allocate(t%b(n), source=2)
 
-  !$omp target enter data map(alloc: t)
-
-  ! Valid: using custom mapper with target update to
-  t%a = 42
+  ! Valid: using custom mapper
   !$omp target update to(mapper(custom): t)
-
-  !$omp target
-    t%a(:) = t%a(:) / 2
-    t%b(:) = -1
-  !$omp end target
-
-  ! Valid: using custom mapper with target update from
   !$omp target update from(mapper(custom): t)
 
-  ! Valid: using default mapper explicitly
+  ! Valid: using default mapper
   !$omp target update to(mapper(default): t)
 
-  print*, t%a
-  print*, t%b
-
-  !$omp target exit data map(delete: t)
-  deallocate(t%a)
-  deallocate(t%b)
-
-  ! Test error case: undefined mapper
+  ! Error: undefined mapper
   !ERROR: 'undefined_mapper' not declared
   !$omp target update to(mapper(undefined_mapper): t)
 
-  ! Test error case: wrong kind of symbol
+  ! Error: wrong kind of symbol
   !ERROR: Name 'not_a_mapper' should be a mapper name
   !$omp target update from(mapper(not_a_mapper): t)
 



More information about the flang-commits mailing list