[libcxx-commits] [libcxx] [libcxx][test] Prevent compiler optimising out uses of 64-bit atomics (PR #172517)

David Spickett via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 16 08:35:57 PST 2025


https://github.com/DavidSpickett created https://github.com/llvm/llvm-project/pull/172517

I found this while trying different optimisation options to fix a test failure on #169901.

Normally the tests are built for Cortex-M with no options, aka -O0. These tests fail to builds because we do not have 64-bit atomics on that platform:
ld.lld: error: undefined symbol: __atomic_load_8

This is noted by an XFAIL annotation in the test, which is correct when you're using -O0.

When you optimise this code, the call to the atomic is actually removed and the test does compile and does run. Turning it into an unexpected pass.

To fix this I've added DoNotOptimise in various places. To make this truly robust, it probably needs to be in many more, but I've stuck to what turned the tests back into XFAILs for Cortex-M.

>From d60faa6230478d451f5f294ce75cc4de0965a00d Mon Sep 17 00:00:00 2001
From: David Spickett <david.spickett at linaro.org>
Date: Tue, 16 Dec 2025 16:30:47 +0000
Subject: [PATCH] [libcxx][test] Prevent compiler optimising out uses of 64-bit
 atomics

I found this while trying different optimisation options to fix a
test failure on #169901.

Normally the tests are built with no options, aka -O0. These tests
fail for Cortex-M picolib builds because we do not have 64-bit atomics
on that platform.

They fail to compile:
ld.lld: error: undefined symbol: __atomic_load_8

This is noted by an XFAIL annotation in the test.

When you optimise this code, the call to the atomic is actually
removed and the test does compile and does run. Meaning it's
an unexpected pass.

To fix this I've added DoNotOptimise in various places. To make
this truly robust, it probably needs to be in many more, but
I've stuck to what turned the tests back into XFAILs for Cortex-M.
---
 .../atomics.types.generic/atomics.types.float/assign.pass.cpp    | 1 +
 .../atomics.types.generic/atomics.types.float/load.pass.cpp      | 1 +
 .../atomics.types.float/operator.float.pass.cpp                  | 1 +
 .../atomics.types.generic/atomics.types.float/store.pass.cpp     | 1 +
 .../atomics.types.generic/atomics.types.float/wait.pass.cpp      | 1 +
 5 files changed, 5 insertions(+)

diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
index 687b324f3f19b..473e511703284 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
@@ -32,6 +32,7 @@ void test_impl() {
   // assignment
   {
     MaybeVolatile<std::atomic<T>> a(T(3.1));
+    DoNotOptimize(a);
     std::same_as<T> decltype(auto) r = (a = T(1.2));
     assert(a.load() == T(1.2));
     assert(r == T(1.2));
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
index 695fd593b51e2..acc75d9acb15e 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
@@ -40,6 +40,7 @@ void test_impl() {
   // load
   {
     MaybeVolatile<std::atomic<T>> a(T(3.1));
+    DoNotOptimize(a);
     a.store(T(1.2));
     std::same_as<T> decltype(auto) r = a.load(std::memory_order::relaxed);
     assert(r == T(1.2));
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
index 1f08906065742..2e64764f3bce2 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
@@ -29,6 +29,7 @@ void test_impl() {
   // operator float
   {
     MaybeVolatile<std::atomic<T>> a(T(3.1));
+    DoNotOptimize(a);
     T r = a;
     assert(r == T(3.1));
   }
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
index 34bd09e945f94..24cadab0c1559 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
@@ -39,6 +39,7 @@ void test_impl() {
   // store
   {
     MaybeVolatile<std::atomic<T>> a(T(3.1));
+    DoNotOptimize(a);
     a.store(T(1.2), std::memory_order::relaxed);
     assert(a.load() == T(1.2));
   }
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
index 846d276c0ede8..fba523d8c2b55 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
@@ -38,6 +38,7 @@ void test_impl() {
   // wait with different value
   {
     MaybeVolatile<std::atomic<T>> a(T(3.1));
+    DoNotOptimize(a);
     a.wait(T(1.1), std::memory_order::relaxed);
   }
 



More information about the libcxx-commits mailing list