[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