Skip to content

Commit

Permalink
[libc++] Allow running the test suite with optimizations (#68753)
Browse files Browse the repository at this point in the history
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]: #68552
  • Loading branch information
ldionne committed Jan 9, 2024
1 parent 07c9189 commit ca06c33
Show file tree
Hide file tree
Showing 31 changed files with 157 additions and 74 deletions.
1 change: 1 addition & 0 deletions .github/workflows/libcxx-build-and-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ jobs:
'generic-no-unicode',
'generic-no-wide-characters',
'generic-no-rtti',
'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
Expand Down
4 changes: 4 additions & 0 deletions libcxx/cmake/caches/Generic-optimized-speed.cmake
Original file line number Diff line number Diff line change
@@ -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 "")
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,13 @@ void test_allocator_and_new_match() {
stats.reset();
#if defined(NO_SIZE) && defined(NO_ALIGN)
{
int* x = new int(42);
int* x = DoNotOptimize(new int(42));
delete x;
assert(stats.expect_plain());
}
stats.reset();
{
AlignedType* a = new AlignedType();
AlignedType* a = DoNotOptimize(new AlignedType());
delete a;
assert(stats.expect_plain());
}
Expand All @@ -202,42 +202,42 @@ void test_allocator_and_new_match() {
stats.reset();
#if TEST_STD_VER >= 11
{
int* x = new int(42);
int* x = DoNotOptimize(new int(42));
delete x;
assert(stats.expect_plain());
}
#endif
stats.reset();
{
AlignedType* a = new AlignedType();
AlignedType* a = DoNotOptimize(new AlignedType());
delete a;
assert(stats.expect_align(TEST_ALIGNOF(AlignedType)));
}
stats.reset();
#elif defined(NO_ALIGN)
stats.reset();
{
int* x = new int(42);
int* x = DoNotOptimize(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
AlignedType* a = new AlignedType();
AlignedType* a = DoNotOptimize(new AlignedType());
delete a;
assert(stats.expect_size(sizeof(AlignedType)));
}
stats.reset();
#else
stats.reset();
{
int* x = new int(42);
int* x = DoNotOptimize(new int(42));
delete x;
assert(stats.expect_size(sizeof(int)));
}
stats.reset();
{
AlignedType* a = new AlignedType();
AlignedType* a = DoNotOptimize(new AlignedType());
delete a;
assert(stats.expect_size_align(sizeof(AlignedType),
TEST_ALIGNOF(AlignedType)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
// UNSUPPORTED: c++03, c++11, c++14
// XFAIL: target=powerpc{{.*}}le-unknown-linux-gnu

// TODO: This test makes incorrect assumptions about floating point conversions.
// See https://github.com/llvm/llvm-project/issues/74327.
// XFAIL: optimization=speed

// <experimental/simd>
//
// [simd.class]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ void operator delete(void* p) TEST_NOEXCEPT {

int main(int, char**) {
new_called = delete_called = 0;
int* x = new int[3];
int* x = DoNotOptimize(new int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void operator delete[](void* p) TEST_NOEXCEPT {

int main(int, char**) {
new_called = delete_called = 0;
int* x = new int[3];
int* x = DoNotOptimize(new int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
OverAligned* x = 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);

Expand All @@ -62,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 MaxAligned[3];
MaxAligned* x = DoNotOptimize(new MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);

Expand All @@ -73,7 +73,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 = DoNotOptimize(new int[3]);
assert(x != nullptr);
assert(new_called == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
OverAligned* x = 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);

Expand All @@ -62,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[3];
MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_called == 0);

Expand All @@ -73,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[3];
int* x = DoNotOptimize(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_called == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,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 = DoNotOptimize(new (std::nothrow) OverAligned[3]);
assert(static_cast<void*>(x) == DummyData);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);

Expand All @@ -59,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 = new (std::nothrow) MaxAligned[3];
MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);

Expand All @@ -70,7 +70,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 = DoNotOptimize(new (std::nothrow) int[3]);
assert(x != nullptr);
assert(new_nothrow_called == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,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 = DoNotOptimize(new (std::nothrow) int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,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 = DoNotOptimize(new (std::nothrow) int[3]);
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_nothrow_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void operator delete(void* p) TEST_NOEXCEPT {

int main(int, char**) {
new_called = delete_called = 0;
int* x = new int(3);
int* x = DoNotOptimize(new int(3));
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int main(int, char**) {
// Test with an overaligned type
{
new_called = delete_called = 0;
OverAligned* x = 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);

Expand All @@ -61,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 = new (std::nothrow) MaxAligned;
MaxAligned* x = DoNotOptimize(new (std::nothrow) MaxAligned);
assert(x != nullptr);
assert(new_called == 0);

Expand All @@ -72,7 +72,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 = DoNotOptimize(new (std::nothrow) int);
assert(x != nullptr);
assert(new_called == 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,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 = DoNotOptimize(new (std::nothrow) int(3));
assert(x != nullptr);
ASSERT_WITH_OPERATOR_NEW_FALLBACKS(new_called == 1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit ca06c33

Please sign in to comment.