From 0159f87cfaf679f55bcc99f375a772ea3374d272 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Fri, 5 Mar 2021 12:19:32 -0500 Subject: Disable double-double unit tests Compiler bugs make unit tests flaky on double-double platforms. Apply a patch from upstream to disable the relevant tests on those platforms. --- debian/changelog | 1 + debian/patches/disable-double-double-tests.diff | 489 ++++++++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 491 insertions(+) create mode 100644 debian/patches/disable-double-double-tests.diff diff --git a/debian/changelog b/debian/changelog index e3f4e909..500ef137 100644 --- a/debian/changelog +++ b/debian/changelog @@ -2,6 +2,7 @@ abseil (0~20200923.3-3) UNRELEASED; urgency=medium * Fix "ftbfs with -march=x86-64-v3" by correcting the relevant unit tests. (Closes: #983936) + * Disable double-double unit tests due to compiler bugs. -- Benjamin Barenblat Thu, 04 Mar 2021 14:37:45 -0500 diff --git a/debian/patches/disable-double-double-tests.diff b/debian/patches/disable-double-double-tests.diff new file mode 100644 index 00000000..e80a8a78 --- /dev/null +++ b/debian/patches/disable-double-double-tests.diff @@ -0,0 +1,489 @@ +From: Benjamin Barenblat +Subject: Stop testing with double-double random variables +Forwarded: yes +Applied-Upstream: https://github.com/abseil/abseil-cpp/commit/ab21820d47e4f83875dda008b600514d3520fd35 + +On POWER, long double is often represented as a pair of doubles added +together (double-double arithmetic). We’ve already special-cased +double-double arithmetic in a number of tests, but compiler +bugs [1, 2, 3] have now triggered both false positives and false +negatives, which suggests testing with double doubles is unlikely to +yield useful signal. Remove the special casing and detect if we’re on a +double-double system; if so, just don’t test long doubles. + +[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048 +[2] https://bugs.llvm.org/show_bug.cgi?id=49131 +[3] https://bugs.llvm.org/show_bug.cgi?id=49132 + +The author works at Google. Upstream applied this patch as Piper +revision 360793161 and exported it to GitHub; the the Applied-Upstream +URL above points to the exported commit. + +--- a/CMake/AbseilDll.cmake ++++ b/CMake/AbseilDll.cmake +@@ -126,6 +126,7 @@ set(ABSL_INTERNAL_DLL_FILES + "meta/type_traits.h" + "numeric/int128.cc" + "numeric/int128.h" ++ "numeric/internal/representation.h" + "random/bernoulli_distribution.h" + "random/beta_distribution.h" + "random/bit_gen_ref.h" +--- a/absl/numeric/BUILD.bazel ++++ b/absl/numeric/BUILD.bazel +@@ -72,3 +72,15 @@ + "@com_github_google_benchmark//:benchmark_main", + ], + ) ++ ++cc_library( ++ name = "representation", ++ hdrs = [ ++ "internal/representation.h", ++ ], ++ copts = ABSL_DEFAULT_COPTS, ++ linkopts = ABSL_DEFAULT_LINKOPTS, ++ deps = [ ++ "//absl/base:config", ++ ], ++) +--- a/absl/numeric/CMakeLists.txt ++++ b/absl/numeric/CMakeLists.txt +@@ -59,3 +59,15 @@ + absl::int128 + PUBLIC + ) ++ ++absl_cc_library( ++ NAME ++ numeric_representation ++ HDRS ++ "internal/representation.h" ++ COPTS ++ ${ABSL_DEFAULT_COPTS} ++ DEPS ++ absl::config ++ PUBLIC ++) +--- /dev/null ++++ b/absl/numeric/internal/representation.h +@@ -0,0 +1,55 @@ ++// Copyright 2021 The Abseil Authors ++// ++// Licensed under the Apache License, Version 2.0 (the "License"); ++// you may not use this file except in compliance with the License. ++// You may obtain a copy of the License at ++// ++// https://www.apache.org/licenses/LICENSE-2.0 ++// ++// Unless required by applicable law or agreed to in writing, software ++// distributed under the License is distributed on an "AS IS" BASIS, ++// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++// See the License for the specific language governing permissions and ++// limitations under the License. ++ ++#ifndef ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++#define ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ ++ ++#include ++ ++#include "absl/base/config.h" ++ ++namespace absl { ++ABSL_NAMESPACE_BEGIN ++namespace numeric_internal { ++ ++// Returns true iff long double is represented as a pair of doubles added ++// together. ++inline constexpr bool IsDoubleDouble() { ++ // A double-double value always has exactly twice the precision of a double ++ // value--one double carries the high digits and one double carries the low ++ // digits. This property is not shared with any other common floating-point ++ // representation, so this test won't trigger false positives. For reference, ++ // this table gives the number of bits of precision of each common ++ // floating-point representation: ++ // ++ // type precision ++ // IEEE single 24 b ++ // IEEE double 53 ++ // x86 long double 64 ++ // double-double 106 ++ // IEEE quadruple 113 ++ // ++ // Note in particular that a quadruple-precision float has greater precision ++ // than a double-double float despite taking up the same amount of memory; the ++ // quad has more of its bits allocated to the mantissa than the double-double ++ // has. ++ return std::numeric_limits::digits == ++ 2 * std::numeric_limits::digits; ++} ++ ++} // namespace numeric_internal ++ABSL_NAMESPACE_END ++} // namespace absl ++ ++#endif // ABSL_NUMERIC_INTERNAL_REPRESENTATION_H_ +--- a/absl/random/BUILD.bazel ++++ b/absl/random/BUILD.bazel +@@ -187,6 +187,7 @@ cc_test(name = "beta_distribution_test", + ":distributions", + ":random", + "//absl/base:raw_logging_internal", ++ "//absl/numeric:representation", + "//absl/random/internal:distribution_test_util", + "//absl/random/internal:pcg_engine", + "//absl/random/internal:sequence_urbg", +@@ -307,6 +308,7 @@ cc_test(name = "exponential_distribution_test", + ":random", + "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ++ "//absl/numeric:representation", + "//absl/random/internal:distribution_test_util", + "//absl/random/internal:pcg_engine", + "//absl/random/internal:sequence_urbg", +@@ -330,6 +332,7 @@ cc_test(name = "gaussian_distribution_test", + ":random", + "//absl/base:core_headers", + "//absl/base:raw_logging_internal", ++ "//absl/numeric:representation", + "//absl/random/internal:distribution_test_util", + "//absl/random/internal:sequence_urbg", + "//absl/strings", +@@ -376,6 +379,7 @@ cc_test(name = "uniform_real_distribution_test", + ":distributions", + ":random", + "//absl/base:raw_logging_internal", ++ "//absl/numeric:representation", + "//absl/random/internal:distribution_test_util", + "//absl/random/internal:pcg_engine", + "//absl/random/internal:sequence_urbg", +--- a/absl/random/CMakeLists.txt ++++ b/absl/random/CMakeLists.txt +@@ -259,6 +259,7 @@ absl_cc_test(NAME random_beta_distribution_test + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS ++ absl::numeric_representation + absl::random_distributions + absl::random_random + absl::random_internal_distribution_test_util +@@ -381,6 +382,7 @@ absl_cc_test(NAME random_exponential_distribution_test + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::core_headers ++ absl::numeric_representation + absl::random_distributions + absl::random_internal_distribution_test_util + absl::random_internal_pcg_engine +@@ -404,6 +406,7 @@ absl_cc_test(NAME random_gaussian_distribution_test + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::core_headers ++ absl::numeric_representation + absl::random_distributions + absl::random_internal_distribution_test_util + absl::random_internal_sequence_urbg +@@ -446,6 +449,7 @@ absl_cc_test(NAME random_uniform_real_distribution_test + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS ++ absl::numeric_representation + absl::random_distributions + absl::random_internal_distribution_test_util + absl::random_internal_pcg_engine +--- a/absl/random/beta_distribution_test.cc ++++ b/absl/random/beta_distribution_test.cc +@@ -21,12 +21,14 @@ + #include + #include + #include ++#include + #include + #include + + #include "gmock/gmock.h" + #include "gtest/gtest.h" + #include "absl/base/internal/raw_logging.h" ++#include "absl/numeric/internal/representation.h" + #include "absl/random/internal/chi_square.h" + #include "absl/random/internal/distribution_test_util.h" + #include "absl/random/internal/pcg_engine.h" +@@ -42,7 +44,15 @@ + template + class BetaDistributionInterfaceTest : public ::testing::Test {}; + +-using RealTypes = ::testing::Types; ++// double-double arithmetic is not supported well by either GCC or Clang; see ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048, ++// https://bugs.llvm.org/show_bug.cgi?id=49131, and ++// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests ++// with double doubles until compiler support is better. ++using RealTypes = ++ std::conditional, ++ ::testing::Types>::type; + TYPED_TEST_CASE(BetaDistributionInterfaceTest, RealTypes); + + TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest) { +@@ -53,9 +63,6 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest { + const TypeParam kLargeA = + std::exp(std::log((std::numeric_limits::max)()) - + std::log(std::log((std::numeric_limits::max)()))); +- const TypeParam kLargeAPPC = std::exp( +- std::log((std::numeric_limits::max)()) - +- std::log(std::log((std::numeric_limits::max)())) - 10.0f); + using param_type = typename absl::beta_distribution::param_type; + + constexpr int kCount = 1000; +@@ -76,9 +83,6 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest { + kLargeA, // + std::nextafter(kLargeA, TypeParam(0)), // + std::nextafter(kLargeA, std::numeric_limits::max()), +- kLargeAPPC, // +- std::nextafter(kLargeAPPC, TypeParam(0)), +- std::nextafter(kLargeAPPC, std::numeric_limits::max()), + // Boundary cases. + std::numeric_limits::max(), + std::numeric_limits::epsilon(), +@@ -125,28 +129,6 @@ TYPED_TEST(BetaDistributionInterfaceTest, SerializeTest { + + ss >> after; + +-#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ +- defined(__ppc__) || defined(__PPC__) +- if (std::is_same::value) { +- // Roundtripping floating point values requires sufficient precision +- // to reconstruct the exact value. It turns out that long double +- // has some errors doing this on ppc. +- if (alpha <= std::numeric_limits::max() && +- alpha >= std::numeric_limits::lowest()) { +- EXPECT_EQ(static_cast(before.alpha()), +- static_cast(after.alpha())) +- << ss.str(); +- } +- if (beta <= std::numeric_limits::max() && +- beta >= std::numeric_limits::lowest()) { +- EXPECT_EQ(static_cast(before.beta()), +- static_cast(after.beta())) +- << ss.str(); +- } +- continue; +- } +-#endif +- + EXPECT_EQ(before.alpha(), after.alpha()); + EXPECT_EQ(before.beta(), after.beta()); + EXPECT_EQ(before, after) // +--- a/absl/random/exponential_distribution_test.cc ++++ b/absl/random/exponential_distribution_test.cc +@@ -30,6 +30,7 @@ + #include "gtest/gtest.h" + #include "absl/base/internal/raw_logging.h" + #include "absl/base/macros.h" ++#include "absl/numeric/internal/representation.h" + #include "absl/random/internal/chi_square.h" + #include "absl/random/internal/distribution_test_util.h" + #include "absl/random/internal/pcg_engine.h" +@@ -50,7 +51,15 @@ + #if defined(__EMSCRIPTEN__) + using RealTypes = ::testing::Types; + #else +-using RealTypes = ::testing::Types; ++// double-double arithmetic is not supported well by either GCC or Clang; see ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048, ++// https://bugs.llvm.org/show_bug.cgi?id=49131, and ++// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests ++// with double doubles until compiler support is better. ++using RealTypes = ++ std::conditional, ++ ::testing::Types>::type; + #endif // defined(__EMSCRIPTEN__) + TYPED_TEST_CASE(ExponentialDistributionTypedTest, RealTypes); + +@@ -130,23 +139,6 @@ TYPED_TEST(ExponentialDistributionTypedTest, SerializeTest) { + + ss >> after; + +-#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ +- defined(__ppc__) || defined(__PPC__) +- if (std::is_same::value) { +- // Roundtripping floating point values requires sufficient precision to +- // reconstruct the exact value. It turns out that long double has some +- // errors doing this on ppc, particularly for values +- // near {1.0 +/- epsilon}. +- if (lambda <= std::numeric_limits::max() && +- lambda >= std::numeric_limits::lowest()) { +- EXPECT_EQ(static_cast(before.lambda()), +- static_cast(after.lambda())) +- << ss.str(); +- } +- continue; +- } +-#endif +- + EXPECT_EQ(before.lambda(), after.lambda()) // + << ss.str() << " " // + << (ss.good() ? "good " : "") // +--- a/absl/random/gaussian_distribution_test.cc ++++ b/absl/random/gaussian_distribution_test.cc +@@ -21,12 +21,14 @@ + #include + #include + #include ++#include + #include + + #include "gmock/gmock.h" + #include "gtest/gtest.h" + #include "absl/base/internal/raw_logging.h" + #include "absl/base/macros.h" ++#include "absl/numeric/internal/representation.h" + #include "absl/random/internal/chi_square.h" + #include "absl/random/internal/distribution_test_util.h" + #include "absl/random/internal/sequence_urbg.h" +@@ -43,7 +45,15 @@ + template + class GaussianDistributionInterfaceTest : public ::testing::Test {}; + +-using RealTypes = ::testing::Types; ++// double-double arithmetic is not supported well by either GCC or Clang; see ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048, ++// https://bugs.llvm.org/show_bug.cgi?id=49131, and ++// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests ++// with double doubles until compiler support is better. ++using RealTypes = ++ std::conditional, ++ ::testing::Types>::type; + TYPED_TEST_CASE(GaussianDistributionInterfaceTest, RealTypes); + + TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) { +@@ -129,32 +139,6 @@ TYPED_TEST(GaussianDistributionInterfaceTest, SerializeTest) { + + ss >> after; + +-#if defined(__powerpc64__) || defined(__PPC64__) || defined(__powerpc__) || \ +- defined(__ppc__) || defined(__PPC__) || defined(__EMSCRIPTEN__) +- if (std::is_same::value) { +- // Roundtripping floating point values requires sufficient precision +- // to reconstruct the exact value. It turns out that long double +- // has some errors doing this on ppc, particularly for values +- // near {1.0 +/- epsilon}. +- // +- // Emscripten is even worse, implementing long double as a 128-bit +- // type, but shipping with a strtold() that doesn't support that. +- if (mean <= std::numeric_limits::max() && +- mean >= std::numeric_limits::lowest()) { +- EXPECT_EQ(static_cast(before.mean()), +- static_cast(after.mean())) +- << ss.str(); +- } +- if (stddev <= std::numeric_limits::max() && +- stddev >= std::numeric_limits::lowest()) { +- EXPECT_EQ(static_cast(before.stddev()), +- static_cast(after.stddev())) +- << ss.str(); +- } +- continue; +- } +-#endif +- + EXPECT_EQ(before.mean(), after.mean()); + EXPECT_EQ(before.stddev(), after.stddev()) // + << ss.str() << " " // +--- a/absl/random/uniform_real_distribution_test.cc ++++ b/absl/random/uniform_real_distribution_test.cc +@@ -20,11 +20,13 @@ + #include + #include + #include ++#include + #include + + #include "gmock/gmock.h" + #include "gtest/gtest.h" + #include "absl/base/internal/raw_logging.h" ++#include "absl/numeric/internal/representation.h" + #include "absl/random/internal/chi_square.h" + #include "absl/random/internal/distribution_test_util.h" + #include "absl/random/internal/pcg_engine.h" +@@ -58,7 +60,15 @@ + #if defined(__EMSCRIPTEN__) + using RealTypes = ::testing::Types; + #else +-using RealTypes = ::testing::Types; ++// double-double arithmetic is not supported well by either GCC or Clang; see ++// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99048, ++// https://bugs.llvm.org/show_bug.cgi?id=49131, and ++// https://bugs.llvm.org/show_bug.cgi?id=49132. Don't bother running these tests ++// with double doubles until compiler support is better. ++using RealTypes = ++ std::conditional, ++ ::testing::Types>::type; + #endif // defined(__EMSCRIPTEN__) + + TYPED_TEST_SUITE(UniformRealDistributionTest, RealTypes); +--- a/absl/strings/BUILD.bazel ++++ b/absl/strings/BUILD.bazel +@@ -645,6 +645,7 @@ cc_library(name = "str_format_internal", + "//absl/functional:function_ref", + "//absl/meta:type_traits", + "//absl/numeric:int128", ++ "//absl/numeric:representation", + "//absl/types:optional", + "//absl/types:span", + ], +--- a/absl/strings/CMakeLists.txt ++++ b/absl/strings/CMakeLists.txt +@@ -396,6 +396,7 @@ absl_cc_library(NAME str_format_internal + absl::strings + absl::config + absl::core_headers ++ absl::numeric_representation + absl::type_traits + absl::int128 + absl::span +--- a/absl/strings/internal/str_format/float_conversion.cc ++++ b/absl/strings/internal/str_format/float_conversion.cc +@@ -15,6 +15,7 @@ + #include "absl/functional/function_ref.h" + #include "absl/meta/type_traits.h" + #include "absl/numeric/int128.h" ++#include "absl/numeric/internal/representation.h" + #include "absl/strings/numbers.h" + #include "absl/types/optional.h" + #include "absl/types/span.h" +@@ -25,6 +26,8 @@ + + namespace { + ++using ::absl::numeric_internal::IsDoubleDouble; ++ + // The code below wants to avoid heap allocations. + // To do so it needs to allocate memory on the stack. + // `StackArray` will allocate memory on the stack in the form of a uint32_t +@@ -98,13 +101,6 @@ + return next_carry % divisor; + } + +-constexpr bool IsDoubleDouble() { +- // This is the `double-double` representation of `long double`. +- // We do not handle it natively. Fallback to snprintf. +- return std::numeric_limits::digits == +- 2 * std::numeric_limits::digits; +-} +- + using MaxFloatType = + typename std::conditional::type; + +@@ -1391,6 +1387,8 @@ + bool ConvertFloatImpl(long double v, const FormatConversionSpecImpl &conv, + FormatSinkImpl *sink) { + if (IsDoubleDouble()) { ++ // This is the `double-double` representation of `long double`. We do not ++ // handle it natively. Fallback to snprintf. + return FallbackToSnprintf(v, conv, sink); + } + diff --git a/debian/patches/series b/debian/patches/series index c07c5a22..efe60449 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -8,3 +8,4 @@ endian-hash.diff endian-random.diff ppc-float-conversion.diff fma-contraction.diff +disable-double-double-tests.diff -- cgit v1.2.3