OpenMP/USM implies memory accessible from host as well as device, but doesn't
imply that allocation vs. deallocation may be done in the opposite context.
For most of the test cases, (by construction) we're not allocating memory
during device execution, so have nothing to clean up.  (..., but still document
these semantics.)  But for a few, we have to clean up:
'libgomp.c++/target-std__map-concurrent-usm.C',
'libgomp.c++/target-std__multimap-concurrent-usm.C',
'libgomp.c++/target-std__multiset-concurrent-usm.C',
'libgomp.c++/target-std__set-concurrent-usm.C'.

For 'libgomp.c++/target-std__multimap-concurrent-usm.C' (only), this issue
already got addressed in commit 90f2ab4b6e1463d8cb89c70585e19987a58f3de1
"libgomp.c++/target-std__multimap-concurrent.C: Fix USM memory freeing".
However, instead of invoking the 'clear' function (which doesn't generally
guarantee to release dynamically allocated memory; for example, see PR123582
"C++ unordered associative container: dynamic memory management"), we properly
restore the respective object into pristine state.

        libgomp/
        * testsuite/libgomp.c++/target-std__array-concurrent-usm.C:
        '#define OMP_USM'.
        * testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__list-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__span-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__map-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__set-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__vector-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__deque-concurrent-usm.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__array-concurrent.C: Comment.
        * testsuite/libgomp.c++/target-std__bitset-concurrent.C: Likewise.
        * testsuite/libgomp.c++/target-std__deque-concurrent.C: Likewise.
        * testsuite/libgomp.c++/target-std__forward_list-concurrent.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__list-concurrent.C: Likewise.
        * testsuite/libgomp.c++/target-std__span-concurrent.C: Likewise.
        * testsuite/libgomp.c++/target-std__valarray-concurrent.C:
        Likewise.
        * testsuite/libgomp.c++/target-std__vector-concurrent.C: Likewise.
        * testsuite/libgomp.c++/target-std__map-concurrent.C [OMP_USM]:
        Fix up dynamic memory allocation.
        * testsuite/libgomp.c++/target-std__multimap-concurrent.C
        [OMP_USM]: Likewise.
        * testsuite/libgomp.c++/target-std__multiset-concurrent.C
        [OMP_USM]: Likewise.
        * testsuite/libgomp.c++/target-std__set-concurrent.C [OMP_USM]:
        Likewise.
---
 .../target-std__array-concurrent-usm.C         |  2 +-
 .../libgomp.c++/target-std__array-concurrent.C |  5 +++++
 .../target-std__bitset-concurrent-usm.C        |  2 +-
 .../target-std__bitset-concurrent.C            |  4 ++++
 .../target-std__deque-concurrent-usm.C         |  2 +-
 .../libgomp.c++/target-std__deque-concurrent.C |  5 +++++
 .../target-std__forward_list-concurrent-usm.C  |  2 +-
 .../target-std__forward_list-concurrent.C      |  5 +++++
 .../target-std__list-concurrent-usm.C          |  2 +-
 .../libgomp.c++/target-std__list-concurrent.C  |  5 +++++
 .../target-std__map-concurrent-usm.C           |  2 +-
 .../libgomp.c++/target-std__map-concurrent.C   |  8 ++++++++
 .../target-std__multimap-concurrent-usm.C      |  2 +-
 .../target-std__multimap-concurrent.C          | 18 ++++++++----------
 .../target-std__multiset-concurrent-usm.C      |  2 +-
 .../target-std__multiset-concurrent.C          |  8 ++++++++
 .../target-std__set-concurrent-usm.C           |  2 +-
 .../libgomp.c++/target-std__set-concurrent.C   |  8 ++++++++
 .../target-std__span-concurrent-usm.C          |  2 +-
 .../libgomp.c++/target-std__span-concurrent.C  |  5 +++++
 .../target-std__valarray-concurrent-usm.C      |  2 +-
 .../target-std__valarray-concurrent.C          |  5 +++++
 .../target-std__vector-concurrent-usm.C        |  2 +-
 .../target-std__vector-concurrent.C            |  5 +++++
 24 files changed, 83 insertions(+), 22 deletions(-)

diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
index c98d8559b97..4aa3e8eaa5b 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__array-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
index d40fe1044ff..f4a3049bc24 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
@@ -53,6 +53,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (arr, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          arr.~array ();
 #endif
diff --git a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
index d08ea710971..36f3fcf2b3f 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target omp_usm } */
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__bitset-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C
index 9dc941d8693..9cc98976cca 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C
@@ -58,6 +58,10 @@ int main (void)
          if (_set[i])
            sum += i;
 
