[flang-commits] [flang] [llvm] [Flang][OpenMP] Stop implicit declare mapper emission for derived types containing iso_c types (PR #219543)
via flang-commits
flang-commits at lists.llvm.org
Fri Aug 28 10:46:22 PDT 2026
https://github.com/agozillon created https://github.com/llvm/llvm-project/pull/219543
Follow up patch to the previous PR, removing the mapper emission for iso_c types as it should be unrequired as shown by the check-offload test added in the PR. When mapping the derived type we capture the whole object, including the iso_c types that are themselves record types containing an integer for the address.
The overall intent is to try and limit the number of cases where we emit mappers as they can be detrimental to performance in certain cases.
>From 4b280d5422a2352fd4b282a9969ab99dfb3c3b71 Mon Sep 17 00:00:00 2001
From: agozillon <Andrew.Gozillon at amd.com>
Date: Fri, 28 Aug 2026 12:33:28 -0500
Subject: [PATCH] [Flang][OpenMP] Stop implicit declare mapper emission for
derived types containing iso_c types
Follow up patch to the previous PR, removing the mapper emission for iso_c types as it
should be unrequired as shown by the check-offload test added in the PR. When mapping
the derived type we capture the whole object, including the iso_c types that are
themselves record types containing an integer for the address.
---
flang/lib/Lower/OpenMP/Utils.cpp | 6 --
.../OpenMP/default-mapper-iso-c-nested.f90 | 47 --------------
flang/test/Lower/OpenMP/target.f90 | 2 +-
.../fortran/target-map-cptr-cfunptr.f90 | 63 +++++++++++++++++++
4 files changed, 64 insertions(+), 54 deletions(-)
delete mode 100644 flang/test/Lower/OpenMP/default-mapper-iso-c-nested.f90
create mode 100644 offload/test/offloading/fortran/target-map-cptr-cfunptr.f90
diff --git a/flang/lib/Lower/OpenMP/Utils.cpp b/flang/lib/Lower/OpenMP/Utils.cpp
index 4e7cf5ca34cc3..15e64ed7b20f7 100644
--- a/flang/lib/Lower/OpenMP/Utils.cpp
+++ b/flang/lib/Lower/OpenMP/Utils.cpp
@@ -80,12 +80,6 @@ bool requiresImplicitDefaultDeclareMapper(
std::function<bool(const semantics::DerivedTypeSpec &)> requiresMapper =
[&](const semantics::DerivedTypeSpec &spec) -> bool {
- // ISO C interoperable types (e.g., c_ptr, c_funptr) must always have
- // implicit default mappers available so that OpenMP offloading can
- // correctly map them.
- if (semantics::IsIsoCType(&spec))
- return true;
-
if (!visited.insert(&spec).second)
return false;
diff --git a/flang/test/Lower/OpenMP/default-mapper-iso-c-nested.f90 b/flang/test/Lower/OpenMP/default-mapper-iso-c-nested.f90
deleted file mode 100644
index 4a181daf42e4a..0000000000000
--- a/flang/test/Lower/OpenMP/default-mapper-iso-c-nested.f90
+++ /dev/null
@@ -1,47 +0,0 @@
-! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
-
-! Test that an implicit default declare mapper is synthesized for ISO C
-! interoperable types.
-
-program test_iso_c_nested_mapper
- use iso_c_binding, only : c_ptr
- implicit none
-
- type :: dtype
- integer :: id
- type(c_ptr) :: ptr
- end type dtype
-
- type(dtype), allocatable :: arr(:)
-
- allocate(arr(10))
-
- !$omp target map(tofrom: arr)
- arr(1)%id = 1
- !$omp end target
-end program test_iso_c_nested_mapper
-
-subroutine map_cptr_direct
- use iso_c_binding, only : c_ptr
- implicit none
- type(c_ptr) :: p
-
- !$omp target map(tofrom: p)
- !$omp end target
-end subroutine map_cptr_direct
-
-
-! CHECK-LABEL: omp.declare_mapper @_QQM__fortran_builtinsc_ptr_omp_default_mapper
-! CHECK: omp.map.info var_ptr({{.*}}) map_clauses(implicit, tofrom){{.*}}name("")
-! CHECK: omp.map.info var_ptr({{.*}}) map_clauses(implicit){{.*}}members({{.*}}){{.*}}name("") partial_map(true)
-! CHECK: omp.declare_mapper.info map_entries(
-
-! CHECK-LABEL: func.func @_QQmain
-! CHECK: %[[ARR_DATA:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(tofrom){{.*}}var_ptr_ptr(%{{.*}}){{.*}}name("")
-! CHECK: %[[ARR_DESC:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(always, to){{.*}}members(%[[ARR_DATA]] : [0] :{{.*}}){{.*}}name("arr")
-! CHECK: %[[ARR_ATTACH:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(attach, ref_ptr, ref_ptee){{.*}}name("arr")
-! CHECK: omp.target {{.*}}map_entries(%[[ARR_DESC]] -> %{{[^,]*}}, %[[ARR_ATTACH]] -> %{{[^,]*}}, %[[ARR_DATA]] -> %{{[^,]*}} :
-
-! CHECK-LABEL: func.func @_QPmap_cptr_direct
-! CHECK: %[[P_MAP:.*]] = omp.map.info var_ptr(%{{.*}}){{.*}}map_clauses(tofrom){{.*}}mapper(@_QQM__fortran_builtinsc_ptr_omp_default_mapper){{.*}}name("p")
-! CHECK: omp.target {{.*}}map_entries(%[[P_MAP]] -> %{{[^,]*}} :
diff --git a/flang/test/Lower/OpenMP/target.f90 b/flang/test/Lower/OpenMP/target.f90
index f21434b6cedc6..ed24bdbbcd5c5 100644
--- a/flang/test/Lower/OpenMP/target.f90
+++ b/flang/test/Lower/OpenMP/target.f90
@@ -529,7 +529,7 @@ subroutine omp_target_device_ptr
use iso_c_binding, only : c_ptr, c_loc
type(c_ptr) :: a
integer, target :: b
- !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) mapper(@[[CPTR_DEFAULT:_QQM__fortran_builtinsc_ptr_omp_default_mapper]]) name("a") -> {{.*}}
+ !CHECK: %[[MAP:.*]] = omp.map.info var_ptr({{.*}}) map_clauses(tofrom) capture(ByRef) name("a") -> {{.*}}
!CHECK: omp.target_data map_entries(%[[MAP]]{{.*}}) use_device_ptr({{.*}} -> %[[VAL_1:.*]] : !fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>)
!$omp target data map(tofrom: a) use_device_ptr(a)
!CHECK: {{.*}} = fir.coordinate_of %[[VAL_1:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64>
diff --git a/offload/test/offloading/fortran/target-map-cptr-cfunptr.f90 b/offload/test/offloading/fortran/target-map-cptr-cfunptr.f90
new file mode 100644
index 0000000000000..53e5a18714dec
--- /dev/null
+++ b/offload/test/offloading/fortran/target-map-cptr-cfunptr.f90
@@ -0,0 +1,63 @@
+! Offloading test that verifies a type(c_ptr) and type(c_funptr) nested inside
+! a derived type are mapped correctly to the target device, i.e. their
+! underlying address values are transferred intact when the enclosing derived
+! type is mapped. This exercises the handling of ISO C interoperable types
+! nested within derived types across the host/device boundary.
+! REQUIRES: flang, amdgpu
+
+! RUN: %libomptarget-compile-fortran-run-and-check-generic
+program target_map_cptr_cfunptr
+ use iso_c_binding
+ implicit none
+
+ type :: iso_holder
+ integer :: id
+ type(c_ptr) :: ptr
+ type(c_funptr) :: funptr
+ end type iso_holder
+
+ integer, target :: data
+ type(iso_holder) :: holder
+ integer(c_intptr_t) :: host_ptr_val, dev_ptr_val
+ integer(c_intptr_t) :: host_fun_val, dev_fun_val
+
+ data = 42
+
+ ! Populate the derived type with the host address values.
+ holder%ptr = c_loc(data)
+ holder%funptr = c_funloc(dummy_proc)
+
+ host_ptr_val = transfer(holder%ptr, host_ptr_val)
+ host_fun_val = transfer(holder%funptr, host_fun_val)
+
+ dev_ptr_val = 0
+ dev_fun_val = 0
+
+ ! Map the whole derived type (containing the nested c_ptr/c_funptr) to the
+ ! device and read back their bit values from within the target region.
+ !$omp target map(to: holder) &
+ !$omp& map(from: dev_ptr_val, dev_fun_val)
+ dev_ptr_val = transfer(holder%ptr, dev_ptr_val)
+ dev_fun_val = transfer(holder%funptr, dev_fun_val)
+ !$omp end target
+
+ ! CHECK: nested c_ptr mapped correctly
+ if (dev_ptr_val == host_ptr_val) then
+ print *, "nested c_ptr mapped correctly"
+ else
+ print *, "nested c_ptr mapping FAILED"
+ end if
+
+ ! CHECK: nested c_funptr mapped correctly
+ if (dev_fun_val == host_fun_val) then
+ print *, "nested c_funptr mapped correctly"
+ else
+ print *, "nested c_funptr mapping FAILED"
+ end if
+
+contains
+
+ subroutine dummy_proc() bind(C)
+ end subroutine dummy_proc
+
+end program target_map_cptr_cfunptr
More information about the flang-commits
mailing list