Skip to content

[Flang][OpenMP][MLIR] Implement close, present and ompx_hold modifiers for Flang maps #129586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,15 +1029,15 @@ bool ClauseProcessor::processMap(
}

if (typeMods) {
// TODO: Still requires "self" modifier, an OpenMP 6.0+ feature
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Always))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_ALWAYS;
// Diagnose unimplemented map-type-modifiers.
if (llvm::any_of(*typeMods, [](Map::MapTypeModifier m) {
return m != Map::MapTypeModifier::Always;
})) {
TODO(currentLocation, "Map type modifiers (other than 'ALWAYS')"
" are not implemented yet");
}
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Present))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
}

if (iterator) {
Expand Down Expand Up @@ -1073,19 +1073,20 @@ 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;
// TODO Support motion modifiers: present, mapper, iterator.
if (expectation) {
TODO(clauseLocation, "PRESENT modifier is not supported yet");
} else if (mapper) {

// 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");
}
constexpr llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =

llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
std::is_same_v<llvm::remove_cvref_t<decltype(clause)>, omp::clause::To>
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;

if (expectation && *expectation == omp::clause::To::Expectation::Present)
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
processMapObjects(stmtCtx, clauseLocation, objects, mapTypeBits,
parentMemberIndices, result.mapVars, mapSymbols);
};
Expand Down
15 changes: 5 additions & 10 deletions flang/lib/Optimizer/OpenMP/MapInfoFinalization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,20 +243,15 @@ class MapInfoFinalizationPass
/// where necessary, although it does not seem strictly required.
unsigned long getDescriptorMapType(unsigned long mapTypeFlag,
mlir::Operation *target) {
using mapFlags = llvm::omp::OpenMPOffloadMappingFlags;
if (llvm::isa_and_nonnull<mlir::omp::TargetExitDataOp,
mlir::omp::TargetUpdateOp>(target))
return mapTypeFlag;

bool hasImplicitMap =
(llvm::omp::OpenMPOffloadMappingFlags(mapTypeFlag) &
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT) ==
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;

return llvm::to_underlying(
hasImplicitMap
? llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT
: llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO);
mapFlags flags = mapFlags::OMP_MAP_TO |
(mapFlags(mapTypeFlag) &
(mapFlags::OMP_MAP_IMPLICIT | mapFlags::OMP_MAP_CLOSE));
return llvm::to_underlying(flags);
}

mlir::omp::MapInfoOp genDescriptorMemberMaps(mlir::omp::MapInfoOp op,
Expand Down
33 changes: 32 additions & 1 deletion flang/test/Integration/OpenMP/map-types-and-sizes.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
! added to this directory and sub-directories.
!===----------------------------------------------------------------------===!

!RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-targets=amdgcn-amd-amdhsa -flang-deprecated-no-hlfir %s -o - | FileCheck %s
!RUN: %flang_fc1 -emit-llvm -fopenmp -fopenmp-version=51 -fopenmp-targets=amdgcn-amd-amdhsa -flang-deprecated-no-hlfir %s -o - | FileCheck %s

!===============================================================================
! Check MapTypes for target implicit captures
Expand Down Expand Up @@ -39,6 +39,37 @@ subroutine mapType_ptr
!$omp end target
end subroutine mapType_ptr

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4097]
subroutine map_present_target_data
integer :: x
!$omp target data map(present, to: x)
!$omp end target data
end subroutine

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4097]
subroutine map_present_update
integer :: x
!$omp target update to(present: x)
end subroutine

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 1027]
subroutine map_close
integer :: x
!$omp target data map(close, tofrom: x)
!$omp end target data
end subroutine

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [1 x i64] [i64 4]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [1 x i64] [i64 8195]
subroutine map_ompx_hold
integer :: x
!$omp target data map(ompx_hold, tofrom: x)
!$omp end target data
end subroutine