+#ifdef OMP_USM
+       /* (By construction) we're not allocating memory during device
+          execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
       #pragma omp target
        _set.~bitset ();
diff --git a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
index aaa6acc6312..e7296699e9b 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__deque-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C
index e89c2557c91..e2cf17bda61 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C
@@ -54,6 +54,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (_deque, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          _deque.~deque ();
 #endif
diff --git 
a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
index 2c28ed81580..da142272c3d 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__forward_list-concurrent.C"
diff --git 
a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent.C
index 93f91476712..7b9c4221e0c 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent.C
@@ -73,6 +73,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (list, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          list.~forward_list ();
 #endif
diff --git a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
index dec92d2639d..d97def17cb0 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__list-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C
index 6b3f8c51231..3cd9ab8242e 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C
@@ -73,6 +73,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (_list, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          _list.~list ();
 #endif
diff --git a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
index b7d3dd822a7..d31e3e29b0d 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target omp_usm } */
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__map-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C
index c54acea1d25..8d1c6dac241 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C
@@ -56,6 +56,14 @@ int main (void)
     for (int i = 0; i < N; ++i)
       sum += (long long) keys[i] * _map[keys[i]];
 
+#ifdef OMP_USM
+  #pragma omp target
+    /* Restore the object into pristine state.  In particular, deallocate
+       any memory allocated during device execution, which otherwise, back
+       on the host, we'd SIGSEGV on, when attempting to deallocate during
+       destruction of the object.  */
+    __typeof__ (_map){}.swap (_map);
+#endif
 #ifndef MEM_SHARED
   #pragma omp target
     _map.~map ();
diff --git 
a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
index f243790a638..4a7d8957c31 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target omp_usm } */
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__multimap-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C
index 34518a5a0e3..81932a0c1e4 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C
@@ -54,17 +54,15 @@ int main (void)
        for (auto it = range.first; it != range.second; ++it)
          sum += (long long) it->first * it->second;
       }
-#ifdef MEM_SHARED
-  /* Even with USM, memory allocated on the device (with _map.insert)
-     must be freed on the device.  */
-  if (omp_get_default_device () != omp_initial_device
-      && omp_get_default_device () != omp_get_num_devices ())
-    {
-      #pragma omp target
-       _map.clear ();
-    }
-#endif
 
+#ifdef OMP_USM
+  #pragma omp target
+    /* Restore the object into pristine state.  In particular, deallocate
+       any memory allocated during device execution, which otherwise, back
+       on the host, we'd SIGSEGV on, when attempting to deallocate during
+       destruction of the object.  */
+    __typeof__ (_map){}.swap (_map);
+#endif
 #ifndef MEM_SHARED
   #pragma omp target
     _map.~multimap ();
diff --git 
a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
index d869e8937ff..fdd8729c1dc 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target omp_usm } */
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__multiset-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C
index bace4201cb1..7b5841609be 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C
@@ -51,6 +51,14 @@ int main (void)
        for (int i = 0; i < MAX; ++i)
          sum += i * set.count (i);
 
+#ifdef OMP_USM
+      #pragma omp target
+       /* Restore the object into pristine state.  In particular, deallocate
+          any memory allocated during device execution, which otherwise, back
+          on the host, we'd SIGSEGV on, when attempting to deallocate during
+          destruction of the object.  */
+       __typeof__ (set){}.swap (set);
+#endif
 #ifndef MEM_SHARED
       #pragma omp target
        set.~multiset ();
diff --git a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
index 5fbf91b2e07..50147516884 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target omp_usm } */
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__set-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C
index 4559778efd7..1730f57c607 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C
@@ -57,6 +57,14 @@ int main (void)
          if (_set.find (i) != _set.end ())
            sum += i;
 
+#ifdef OMP_USM
+      #pragma omp target
+       /* Restore the object into pristine state.  In particular, deallocate
+          any memory allocated during device execution, which otherwise, back
+          on the host, we'd SIGSEGV on, when attempting to deallocate during
+          destruction of the object.  */
+       __typeof__ (_set){}.swap (_set);
+#endif
 #ifndef MEM_SHARED
       #pragma omp target
        _set.~set ();
diff --git a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
index 09af5c2dd21..f3a0d2357b0 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
@@ -2,7 +2,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__span-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C
index 761abc357e7..6b1b20fb397 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C
@@ -53,6 +53,11 @@ int main (void)
   #pragma omp target map (from: ok)
     {
       ok = validate (span, data);
+
+#ifdef OMP_USM
+      /* (By construction) we're not allocating memory during device
+        execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
       span.~span ();
 #endif
diff --git 
a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
index 9a0485ce77a..2a52d9e5da9 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__valarray-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C
index 15ca0f999b4..64fdcceb7b7 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C
@@ -56,6 +56,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (arr, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          arr.~valarray ();
 #endif
diff --git a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C 
b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
index c9f42838327..fe808d30223 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
@@ -1,7 +1,7 @@
 /* { dg-require-effective-target omp_usm } */
 // { dg-additional-options "-Wno-deprecated-openmp" }
 #pragma omp requires unified_shared_memory self_maps
-
+#define OMP_USM
 #define MEM_SHARED
 
 #include "target-std__vector-concurrent.C"
diff --git a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C 
b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C
index ae269630107..cb1e97df6b9 100644
--- a/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C
+++ b/libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C
@@ -53,6 +53,11 @@ int main (void)
       #pragma omp target map (from: ok)
        {
          ok = validate (vec, data);
+
+#ifdef OMP_USM
+         /* (By construction) we're not allocating memory during device
+            execution, so have nothing to clean up.  */
+#endif
 #ifndef MEM_SHARED
          vec.~vector ();
 #endif
-- 
2.34.1

Reply via email to