[libunwind] [llvm] [libcxx] [libc++] Allow running the test suite with optimizations (PR #68753)

Louis Dionne via cfe-commits cfe-commits at lists.llvm.org
Sat Dec 2 05:19:58 PST 2023


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/68753

>From 5e53337f16aa446d6a2dc764d347ea37b22c3a56 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 10 Oct 2023 16:35:11 -0700
Subject: [PATCH 1/5] [libc++] Allow running the test suite with optimizations

This patch adds a configuration of the libc++ test suite that enables
optimizations when building the tests. It also adds a new CI configuration
to exercise this on a regular basis. This is added in the context of [1],
which requires building with optimizations in order to hit the bug.

[1]: https://github.com/llvm/llvm-project/issues/68552
---
 .github/workflows/libcxx-build-and-test.yaml  |  2 +-
 .../caches/Generic-optimized-speed.cmake      |  4 +++
 .../support.dynamic/libcpp_deallocate.sh.cpp  | 17 +++++------
 .../path.member/path.assign/move.pass.cpp     |  2 +-
 .../path.member/path.construct/move.pass.cpp  |  2 +-
 .../new.size.replace.indirect.pass.cpp        |  3 +-
 .../new.size.replace.pass.cpp                 |  3 +-
 .../new.size_align.replace.indirect.pass.cpp  |  7 +++--
 ...ze_align_nothrow.replace.indirect.pass.cpp |  7 +++--
 .../new.size_align_nothrow.replace.pass.cpp   |  7 +++--
 ...new.size_nothrow.replace.indirect.pass.cpp |  3 +-
 .../new.size_nothrow.replace.pass.cpp         |  3 +-
 .../new.size.replace.pass.cpp                 |  3 +-
 ...ze_align_nothrow.replace.indirect.pass.cpp |  7 +++--
 ...new.size_nothrow.replace.indirect.pass.cpp |  3 +-
 .../func.wrap.func.alg/swap.pass.cpp          | 16 +++++------
 .../func.wrap.func.con/F.pass.cpp             |  2 +-
 .../func.wrap.func.con/copy_assign.pass.cpp   |  8 +++---
 .../func.wrap.func.con/copy_move.pass.cpp     |  8 +++---
 .../nullptr_t_assign.pass.cpp                 |  2 +-
 .../func.wrap.func.mod/swap.pass.cpp          | 12 ++++----
 .../make_shared.pass.cpp                      |  4 +--
 libcxx/test/support/count_new.h               |  5 ++++
 libcxx/test/support/do_not_optimize.h         | 28 +++++++++++++++++++
 libcxx/utils/ci/run-buildbot                  |  5 ++++
 libcxx/utils/libcxx/test/params.py            | 28 ++++++++++++++++++-
 libunwind/test/libunwind_02.pass.cpp          | 26 +++++++++++++----
 libunwind/test/unw_resume.pass.cpp            |  2 +-
 libunwind/test/unwind_leaffunction.pass.cpp   | 20 +++++++------
 29 files changed, 169 insertions(+), 70 deletions(-)
 create mode 100644 libcxx/cmake/caches/Generic-optimized-speed.cmake
 create mode 100644 libcxx/test/support/do_not_optimize.h

diff --git a/.github/workflows/libcxx-build-and-test.yaml b/.github/workflows/libcxx-build-and-test.yaml
index 018f0e45a244..9c7adb808bcb 100644
--- a/.github/workflows/libcxx-build-and-test.yaml
+++ b/.github/workflows/libcxx-build-and-test.yaml
@@ -162,6 +162,7 @@ jobs:
           'generic-no-tzdb',
           'generic-no-unicode',
           'generic-no-wide-characters',
+          'generic-optimized-speed',
           'generic-static',
           'generic-with_llvm_unwinder',
           # TODO Find a better place for the benchmark and bootstrapping builds to live. They're either very expensive
@@ -209,4 +210,3 @@ jobs:
             **/CMakeError.log
             **/CMakeOutput.log
             **/crash_diagnostics/*
-  
diff --git a/libcxx/cmake/caches/Generic-optimized-speed.cmake b/libcxx/cmake/caches/Generic-optimized-speed.cmake
new file mode 100644
index 000000000000..577a5de9f34c
--- /dev/null
+++ b/libcxx/cmake/caches/Generic-optimized-speed.cmake
@@ -0,0 +1,4 @@
+set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "")
+set(LIBCXX_TEST_PARAMS "optimization=speed" CACHE STRING "")
+set(LIBCXXABI_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
+set(LIBUNWIND_TEST_PARAMS "${LIBCXX_TEST_PARAMS}" CACHE STRING "")
diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
index fb56ce4518a7..6e6229b752a7 100644
--- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
+++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
@@ -34,6 +34,7 @@
 #include <cstdlib>
 #include <new>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 TEST_DIAGNOSTIC_PUSH
@@ -187,13 +188,13 @@ void test_allocator_and_new_match() {
   stats.reset();
 #if defined(NO_SIZE) && defined(NO_ALIGN)
   {
-    int* x = new int(42);
+    int* x = support::do_not_optimize(new int(42));
     delete x;
     assert(stats.expect_plain());
   }
   stats.reset();
   {
-    AlignedType* a = new AlignedType();
+    AlignedType* a = support::do_not_optimize(new AlignedType());
     delete a;
     assert(stats.expect_plain());
   }
@@ -202,14 +203,14 @@ void test_allocator_and_new_match() {
   stats.reset();
 #if TEST_STD_VER >= 11
   {
-    int* x = new int(42);
+    int* x = support::do_not_optimize(new int(42));
     delete x;
     assert(stats.expect_plain());
   }
 #endif
   stats.reset();
   {
-    AlignedType* a = new AlignedType();
+    AlignedType* a = support::do_not_optimize(new AlignedType());
     delete a;
     assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));
   }
@@ -217,13 +218,13 @@ void test_allocator_and_new_match() {
 #elif defined(NO_ALIGN)
   stats.reset();
   {
-    int* x = new int(42);
+    int* x = support::do_not_optimize(new int(42));
     delete x;
     assert(stats.expect_size(sizeof(int)));
   }
   stats.reset();
   {
-    AlignedType* a = new AlignedType();
+    AlignedType* a = support::do_not_optimize(new AlignedType());
     delete a;
     assert(stats.expect_size(sizeof(AlignedType)));
   }
@@ -231,13 +232,13 @@ void test_allocator_and_new_match() {
 #else
   stats.reset();
   {
-    int* x = new int(42);
+    int* x = support::do_not_optimize(new int(42));
     delete x;
     assert(stats.expect_size(sizeof(int)));
   }
   stats.reset();
   {
-    AlignedType* a = new AlignedType();
+    AlignedType* a = support::do_not_optimize(new AlignedType());
     delete a;
     assert(stats.expect_size_align(sizeof(AlignedType),
                                    TEST_ALIGNOF(AlignedType)));
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
index 0efd9596f1c2..93295d9f6d5f 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.assign/move.pass.cpp
@@ -31,7 +31,7 @@ int main(int, char**) {
   const std::string s("we really really really really really really really "
                       "really really long string so that we allocate");
   ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
-      globalMemCounter.checkOutstandingNewEq(1));
+      globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
   const fs::path::string_type ps(s.begin(), s.end());
   path p(s);
   {
diff --git a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
index 15782dffa7df..3c762ee676be 100644
--- a/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
+++ b/libcxx/test/std/input.output/filesystems/class.path/path.member/path.construct/move.pass.cpp
@@ -31,7 +31,7 @@ int main(int, char**) {
   const std::string s("we really really really really really really really "
                       "really really long string so that we allocate");
   ASSERT_WITH_LIBRARY_INTERNAL_ALLOCATIONS(
-      globalMemCounter.checkOutstandingNewEq(1));
+      globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
   const fs::path::string_type ps(s.begin(), s.end());
   path p(s);
   {
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
index 172b6cc2f294..13f6217c521f 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
@@ -20,6 +20,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -40,7 +41,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = new int[3];
+    int* x = support::do_not_optimize(new int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
index e352c00b4d0a..9b3d39986484 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
@@ -19,6 +19,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -38,7 +39,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = new int[3];
+    int* x = support::do_not_optimize(new int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
index dcaa76a650d3..014951f50b7e 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
@@ -26,6 +26,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -51,7 +52,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = new OverAligned[3];
+        OverAligned* x = support::do_not_optimize(new OverAligned[3]);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -62,7 +63,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = new MaxAligned[3];
+        MaxAligned* x = support::do_not_optimize(new MaxAligned[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -73,7 +74,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = new int[3];
+        int* x = support::do_not_optimize(new int[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
index eba8a9026fa4..99926b876a03 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
@@ -26,6 +26,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -51,7 +52,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = new (std::nothrow) OverAligned[3];
+        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -62,7 +63,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = new (std::nothrow) MaxAligned[3];
+        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -73,7 +74,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = new (std::nothrow) int[3];
+        int* x = support::do_not_optimize(new (std::nothrow) int[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
index 62a040e297ae..cd8af782f972 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
@@ -23,6 +23,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -48,7 +49,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_nothrow_called = delete_called = 0;
-        OverAligned* x = new (std::nothrow) OverAligned[3];
+        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
         assert(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
 
@@ -59,7 +60,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_nothrow_called = delete_called = 0;
-        MaxAligned* x = new (std::nothrow) MaxAligned[3];
+        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
         assert(x != nullptr);
         assert(new_nothrow_called == 0);
 
@@ -70,7 +71,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_nothrow_called = delete_called = 0;
-        int* x = new (std::nothrow) int[3];
+        int* x = support::do_not_optimize(new (std::nothrow) int[3]);
         assert(x != nullptr);
         assert(new_nothrow_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
index 8ad0292dcb5c..8b0d801acd1f 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
@@ -24,6 +24,7 @@
 #include <cstdlib>
 #include <cassert>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -44,7 +45,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = new (std::nothrow) int[3];
+    int* x = support::do_not_optimize(new (std::nothrow) int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
index b85e15ce64b4..c9e4942d8153 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
@@ -18,6 +18,7 @@
 #include <cstdlib>
 #include <cassert>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_nothrow_called = 0;
@@ -35,7 +36,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_nothrow_called = delete_called = 0;
-    int* x = new (std::nothrow) int[3];
+    int* x = support::do_not_optimize(new (std::nothrow) int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
index a03313e5872e..c62268c39027 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
@@ -17,6 +17,7 @@
 #include <cstdlib>
 #include <cassert>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -36,7 +37,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = new int(3);
+    int* x = support::do_not_optimize(new int(3));
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
index 4a18ad2df8f2..1c42cdbb50db 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
@@ -25,6 +25,7 @@
 #include <cassert>
 #include <limits>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -50,7 +51,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = new (std::nothrow) OverAligned;
+        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -61,7 +62,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = new (std::nothrow) MaxAligned;
+        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -72,7 +73,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = new (std::nothrow) int;
+        int* x = support::do_not_optimize(new (std::nothrow) int);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
index 2ae0dfa4f1ab..e5f91ad44fc0 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
@@ -19,6 +19,7 @@
 #include <cstdlib>
 #include <cassert>
 
+#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -39,7 +40,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = new (std::nothrow) int(3);
+    int* x = support::do_not_optimize(new (std::nothrow) int(3));
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
index 3924274190c4..97f78ac62dab 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.alg/swap.pass.cpp
@@ -69,12 +69,12 @@ int main(int, char**)
     static_assert(noexcept(swap(f1, f2)), "" );
 #endif
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(f2.target<A>()->id() == 2);
     swap(f1, f2);
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f1.target<A>()->id() == 2);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
     }
@@ -87,12 +87,12 @@ int main(int, char**)
     static_assert(noexcept(swap(f1, f2)), "" );
 #endif
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
     swap(f1, f2);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
     }
@@ -105,12 +105,12 @@ int main(int, char**)
     static_assert(noexcept(swap(f1, f2)), "" );
 #endif
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
     swap(f1, f2);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
     }
@@ -123,12 +123,12 @@ int main(int, char**)
     static_assert(noexcept(swap(f1, f2)), "" );
 #endif
     assert(A::count == 0);
-    assert(globalMemCounter.checkOutstandingNewEq(0));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(0));
     RTTI_ASSERT(*f1.target<int(*)(int)>() == g);
     RTTI_ASSERT(*f2.target<int(*)(int)>() == h);
     swap(f1, f2);
     assert(A::count == 0);
-    assert(globalMemCounter.checkOutstandingNewEq(0));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(0));
     RTTI_ASSERT(*f1.target<int(*)(int)>() == h);
     RTTI_ASSERT(*f2.target<int(*)(int)>() == g);
     }
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
index c1ad528254af..92409577d60d 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F.pass.cpp
@@ -69,7 +69,7 @@ int main(int, char**)
     {
     std::function<int(int)> f = A();
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f.target<A>());
     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
     }
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
index 75eaa55dc71e..e3bd6ef78d61 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_assign.pass.cpp
@@ -57,13 +57,13 @@ int main(int, char**) {
   {
     std::function<int(int)> f = A();
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f.target<A>());
     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
     std::function<int(int)> f2;
     f2 = f;
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f2.target<A>());
     RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
   }
@@ -125,13 +125,13 @@ int main(int, char**) {
   {
     std::function<int(int)> f = A();
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f.target<A>());
     RTTI_ASSERT(f.target<int (*)(int)>() == 0);
     std::function<int(int)> f2;
     f2 = std::move(f);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f2.target<A>());
     RTTI_ASSERT(f2.target<int (*)(int)>() == 0);
     RTTI_ASSERT(f.target<A>() == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
index 4a2a272ae0a3..5b3f4f10cadb 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/copy_move.pass.cpp
@@ -64,12 +64,12 @@ int main(int, char**)
     {
     std::function<int(int)> f = A();
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f.target<A>());
     RTTI_ASSERT(f.target<int(*)(int)>() == 0);
     std::function<int(int)> f2 = f;
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f2.target<A>());
     RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
     }
@@ -113,7 +113,7 @@ int main(int, char**)
     { // Test rvalue references
         std::function<int(int)> f = A();
         assert(A::count == 1);
-        assert(globalMemCounter.checkOutstandingNewEq(1));
+        assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
         RTTI_ASSERT(f.target<A>());
         RTTI_ASSERT(f.target<int(*)(int)>() == 0);
         LIBCPP_ASSERT_NOEXCEPT(std::function<int(int)>(std::move(f)));
@@ -122,7 +122,7 @@ int main(int, char**)
 #endif
         std::function<int(int)> f2 = std::move(f);
         assert(A::count == 1);
-        assert(globalMemCounter.checkOutstandingNewEq(1));
+        assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
         RTTI_ASSERT(f2.target<A>());
         RTTI_ASSERT(f2.target<int(*)(int)>() == 0);
         RTTI_ASSERT(f.target<A>() == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
index 391e2a7434bf..b2f61fa9b68a 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/nullptr_t_assign.pass.cpp
@@ -57,7 +57,7 @@ int main(int, char**)
     {
     std::function<int(int)> f = A();
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f.target<A>());
     f = nullptr;
     assert(A::count == 0);
diff --git a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
index d51c35ea44fa..1723ddfd33be 100644
--- a/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.mod/swap.pass.cpp
@@ -68,12 +68,12 @@ int main(int, char**) {
     std::function<int(int)> f1 = A(1);
     std::function<int(int)> f2 = A(2);
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(f2.target<A>()->id() == 2);
     f1.swap(f2);
     assert(A::count == 2);
-    assert(globalMemCounter.checkOutstandingNewEq(2));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(2));
     RTTI_ASSERT(f1.target<A>()->id() == 2);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
   }
@@ -83,12 +83,12 @@ int main(int, char**) {
     std::function<int(int)> f1 = A(1);
     std::function<int(int)> f2 = g;
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(*f2.target<int (*)(int)>() == g);
     f1.swap(f2);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(*f1.target<int (*)(int)>() == g);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
   }
@@ -98,12 +98,12 @@ int main(int, char**) {
     std::function<int(int)> f1 = g;
     std::function<int(int)> f2 = A(1);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(*f1.target<int (*)(int)>() == g);
     RTTI_ASSERT(f2.target<A>()->id() == 1);
     f1.swap(f2);
     assert(A::count == 1);
-    assert(globalMemCounter.checkOutstandingNewEq(1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(1));
     RTTI_ASSERT(f1.target<A>()->id() == 1);
     RTTI_ASSERT(*f2.target<int (*)(int)>() == g);
   }
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
index 23a904f8ae11..be7505f218cd 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
@@ -96,7 +96,7 @@ int main(int, char**)
     int i = 67;
     char c = 'e';
     std::shared_ptr<A> p = std::make_shared<A>(i, c);
-    assert(globalMemCounter.checkOutstandingNewEq(nc+1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
     assert(A::count == 1);
     assert(p->get_int() == 67);
     assert(p->get_char() == 'e');
@@ -116,7 +116,7 @@ int main(int, char**)
     {
     char c = 'e';
     std::shared_ptr<A> p = std::make_shared<A>(67, c);
-    assert(globalMemCounter.checkOutstandingNewEq(nc+1));
+    assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
     assert(A::count == 1);
     assert(p->get_int() == 67);
     assert(p->get_char() == 'e');
diff --git a/libcxx/test/support/count_new.h b/libcxx/test/support/count_new.h
index b64248501016..ef4306e520b1 100644
--- a/libcxx/test/support/count_new.h
+++ b/libcxx/test/support/count_new.h
@@ -181,6 +181,11 @@ class MemCounter
         return disable_checking || n == outstanding_new;
     }
 
+    bool checkOutstandingNewLessThanOrEqual(int n) const
+    {
+        return disable_checking || outstanding_new <= n;
+    }
+
     bool checkOutstandingNewNotEq(int n) const
     {
         return disable_checking || n != outstanding_new;
diff --git a/libcxx/test/support/do_not_optimize.h b/libcxx/test/support/do_not_optimize.h
new file mode 100644
index 000000000000..542851a8ea6a
--- /dev/null
+++ b/libcxx/test/support/do_not_optimize.h
@@ -0,0 +1,28 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef SUPPORT_DO_NOT_OPTIMIZE_H
+#define SUPPORT_DO_NOT_OPTIMIZE_H
+
+#include "test_macros.h"
+
+namespace support {
+// This function can be used to hide some objects from compiler optimizations.
+//
+// For example, this is useful to hide the result of a call to `new` and ensure
+// that the compiler doesn't elide the call to new/delete. Otherwise, elliding
+// calls to new/delete is allowed by the Standard and compilers actually do it
+// when optimizations are enabled.
+template <class T>
+TEST_CONSTEXPR __attribute__((noinline)) T* do_not_optimize(T* ptr) TEST_NOEXCEPT {
+  return ptr;
+}
+} // namespace support
+
+#endif // SUPPORT_DO_NOT_OPTIMIZE_H
diff --git a/libcxx/utils/ci/run-buildbot b/libcxx/utils/ci/run-buildbot
index 445b1becee0c..5809d3ee956c 100755
--- a/libcxx/utils/ci/run-buildbot
+++ b/libcxx/utils/ci/run-buildbot
@@ -480,6 +480,11 @@ generic-abi-unstable)
     generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-abi-unstable.cmake"
     check-runtimes
 ;;
+generic-optimized-speed)
+    clean
+    generate-cmake -C "${MONOREPO_ROOT}/libcxx/cmake/caches/Generic-optimized-speed.cmake"
+    check-runtimes
+;;
 apple-system)
     clean
 
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 3fedbf972c0c..cb2bbf8b6b81 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -11,7 +11,7 @@
 from pathlib import Path
 
 from libcxx.test.dsl import *
-from libcxx.test.features import _isMSVC
+from libcxx.test.features import _isClang, _isAppleClang, _isGCC, _isMSVC
 
 
 _warningFlags = [
@@ -87,6 +87,21 @@ def getStdFlag(cfg, std):
         return "-std=" + fallbacks[std]
     return None
 
+def getSpeedOptimizationFlag(cfg):
+    if _isClang(cfg) or _isAppleClang(cfg) or _isGCC(cfg):
+        return "-O3"
+    elif _isMSVC(cfg):
+        return "/O2"
+    else:
+        raise RuntimeError("Can't figure out what compiler is used in the configuration")
+
+def getSizeOptimizationFlag(cfg):
+    if _isClang(cfg) or _isAppleClang(cfg) or _isGCC(cfg):
+        return "-Os"
+    elif _isMSVC(cfg):
+        return "/O1"
+    else:
+        raise RuntimeError("Can't figure out what compiler is used in the configuration")
 
 # fmt: off
 DEFAULT_PARAMETERS = [
@@ -118,6 +133,17 @@ def getStdFlag(cfg, std):
             AddCompileFlag(lambda cfg: getStdFlag(cfg, std)),
         ],
     ),
+    Parameter(
+        name="optimization",
+        choices=["none", "speed", "size"],
+        type=str,
+        help="The optimization level to use when compiling the test suite.",
+        default="none",
+        actions=lambda opt: filter(None, [
+            AddCompileFlag(lambda cfg: getSpeedOptimizationFlag(cfg)) if opt == "speed" else None,
+            AddCompileFlag(lambda cfg: getSizeOptimizationFlag(cfg)) if opt == "size" else None,
+        ]),
+    ),
     Parameter(
         name="enable_modules",
         choices=["none", "clang", "clang-lsv"],
diff --git a/libunwind/test/libunwind_02.pass.cpp b/libunwind/test/libunwind_02.pass.cpp
index ea34cd54222c..710325e42dc0 100644
--- a/libunwind/test/libunwind_02.pass.cpp
+++ b/libunwind/test/libunwind_02.pass.cpp
@@ -21,7 +21,7 @@
 #define EXPECTED_NUM_FRAMES 50
 #define NUM_FRAMES_UPPER_BOUND 100
 
-_Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
+__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
   (void)context;
   int *i = (int *)cnt;
   ++*i;
@@ -31,7 +31,7 @@ _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
   return _URC_NO_REASON;
 }
 
-void test_backtrace() {
+__attribute__((noinline)) void test_backtrace() {
   int n = 0;
   _Unwind_Backtrace(&callback, &n);
   if (n < EXPECTED_NUM_FRAMES) {
@@ -39,17 +39,33 @@ void test_backtrace() {
   }
 }
 
-int test(int i) {
+// These functions are effectively the same, but we have to be careful to avoid unwanted
+// optimizations that would mess with the number of frames we expect. Surprisingly,
+// slapping `noinline` is not sufficient -- we also have to avoid writing the function
+// in a way that the compiler can easily spot tail recursion.
+__attribute__((noinline)) int test1(int i);
+__attribute__((noinline)) int test2(int i);
+
+__attribute__((noinline)) int test1(int i) {
+  if (i == 0) {
+    test_backtrace();
+    return 0;
+  } else {
+    return i + test2(i - 1);
+  }
+}
+
+__attribute__((noinline)) int test2(int i) {
   if (i == 0) {
     test_backtrace();
     return 0;
   } else {
-    return i + test(i - 1);
+    return i + test1(i - 1);
   }
 }
 
 int main(int, char**) {
-  int total = test(50);
+  int total = test1(50);
   assert(total == 1275);
   return 0;
 }
diff --git a/libunwind/test/unw_resume.pass.cpp b/libunwind/test/unw_resume.pass.cpp
index 08e8d4edeaf2..2b7470b5cad0 100644
--- a/libunwind/test/unw_resume.pass.cpp
+++ b/libunwind/test/unw_resume.pass.cpp
@@ -15,7 +15,7 @@
 
 #include <libunwind.h>
 
-void test_unw_resume() {
+__attribute__((noinline)) void test_unw_resume() {
   unw_context_t context;
   unw_cursor_t cursor;
 
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index 8c9912e3c386..bcfb38f11f3f 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -28,7 +28,7 @@ _Unwind_Reason_Code frame_handler(struct _Unwind_Context* ctx, void* arg) {
   (void)arg;
   Dl_info info = { 0, 0, 0, 0 };
 
-  // Unwind until the main is reached, above frames deeped on the platform and
+  // Unwind until the main is reached, above frames depend on the platform and
   // architecture.
   if (dladdr(reinterpret_cast<void *>(_Unwind_GetIP(ctx)), &info) &&
       info.dli_sname && !strcmp("main", info.dli_sname)) {
@@ -43,18 +43,22 @@ void signal_handler(int signum) {
   _Exit(-1);
 }
 
-__attribute__((noinline)) void crashing_leaf_func(void) {
+__attribute__((noinline)) void crashing_leaf_func(int do_trap) {
   // libunwind searches for the address before the return address which points
-  // to the trap instruction. NOP guarantees the trap instruction is not the
-  // first instruction of the function.
-  // We should keep this here for other unwinders that also decrement pc.
-  __asm__ __volatile__("nop");
-  __builtin_trap();
+  // to the trap instruction. We make the trap conditional and prevent inlining
+  // of the function to ensure that the compiler doesn't remove the `ret` instruction
+  // altogether.
+  //
+  // It's also important that the trap instruction isn't the first instruction in the
+  // function (which it isn't because of the branch) for other unwinders that also
+  // decrement pc.
+  if (do_trap)
+    __builtin_trap();
 }
 
 int main(int, char**) {
   signal(SIGTRAP, signal_handler);
   signal(SIGILL, signal_handler);
-  crashing_leaf_func();
+  crashing_leaf_func(1);
   return -2;
 }

>From 56626ea2e9f978ee3625da824f0e11d6b5bf82d1 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 17 Nov 2023 16:44:28 -0500
Subject: [PATCH 2/5] Fix formatting

---
 libunwind/test/libunwind_02.pass.cpp        | 12 +++++++-----
 libunwind/test/unwind_leaffunction.pass.cpp | 10 +++++-----
 2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/libunwind/test/libunwind_02.pass.cpp b/libunwind/test/libunwind_02.pass.cpp
index 710325e42dc0..9fd8e5d7159c 100644
--- a/libunwind/test/libunwind_02.pass.cpp
+++ b/libunwind/test/libunwind_02.pass.cpp
@@ -21,7 +21,8 @@
 #define EXPECTED_NUM_FRAMES 50
 #define NUM_FRAMES_UPPER_BOUND 100
 
-__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context, void *cnt) {
+__attribute__((noinline)) _Unwind_Reason_Code callback(_Unwind_Context *context,
+                                                       void *cnt) {
   (void)context;
   int *i = (int *)cnt;
   ++*i;
@@ -39,10 +40,11 @@ __attribute__((noinline)) void test_backtrace() {
   }
 }
 
-// These functions are effectively the same, but we have to be careful to avoid unwanted
-// optimizations that would mess with the number of frames we expect. Surprisingly,
-// slapping `noinline` is not sufficient -- we also have to avoid writing the function
-// in a way that the compiler can easily spot tail recursion.
+// These functions are effectively the same, but we have to be careful to avoid
+// unwanted optimizations that would mess with the number of frames we expect.
+// Surprisingly, slapping `noinline` is not sufficient -- we also have to avoid
+// writing the function in a way that the compiler can easily spot tail
+// recursion.
 __attribute__((noinline)) int test1(int i);
 __attribute__((noinline)) int test2(int i);
 
diff --git a/libunwind/test/unwind_leaffunction.pass.cpp b/libunwind/test/unwind_leaffunction.pass.cpp
index bcfb38f11f3f..112a5968247a 100644
--- a/libunwind/test/unwind_leaffunction.pass.cpp
+++ b/libunwind/test/unwind_leaffunction.pass.cpp
@@ -46,12 +46,12 @@ void signal_handler(int signum) {
 __attribute__((noinline)) void crashing_leaf_func(int do_trap) {
   // libunwind searches for the address before the return address which points
   // to the trap instruction. We make the trap conditional and prevent inlining
-  // of the function to ensure that the compiler doesn't remove the `ret` instruction
-  // altogether.
+  // of the function to ensure that the compiler doesn't remove the `ret`
+  // instruction altogether.
   //
-  // It's also important that the trap instruction isn't the first instruction in the
-  // function (which it isn't because of the branch) for other unwinders that also
-  // decrement pc.
+  // It's also important that the trap instruction isn't the first instruction
+  // in the function (which it isn't because of the branch) for other unwinders
+  // that also decrement pc.
   if (do_trap)
     __builtin_trap();
 }

>From bc5f12b0c98e767a0a969d1495b93f7b82199a4f Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 20 Nov 2023 12:00:23 -0500
Subject: [PATCH 3/5] Remove re-implementation of DoNotOptimize

---
 .../support.dynamic/libcpp_deallocate.sh.cpp  | 17 ++++++-----
 .../new.size.replace.indirect.pass.cpp        |  3 +-
 .../new.size.replace.pass.cpp                 |  3 +-
 .../new.size_align.replace.indirect.pass.cpp  |  7 ++---
 ...ze_align_nothrow.replace.indirect.pass.cpp |  7 ++---
 .../new.size_align_nothrow.replace.pass.cpp   |  7 ++---
 ...new.size_nothrow.replace.indirect.pass.cpp |  3 +-
 .../new.size_nothrow.replace.pass.cpp         |  3 +-
 .../new.size.replace.pass.cpp                 |  3 +-
 ...ze_align_nothrow.replace.indirect.pass.cpp |  7 ++---
 ...new.size_nothrow.replace.indirect.pass.cpp |  3 +-
 libcxx/test/support/do_not_optimize.h         | 28 -------------------
 libcxx/test/support/test_macros.h             |  6 ++++
 13 files changed, 32 insertions(+), 65 deletions(-)
 delete mode 100644 libcxx/test/support/do_not_optimize.h

diff --git a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
index 6e6229b752a7..267f87bd3f6f 100644
--- a/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
+++ b/libcxx/test/libcxx/language.support/support.dynamic/libcpp_deallocate.sh.cpp
@@ -34,7 +34,6 @@
 #include <cstdlib>
 #include <new>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 TEST_DIAGNOSTIC_PUSH
@@ -188,13 +187,13 @@ void test_allocator_and_new_match() {
   stats.reset();
 #if defined(NO_SIZE) && defined(NO_ALIGN)
   {
-    int* x = support::do_not_optimize(new int(42));
+    int* x = DoNotOptimize(new int(42));
     delete x;
     assert(stats.expect_plain());
   }
   stats.reset();
   {
-    AlignedType* a = support::do_not_optimize(new AlignedType());
+    AlignedType* a = DoNotOptimize(new AlignedType());
     delete a;
     assert(stats.expect_plain());
   }
@@ -203,14 +202,14 @@ void test_allocator_and_new_match() {
   stats.reset();
 #if TEST_STD_VER >= 11
   {
-    int* x = support::do_not_optimize(new int(42));
+    int* x = DoNotOptimize(new int(42));
     delete x;
     assert(stats.expect_plain());
   }
 #endif
   stats.reset();
   {
-    AlignedType* a = support::do_not_optimize(new AlignedType());
+    AlignedType* a = DoNotOptimize(new AlignedType());
     delete a;
     assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));
   }
@@ -218,13 +217,13 @@ void test_allocator_and_new_match() {
 #elif defined(NO_ALIGN)
   stats.reset();
   {
-    int* x = support::do_not_optimize(new int(42));
+    int* x = DoNotOptimize(new int(42));
     delete x;
     assert(stats.expect_size(sizeof(int)));
   }
   stats.reset();
   {
-    AlignedType* a = support::do_not_optimize(new AlignedType());
+    AlignedType* a = DoNotOptimize(new AlignedType());
     delete a;
     assert(stats.expect_size(sizeof(AlignedType)));
   }
@@ -232,13 +231,13 @@ void test_allocator_and_new_match() {
 #else
   stats.reset();
   {
-    int* x = support::do_not_optimize(new int(42));
+    int* x = DoNotOptimize(new int(42));
     delete x;
     assert(stats.expect_size(sizeof(int)));
   }
   stats.reset();
   {
-    AlignedType* a = support::do_not_optimize(new AlignedType());
+    AlignedType* a = DoNotOptimize(new AlignedType());
     delete a;
     assert(stats.expect_size_align(sizeof(AlignedType),
                                    TEST_ALIGNOF(AlignedType)));
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
index 13f6217c521f..daedbb38d05c 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.indirect.pass.cpp
@@ -20,7 +20,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -41,7 +40,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = support::do_not_optimize(new int[3]);
+    int* x = DoNotOptimize(new int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
index 9b3d39986484..5fa3d72b7816 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size.replace.pass.cpp
@@ -19,7 +19,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -39,7 +38,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = support::do_not_optimize(new int[3]);
+    int* x = DoNotOptimize(new int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
index 014951f50b7e..66cbb4b9c8eb 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align.replace.indirect.pass.cpp
@@ -26,7 +26,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -52,7 +51,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = support::do_not_optimize(new OverAligned[3]);
+        OverAligned* x = DoNotOptimize(new OverAligned[3]);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -63,7 +62,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = support::do_not_optimize(new MaxAligned[3]);
+        MaxAligned* x = DoNotOptimize(new MaxAligned[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -74,7 +73,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = support::do_not_optimize(new int[3]);
+        int* x = DoNotOptimize(new int[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
index 99926b876a03..df8a651932ce 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.indirect.pass.cpp
@@ -26,7 +26,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -52,7 +51,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
+        OverAligned* x = DoNotOptimize(new (std::nothrow) OverAligned[3]);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -63,7 +62,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
+        MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -74,7 +73,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = support::do_not_optimize(new (std::nothrow) int[3]);
+        int* x = DoNotOptimize(new (std::nothrow) int[3]);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
index cd8af782f972..b984e8cf0a43 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_align_nothrow.replace.pass.cpp
@@ -23,7 +23,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -49,7 +48,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_nothrow_called = delete_called = 0;
-        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned[3]);
+        OverAligned* x = DoNotOptimize(new (std::nothrow) OverAligned[3]);
         assert(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
 
@@ -60,7 +59,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_nothrow_called = delete_called = 0;
-        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned[3]);
+        MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned[3]);
         assert(x != nullptr);
         assert(new_nothrow_called == 0);
 
@@ -71,7 +70,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_nothrow_called = delete_called = 0;
-        int* x = support::do_not_optimize(new (std::nothrow) int[3]);
+        int* x = DoNotOptimize(new (std::nothrow) int[3]);
         assert(x != nullptr);
         assert(new_nothrow_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
index 8b0d801acd1f..eb14e3d15db2 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.indirect.pass.cpp
@@ -24,7 +24,6 @@
 #include <cstdlib>
 #include <cassert>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -45,7 +44,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = support::do_not_optimize(new (std::nothrow) int[3]);
+    int* x = DoNotOptimize(new (std::nothrow) int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
index c9e4942d8153..2b8918276d77 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.array/new.size_nothrow.replace.pass.cpp
@@ -18,7 +18,6 @@
 #include <cstdlib>
 #include <cassert>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_nothrow_called = 0;
@@ -36,7 +35,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_nothrow_called = delete_called = 0;
-    int* x = support::do_not_optimize(new (std::nothrow) int[3]);
+    int* x = DoNotOptimize(new (std::nothrow) int[3]);
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
index c62268c39027..a345559e832c 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size.replace.pass.cpp
@@ -17,7 +17,6 @@
 #include <cstdlib>
 #include <cassert>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -37,7 +36,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = support::do_not_optimize(new int(3));
+    int* x = DoNotOptimize(new int(3));
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
index 1c42cdbb50db..a68cdab54528 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_align_nothrow.replace.indirect.pass.cpp
@@ -25,7 +25,6 @@
 #include <cassert>
 #include <limits>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 #include "../types.h"
 
@@ -51,7 +50,7 @@ int main(int, char**) {
     // Test with an overaligned type
     {
         new_called = delete_called = 0;
-        OverAligned* x = support::do_not_optimize(new (std::nothrow) OverAligned);
+        OverAligned* x = DoNotOptimize(new (std::nothrow) OverAligned);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(static_cast<void*>(x) == DummyData);
         ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
@@ -62,7 +61,7 @@ int main(int, char**) {
     // Test with a type that is right on the verge of being overaligned
     {
         new_called = delete_called = 0;
-        MaxAligned* x = support::do_not_optimize(new (std::nothrow) MaxAligned);
+        MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned);
         assert(x != nullptr);
         assert(new_called == 0);
 
@@ -73,7 +72,7 @@ int main(int, char**) {
     // Test with a type that is clearly not overaligned
     {
         new_called = delete_called = 0;
-        int* x = support::do_not_optimize(new (std::nothrow) int);
+        int* x = DoNotOptimize(new (std::nothrow) int);
         assert(x != nullptr);
         assert(new_called == 0);
 
diff --git a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
index e5f91ad44fc0..c72e99d387e1 100644
--- a/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
+++ b/libcxx/test/std/language.support/support.dynamic/new.delete/new.delete.single/new.size_nothrow.replace.indirect.pass.cpp
@@ -19,7 +19,6 @@
 #include <cstdlib>
 #include <cassert>
 
-#include "do_not_optimize.h"
 #include "test_macros.h"
 
 int new_called = 0;
@@ -40,7 +39,7 @@ void operator delete(void* p) TEST_NOEXCEPT {
 
 int main(int, char**) {
     new_called = delete_called = 0;
-    int* x = support::do_not_optimize(new (std::nothrow) int(3));
+    int* x = DoNotOptimize(new (std::nothrow) int(3));
     assert(x != nullptr);
     ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);
 
diff --git a/libcxx/test/support/do_not_optimize.h b/libcxx/test/support/do_not_optimize.h
deleted file mode 100644
index 542851a8ea6a..000000000000
--- a/libcxx/test/support/do_not_optimize.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// -*- C++ -*-
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SUPPORT_DO_NOT_OPTIMIZE_H
-#define SUPPORT_DO_NOT_OPTIMIZE_H
-
-#include "test_macros.h"
-
-namespace support {
-// This function can be used to hide some objects from compiler optimizations.
-//
-// For example, this is useful to hide the result of a call to `new` and ensure
-// that the compiler doesn't elide the call to new/delete. Otherwise, elliding
-// calls to new/delete is allowed by the Standard and compilers actually do it
-// when optimizations are enabled.
-template <class T>
-TEST_CONSTEXPR __attribute__((noinline)) T* do_not_optimize(T* ptr) TEST_NOEXCEPT {
-  return ptr;
-}
-} // namespace support
-
-#endif // SUPPORT_DO_NOT_OPTIMIZE_H
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index f3c6d8080ff6..a38772a6eb5c 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -274,6 +274,12 @@ struct is_same<T, T> { enum {value = 1}; };
 #endif
 
 #if defined(__GNUC__) || defined(__clang__)
+// This function can be used to hide some objects from compiler optimizations.
+//
+// For example, this is useful to hide the result of a call to `new` and ensure
+// that the compiler doesn't elide the call to new/delete. Otherwise, elliding
+// calls to new/delete is allowed by the Standard and compilers actually do it
+// when optimizations are enabled.
 template <class Tp>
 inline
 void DoNotOptimize(Tp const& value) {

>From 1b132d6d9ba47681ebd8a86b8e4e53fe68a6b5b4 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Fri, 1 Dec 2023 11:30:16 -0500
Subject: [PATCH 4/5] Fix DoNotOptimize

---
 libcxx/test/support/test_macros.h | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index a38772a6eb5c..9d7f2978b948 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -281,18 +281,19 @@ struct is_same<T, T> { enum {value = 1}; };
 // calls to new/delete is allowed by the Standard and compilers actually do it
 // when optimizations are enabled.
 template <class Tp>
-inline
-void DoNotOptimize(Tp const& value) {
+inline Tp const& DoNotOptimize(Tp const& value) {
     asm volatile("" : : "r,m"(value) : "memory");
+    return value;
 }
 
 template <class Tp>
-inline void DoNotOptimize(Tp& value) {
+inline Tp& DoNotOptimize(Tp& value) {
 #if defined(__clang__)
   asm volatile("" : "+r,m"(value) : : "memory");
 #else
   asm volatile("" : "+m,r"(value) : : "memory");
 #endif
+  return value;
 }
 #else
 #include <intrin.h>

>From 995337c71bf4895918c01283ba2c728002b70f06 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Sat, 2 Dec 2023 08:19:33 -0500
Subject: [PATCH 5/5] Fix DoNotOptimize test on GCC

---
 .../allocator.members/allocate.cxx2a.pass.cpp                  | 2 +-
 libcxx/test/support/test_macros.h                              | 3 ++-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp
index da35465c5295..f2fb606ee6db 100644
--- a/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp
+++ b/libcxx/test/libcxx/depr/depr.default.allocator/allocator.members/allocate.cxx2a.pass.cpp
@@ -60,7 +60,7 @@ void test_aligned() {
   {
     globalMemCounter.last_new_size = 0;
     globalMemCounter.last_new_align = 0;
-    T* volatile ap2 = a.allocate(11, (const void*)5);
+    T* ap2 = a.allocate(11, (const void*)5);
     DoNotOptimize(ap2);
     assert(globalMemCounter.checkOutstandingNewEq(1));
     assert(globalMemCounter.checkNewCalledEq(1));
diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h
index 9d7f2978b948..56476139367e 100644
--- a/libcxx/test/support/test_macros.h
+++ b/libcxx/test/support/test_macros.h
@@ -298,10 +298,11 @@ inline Tp& DoNotOptimize(Tp& value) {
 #else
 #include <intrin.h>
 template <class Tp>
-inline void DoNotOptimize(Tp const& value) {
+inline Tp const& DoNotOptimize(Tp const& value) {
   const volatile void* volatile unused = __builtin_addressof(value);
   static_cast<void>(unused);
   _ReadWriteBarrier();
+  return value;
 }
 #endif
 



More information about the cfe-commits mailing list