!CHECK: @.offload_sizes{{.*}} = private unnamed_addr constant [4 x i64] [i64 0, i64 24, i64 8, i64 0]
!CHECK: @.offload_maptypes{{.*}} = private unnamed_addr constant [4 x i64] [i64 32, i64 281474976711169, i64 281474976711171, i64 281474976711187]
subroutine mapType_allocatable
Expand Down
8 changes: 0 additions & 8 deletions flang/test/Lower/OpenMP/Todo/from-expectation-modifier.f90

This file was deleted.

10 changes: 0 additions & 10 deletions flang/test/Lower/OpenMP/Todo/map-modifiers-close.f90

This file was deleted.

11 changes: 0 additions & 11 deletions flang/test/Lower/OpenMP/Todo/map-modifiers-ompxhold.f90

This file was deleted.

11 changes: 0 additions & 11 deletions flang/test/Lower/OpenMP/Todo/map-modifiers-present.f90

This file was deleted.

8 changes: 0 additions & 8 deletions flang/test/Lower/OpenMP/Todo/to-expectation-modifier.f90

This file was deleted.

32 changes: 32 additions & 0 deletions flang/test/Lower/OpenMP/map-modifiers.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s

subroutine map_present_target_data
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(present, to) {{.*}} {name = "x"}
!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) {
!$omp target data map(present, to: x)
!$omp end target data
end subroutine

subroutine map_present_update
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(present, to) {{.*}} {name = "x"}
!CHECK: omp.target_update map_entries(%[[MAP]] : {{.*}})
!$omp target update to(present: x)
end subroutine

subroutine map_close
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(close, tofrom) {{.*}} {name = "x"}
!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) {
!$omp target data map(close, tofrom: x)
!$omp end target data
end subroutine

subroutine map_ompx_hold
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(ompx_hold, tofrom) {{.*}} {name = "x"}
!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) {
!$omp target data map(ompx_hold, tofrom: x)
!$omp end target data
end subroutine
10 changes: 8 additions & 2 deletions mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1458,8 +1458,8 @@ uint64_t mapTypeToBitFlag(uint64_t value,
/// Parses a map_entries map type from a string format back into its numeric
/// value.
///
/// map-clause = `map_clauses ( ( `(` `always, `? `close, `? `present, `? (
/// `to` | `from` | `delete` `)` )+ `)` )
/// map-clause = `map_clauses ( ( `(` `always, `? `implicit, `? `ompx_hold, `?
/// `close, `? `present, `? ( `to` | `from` | `delete` `)` )+ `)` )
static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType) {
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
Expand All @@ -1477,6 +1477,9 @@ static ParseResult parseMapClause(OpAsmParser &parser, IntegerAttr &mapType) {
if (mapTypeMod == "implicit")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT;

if (mapTypeMod == "ompx_hold")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;

if (mapTypeMod == "close")
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;

Expand Down Expand Up @@ -1526,6 +1529,9 @@ static void printMapClause(OpAsmPrinter &p, Operation *op,
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_IMPLICIT))
mapTypeStrs.push_back("implicit");
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD))
mapTypeStrs.push_back("ompx_hold");
if (mapTypeToBitFlag(mapTypeBits,
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE))
mapTypeStrs.push_back("close");
Expand Down
6 changes: 6 additions & 0 deletions mlir/test/Dialect/OpenMP/ops.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -825,6 +825,12 @@ func.func @omp_target_data (%if_cond : i1, %device : si32, %device_ptr: memref<i
%mapv6 = omp.map.info var_ptr(%map2 : memref<?xi32>, tensor<?xi32>) map_clauses(exit_release_or_enter_alloc) capture(ByRef) -> memref<?xi32> {name = ""}
omp.target_exit_data if(%if_cond) device(%device : si32) nowait map_entries(%mapv6 : memref<?xi32>)

// CHECK: %[[MAP_A:.*]] = omp.map.info var_ptr(%[[VAL_2:.*]] : memref<?xi32>, tensor<?xi32>) map_clauses(ompx_hold, to) capture(ByRef) -> memref<?xi32> {name = ""}
// CHECK: omp.target_data map_entries(%[[MAP_A]] : memref<?xi32>)
%mapv7 = omp.map.info var_ptr(%map1 : memref<?xi32>, tensor<?xi32>) map_clauses(ompx_hold, to) capture(ByRef) -> memref<?xi32> {name = ""}
omp.target_data map_entries(%mapv7 : memref<?xi32>) {
omp.terminator
}
return
}

