]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libgomp: Fix USM bugs
authorAndrew Stubbs <ams@codesourcery.com>
Fri, 2 Dec 2022 16:37:58 +0000 (16:37 +0000)
committerAndrew Stubbs <ams@codesourcery.com>
Fri, 16 Dec 2022 11:20:53 +0000 (11:20 +0000)
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.

libgomp/ChangeLog.omp
libgomp/libgomp.h
libgomp/target.c
libgomp/testsuite/libgomp.fortran/usm-1.f90 [new file with mode: 0644]
libgomp/testsuite/libgomp.fortran/usm-2.f90 [new file with mode: 0644]

index a0d0271f63bb90f3747d6c9a2d2147fd82198b0c..068f481010099b89e297fc8304687cf4db5c745f 100644 (file)
@@ -1,3 +1,13 @@
+2022-12-16  Andrew Stubbs  <ams@codesourcery.com>
+
+       * 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  <marcel@codesourcery.com>
 
        * target.c (omp_target_is_accessible): Handle unified shared memory.
index e5345ebee5359a39e441124bd254fef5670a492f..7d55f3cf825bd809f98a06370877f1d90983fcd2 100644 (file)
@@ -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.  */
 
index 2cd8e2a65dda47c9b1ef16e6ac17ae0911ab04d0..cda53d636d158ee5447e9731a887208557d1f56e 100644 (file)
@@ -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 (file)
index 0000000..7147e99
--- /dev/null
@@ -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 (file)
index 0000000..94e8284
--- /dev/null
@@ -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