From 006b28a982e3938d29952341a2ebdeae77b42b16 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Thu, 4 Mar 2021 14:43:19 -0500 Subject: Make Abseil unit tests tolerate fused multiply/add contraction Apply a patch from upstream to make tests pass when GCC replaces double addition and multiplication with fused multiply/add instructions. --- debian/patches/fma-contraction.diff | 63 +++++++++++++++++++++++++++++++++++++ debian/patches/series | 1 + 2 files changed, 64 insertions(+) create mode 100644 debian/patches/fma-contraction.diff (limited to 'debian/patches') diff --git a/debian/patches/fma-contraction.diff b/debian/patches/fma-contraction.diff new file mode 100644 index 00000000..95181a36 --- /dev/null +++ b/debian/patches/fma-contraction.diff @@ -0,0 +1,63 @@ +From: Benjamin Barenblat +Subject: Make tests tolerant of FMA contraction +Forwarded: yes +Applied-Upstream: https://github.com/abseil/abseil-cpp/commit/b0735979d778a768caee207f01f327535cbd2140 + +Weaken Duration.ToDoubleSecondsCheckEdgeCases and +Duration.ToDoubleSecondsCheckRandom to make them less sensitive to fused +multiply/add contraction. + +The author works at Google. Upstream applied this patch as Piper +revision 360297653 and exported it to GitHub; the the Applied-Upstream URL +above points to the exported commit. + +--- a/absl/time/duration_test.cc ++++ b/absl/time/duration_test.cc +@@ -1369,10 +1369,13 @@ + EXPECT_THAT(ToTimeval(absl::Nanoseconds(2000)), TimevalMatcher(tv)); + } + +-void VerifySameAsMul(double time_as_seconds, int* const misses) { ++void VerifyApproxSameAsMul(double time_as_seconds, int* const misses) { + auto direct_seconds = absl::Seconds(time_as_seconds); + auto mul_by_one_second = time_as_seconds * absl::Seconds(1); +- if (direct_seconds != mul_by_one_second) { ++ // These are expected to differ by up to one tick due to fused multiply/add ++ // contraction. ++ if (absl::AbsDuration(direct_seconds - mul_by_one_second) > ++ absl::time_internal::MakeDuration(0, 1u)) { + if (*misses > 10) return; + ASSERT_LE(++(*misses), 10) << "Too many errors, not reporting more."; + EXPECT_EQ(direct_seconds, mul_by_one_second) +@@ -1384,7 +1387,8 @@ + // For a variety of interesting durations, we find the exact point + // where one double converts to that duration, and the very next double + // converts to the next duration. For both of those points, verify that +-// Seconds(point) returns the same duration as point * Seconds(1.0) ++// Seconds(point) returns a duration near point * Seconds(1.0). (They may ++// not be exactly equal due to fused multiply/add contraction.) + TEST(Duration, ToDoubleSecondsCheckEdgeCases) { + constexpr uint32_t kTicksPerSecond = absl::time_internal::kTicksPerSecond; + constexpr auto duration_tick = absl::time_internal::MakeDuration(0, 1u); +@@ -1423,8 +1427,8 @@ + } + // Now low_edge is the highest double that converts to Duration d, + // and high_edge is the lowest double that converts to Duration after_d. +- VerifySameAsMul(low_edge, &misses); +- VerifySameAsMul(high_edge, &misses); ++ VerifyApproxSameAsMul(low_edge, &misses); ++ VerifyApproxSameAsMul(high_edge, &misses); + } + } + } +@@ -1444,8 +1448,8 @@ + int misses = 0; + for (int i = 0; i < 1000000; ++i) { + double d = std::exp(uniform(gen)); +- VerifySameAsMul(d, &misses); +- VerifySameAsMul(-d, &misses); ++ VerifyApproxSameAsMul(d, &misses); ++ VerifyApproxSameAsMul(-d, &misses); + } + } + diff --git a/debian/patches/series b/debian/patches/series index ceceb694..c07c5a22 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -7,3 +7,4 @@ nan-narrowing.diff endian-hash.diff endian-random.diff ppc-float-conversion.diff +fma-contraction.diff -- cgit v1.2.3