Expand Down
4 changes: 4 additions & 0 deletions offload/test/Inputs/target-use-dev-ptr.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@ int check_result(int *host_ptr, int *dev_ptr) {
return 0;
}
}

int check_equality(void *host_ptr, void *dev_ptr) {
return dev_ptr == host_ptr;
}
2 changes: 1 addition & 1 deletion offload/test/offloading/fortran/target-use-dev-ptr.f90
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ end function get_ptr
integer(c_int) function check_result(host, dev) BIND(C)
USE, intrinsic :: iso_c_binding
implicit none
type(c_ptr), intent(in) :: host, dev
type(c_ptr), value, intent(in) :: host, dev
end function check_result
end interface

Expand Down
29 changes: 29 additions & 0 deletions offload/test/offloading/fortran/target_map_ompx_hold.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
! Basic test that checks that when ompx_hold is in use we cannot delete the data
! until the ompx_hold falls out of scope, and verifies this via the utilisation of
! present.
! REQUIRES: flang, amdgpu
! RUN: %libomptarget-compile-fortran-generic
! RUN: %libomptarget-run-fail-generic 2>&1 \
! RUN: | %fcheck-generic

program ompx_hold
implicit none
integer :: presence_check

!CHECK-NOT: omptarget message: device mapping required by 'present' map type modifier does not exist for host address{{.*}}
!$omp target data map(ompx_hold, tofrom: presence_check)
!$omp target exit data map(delete: presence_check)
!$omp target map(present, tofrom: presence_check)
presence_check = 10
!$omp end target
!$omp end target data

!CHECK: omptarget message: device mapping required by 'present' map type modifier does not exist for host address{{.*}}
!$omp target data map(tofrom: presence_check)
!$omp target exit data map(delete: presence_check)
!$omp target map(present, tofrom: presence_check)
presence_check = 20
!$omp end target
!$omp end target data

end program
36 changes: 36 additions & 0 deletions offload/test/offloading/fortran/target_map_present_fail.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
! This checks that the basic functionality of map type present functions as
! expected, emitting an omptarget error when the data is not present.
! REQUIRES: flang, amdgpu
! RUN: %libomptarget-compile-fortran-generic
! RUN: %libomptarget-run-fail-generic 2>&1 \
! RUN: | %fcheck-generic

! NOTE: This should intentionally fatal error in omptarget as it's not
! present, as is intended.
subroutine target_data_not_present()
double precision, dimension(:), allocatable :: arr
integer, parameter :: N = 16
integer :: i

allocate(arr(N))

!$omp target data map(present,alloc:arr)

!$omp target
do i = 1,N
arr(i) = 42.0d0
end do
!$omp end target

!$omp end target data

deallocate(arr)
return
end subroutine

program map_present
implicit none
call target_data_not_present()
end program

!CHECK: omptarget message: device mapping required by 'present' map type modifier does not exist for host address{{.*}}
41 changes: 41 additions & 0 deletions offload/test/offloading/fortran/target_map_present_success.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
! This checks that the basic functionality of map type present functions as
! expected, no-op'ng when present
! REQUIRES: flang, amdgpu
! RUN: %libomptarget-compile-fortran-run-and-check-generic

subroutine target_data_present()
double precision, dimension(:), allocatable :: arr
integer, parameter :: N = 16
integer :: i

allocate(arr(N))

arr(:) = 10.0d0

!$omp target data map(tofrom:arr)

!$omp target data map(present,alloc:arr)

!$omp target
do i = 1,N
arr(i) = 42.0d0
end do
!$omp end target

!$omp end target data

!$omp end target data

print *, arr

deallocate(arr)

return
end subroutine

program map_present
implicit none
call target_data_present()
end program

!CHECK: 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42. 42.
Loading
Loading