]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix up 'libgomp.c++/target-std__[...]-concurrent-usm.C' dynamic memory allocation
authorThomas Schwinge <tschwinge@baylibre.com>
Fri, 30 May 2025 09:37:46 +0000 (11:37 +0200)
committerThomas Schwinge <tschwinge@baylibre.com>
Wed, 14 Jan 2026 15:00:56 +0000 (16:00 +0100)
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.

24 files changed:
libgomp/testsuite/libgomp.c++/target-std__array-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__array-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__bitset-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__deque-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__deque-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__forward_list-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__list-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__list-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__map-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__map-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__multimap-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__multiset-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__set-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__set-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__span-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__span-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__valarray-concurrent.C
libgomp/testsuite/libgomp.c++/target-std__vector-concurrent-usm.C
libgomp/testsuite/libgomp.c++/target-std__vector-concurrent.C

index c98d8559b9778ef776ce9dfa458b81917d52f9af..4aa3e8eaa5b3f265523218e9a5fbfaadba7b342b 100644 (file)
@@ -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"
index d40fe1044ffa4443c00870cf1ca43f3118648cd2..f4a3049bc24e6b480b4bf3ecb2e4fcb483ab23b5 100644 (file)
@@ -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
index d08ea710971444502da523e3ddf076b3b8a660ef..36f3fcf2b3f6aab03f77665440cdc62175438fed 100644 (file)
@@ -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"
index 9dc941d86938fd0bb9b7d477196a88f18a4dfc20..9cc98976cca8af8e5885d110607c8726162882a5 100644 (file)
@@ -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 ();
index aaa6acc6312819ec8554d40d6ac7e532b4a7e241..e7296699e9b15b9456e893621d108ab5ebad8ff1 100644 (file)
@@ -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"
index e89c2557c917a64fabd840108bb05a1ce44a3fda..e2cf17bda616814fe603b731e609ce7f182ffde7 100644 (file)
@@ -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
index 2c28ed815805f4f59d8c72644c86b314c5dfce32..da142272c3d9f73c8c4b65436e6e0d4cd424a451 100644 (file)
@@ -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"
index 93f9147671282db4e0e1ff5cc46de66d142da263..7b9c4221e0c2fc5e0fafbbafeb078e81d33a6632 100644 (file)
@@ -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
index dec92d2639d2c62c0ed11802c082bb0a639aa352..d97def17cb0312b95248ece902ada6851c3dca19 100644 (file)
@@ -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"
index 6b3f8c512314958a25a738acf245a4df85df5c27..3cd9ab8242ed83df66afffbbaa55c18282240a81 100644 (file)
@@ -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
index b7d3dd822a77d5e4a9434146a219351a516b6cc7..d31e3e29b0d2f531eb6c0adafe83e8c3aa2340ae 100644 (file)
@@ -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"
index c54acea1d25488c73a39a4fa0fe9a7afa8e90f64..8d1c6dac2411cbc7a9b138d656ec45679b7e9f6e 100644 (file)
@@ -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 ();
index f243790a6384e438efa1a15ecf64ce7cc6473e7b..4a7d8957c310e45f3f0251a686ad903ed11c0e36 100644 (file)
@@ -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"
index 34518a5a0e3d7f6d33e13eb4770ed3b68021affc..81932a0c1e43cf48e79d8a56644130d4ec310186 100644 (file)
@@ -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 ();
index d869e8937ffd146ca93742966ba0101be3df4b56..fdd8729c1dcc4187bedce0e99fa7d5731f859f05 100644 (file)
@@ -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"
index bace4201cb1fc36380538874e7153a687987598d..7b5841609be4b81e1f4777562e266315d9b65c0e 100644 (file)
@@ -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 ();
index 5fbf91b2e077d8e3338f6bb704ffb4ddbdfd38c7..50147516884536cc5000d56560dc39c5811068cf 100644 (file)
@@ -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"
index 4559778efd74175d98533179f0fbf394cfd06518..1730f57c607da1e8ded313e3b28905c996cfcfe4 100644 (file)
@@ -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 ();
index 09af5c2dd214a9263e6cbcb1395b3869205973e9..f3a0d2357b02c4c40b8bcd1f21ca9af4dbe1a635 100644 (file)
@@ -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"
index 761abc357e705003f64addbf79ec7009e9ef1740..6b1b20fb3978a40de4238ba4bfda7499441fc613 100644 (file)
@@ -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
index 9a0485ce77a491cd2b284be23cc2f1a65e9379d0..2a52d9e5da9482c08721deed65a9d13d8c8be2ea 100644 (file)
@@ -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"
index 15ca0f999b4ed2d9e538b35b5911ae1663b71b00..64fdcceb7b7d929d3785321cbf975685cd2d1e79 100644 (file)
@@ -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
index c9f42838327575c96037b39868ab7f1a94064768..fe808d30223303d3893b43d78000b42c0ed2da4c 100644 (file)
@@ -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"
index ae2696301076c5dc4097ba99c3d85cb902d91074..cb1e97df6b9050b292bab7d1da1a0d80261bbbd1 100644 (file)
@@ -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