From: Andrew Stubbs Date: Fri, 2 Dec 2022 16:37:58 +0000 (+0000) Subject: libgomp: Fix USM bugs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ab62864c292f5d1d8b5a499cdf434346d46a924;p=thirdparty%2Fgcc.git libgomp: Fix USM bugs Fix up some USM corner cases. libgomp/ChangeLog: * libgomp.h (OFFSET_USM): New macro. * target.c (gomp_map_pointer): Handle USM mappings. (gomp_map_val): Handle OFFSET_USM. (gomp_map_vars_internal): Move USM check earlier, and use OFFSET_USM. Add OFFSET_USM check to the second mapping pass. * testsuite/libgomp.fortran/usm-1.f90: New test. * testsuite/libgomp.fortran/usm-2.f90: New test. --- diff --git a/libgomp/ChangeLog.omp b/libgomp/ChangeLog.omp index a0d0271f63bb..068f48101009 100644 --- a/libgomp/ChangeLog.omp +++ b/libgomp/ChangeLog.omp @@ -1,3 +1,13 @@ +2022-12-16 Andrew Stubbs + + * libgomp.h (OFFSET_USM): New macro. + * target.c (gomp_map_pointer): Handle USM mappings. + (gomp_map_val): Handle OFFSET_USM. + (gomp_map_vars_internal): Move USM check earlier, and use OFFSET_USM. + Add OFFSET_USM check to the second mapping pass. + * testsuite/libgomp.fortran/usm-1.f90: New test. + * testsuite/libgomp.fortran/usm-2.f90: New test. + 2022-12-13 Marcel Vollweiler * target.c (omp_target_is_accessible): Handle unified shared memory. diff --git a/libgomp/libgomp.h b/libgomp/libgomp.h index e5345ebee535..7d55f3cf825b 100644 --- a/libgomp/libgomp.h +++ b/libgomp/libgomp.h @@ -1196,6 +1196,7 @@ struct target_mem_desc; #define OFFSET_INLINED (~(uintptr_t) 0) #define OFFSET_POINTER (~(uintptr_t) 1) #define OFFSET_STRUCT (~(uintptr_t) 2) +#define OFFSET_USM (~(uintptr_t) 3) /* Auxiliary structure for infrequently-used or API-specific data. */ diff --git a/libgomp/target.c b/libgomp/target.c index 2cd8e2a65dda..cda53d636d15 100644 --- a/libgomp/target.c +++ b/libgomp/target.c @@ -692,6 +692,9 @@ gomp_map_pointer (struct target_mem_desc *tgt, struct goacc_asyncqueue *aq, { if (allow_zero_length_array_sections) cur_node.tgt_offset = 0; + else if (devicep->is_usm_ptr_func + && devicep->is_usm_ptr_func ((void*)cur_node.host_start)) + cur_node.tgt_offset = cur_node.host_start; else { gomp_mutex_unlock (&devicep->lock); @@ -928,6 +931,7 @@ gomp_map_val (struct target_mem_desc *tgt, void **hostaddrs, size_t i) switch (tgt->list[i].offset) { case OFFSET_INLINED: + case OFFSET_USM: return (uintptr_t) hostaddrs[i]; case OFFSET_POINTER: @@ -1013,6 +1017,7 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, { int kind = get_kind (short_mapkind, kinds, i); bool implicit = get_implicit (short_mapkind, kinds, i); + tgt->list[i].offset = 0; if (hostaddrs[i] == NULL || (kind & typemask) == GOMP_MAP_FIRSTPRIVATE_INT) { @@ -1020,6 +1025,15 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, tgt->list[i].offset = OFFSET_INLINED; continue; } + else if (devicep->is_usm_ptr_func + && devicep->is_usm_ptr_func (hostaddrs[i])) + { + /* The memory is visible from both host and target + so nothing needs to be moved. */ + tgt->list[i].key = NULL; + tgt->list[i].offset = OFFSET_USM; + continue; + } else if ((kind & typemask) == GOMP_MAP_USE_DEVICE_PTR || (kind & typemask) == GOMP_MAP_USE_DEVICE_PTR_IF_PRESENT) { @@ -1063,15 +1077,6 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, tgt->list[i].offset = 0; continue; } - else if (devicep->is_usm_ptr_func - && devicep->is_usm_ptr_func (hostaddrs[i])) - { - /* The memory is visible from both host and target - so nothing needs to be moved. */ - tgt->list[i].key = NULL; - tgt->list[i].offset = OFFSET_INLINED; - continue; - } else if ((kind & typemask) == GOMP_MAP_STRUCT) { size_t first = i + 1; @@ -1441,6 +1446,8 @@ gomp_map_vars_internal (struct gomp_device_descr *devicep, bool implicit = get_implicit (short_mapkind, kinds, i); if (hostaddrs[i] == NULL) continue; + if (tgt->list[i].offset == OFFSET_USM) + continue; switch (kind & typemask) { size_t align, len, first, last; diff --git a/libgomp/testsuite/libgomp.fortran/usm-1.f90 b/libgomp/testsuite/libgomp.fortran/usm-1.f90 new file mode 100644 index 000000000000..7147e9925a24 --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/usm-1.f90 @@ -0,0 +1,28 @@ +! { dg-do run } +! { dg-require-effective-target omp_usm } + +! Ensure that USM works for implicit mappings. +! This needs to cover both the initial mapping scan and the rescan that +! happens when some of the mappings aren't no-ops (in this cases there are +! some hidden pointers). + +program usm + use iso_fortran_env + use omp_lib + implicit none + + !$omp requires unified_shared_memory + + integer, parameter :: N = 1024 + real(real64), allocatable :: x(:), y(:) + integer :: i + + allocate(x(N), y(N)) + !$omp target teams distribute parallel do simd + do i=1,N + y(i) = x(i) + enddo + + deallocate(x,y) + +end program usm diff --git a/libgomp/testsuite/libgomp.fortran/usm-2.f90 b/libgomp/testsuite/libgomp.fortran/usm-2.f90 new file mode 100644 index 000000000000..94e8284c475e --- /dev/null +++ b/libgomp/testsuite/libgomp.fortran/usm-2.f90 @@ -0,0 +1,33 @@ +! { dg-do run } +! { dg-require-effective-target omp_usm } + +! Ensure that USM doesn't break the use_device_ptr clause (host pointers and +! target pointers being "unified"). + +program usm + use iso_fortran_env + use omp_lib + implicit none + + !$omp requires unified_shared_memory + + integer, parameter :: N = 1024 + real(real64), allocatable :: x(:), y(:) + integer :: i + + allocate(x(N),y(N)) + + !$omp target data map(x) + ! The "i" variable is not explictly mapped yet, so ensures that both + ! mapping scan passes are tested. + !$omp target data map(i) use_device_ptr(x) + !$omp target teams distribute parallel do simd + do i=1,N + y(i) = x(i) + enddo + !$omp end target data + !$omp end target data + + deallocate(x,y) + +end program usm