mysql/community-mysql-5.7.13-fpu.patch
2016-07-13 19:52:17 +02:00

114 lines
4.1 KiB
Diff

commit 34ee5b9ce2d3ab1ccfb91016ee058949c69c1066
Author: Norvald H. Ryeng <norvald.ryeng@oracle.com>
Date: Fri May 27 15:19:56 2016 +0200
Bug#23046775 DIFFERENT FLOATING POINT RESULTS ON ARM64 AND POWERPC
Backport from trunk.
Problem: The -fexpensive-optimizations option to gcc causes ARM64 and
PowerPC build to compute floating point operations slightly
differently from other platforms. This flag is enabled by -O2 and
higher optimization levels.
Fix: Check for the unwanted floating point behavior in CMake and
disable expensive-optimizations in GCC builds on platforms that
experience this behavior.
diff --git a/cmake/build_configurations/compiler_options.cmake b/cmake/build_configurations/compiler_options.cmake
index 98d553a..f105c7a 100644
--- a/cmake/build_configurations/compiler_options.cmake
+++ b/cmake/build_configurations/compiler_options.cmake
@@ -15,6 +15,7 @@
INCLUDE(CheckCCompilerFlag)
INCLUDE(CheckCXXCompilerFlag)
+INCLUDE(cmake/floating_point.cmake)
IF(SIZEOF_VOIDP EQUAL 4)
SET(32BIT 1)
@@ -33,6 +34,10 @@ IF(UNIX)
IF(WITH_VALGRIND)
SET(COMMON_C_FLAGS "-fno-inline ${COMMON_C_FLAGS}")
ENDIF()
+ # Disable optimizations that change floating point results
+ IF(HAVE_C_FLOATING_POINT_OPTIMIZATION_PROBLEMS)
+ SET(COMMON_C_FLAGS "${COMMON_C_FLAGS} -fno-expensive-optimizations")
+ ENDIF()
SET(CMAKE_C_FLAGS_DEBUG "${COMMON_C_FLAGS}")
SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_C_FLAGS}")
ENDIF()
@@ -48,6 +53,10 @@ IF(UNIX)
IF(WITH_VALGRIND)
SET(COMMON_CXX_FLAGS "-fno-inline ${COMMON_CXX_FLAGS}")
ENDIF()
+ # Disable optimizations that change floating point results
+ IF(HAVE_CXX_FLOATING_POINT_OPTIMIZATION_PROBLEMS)
+ SET(COMMON_CXX_FLAGS "${COMMON_CXX_FLAGS} -fno-expensive-optimizations")
+ ENDIF()
SET(CMAKE_CXX_FLAGS_DEBUG "${COMMON_CXX_FLAGS}")
SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${COMMON_CXX_FLAGS}")
ENDIF()
diff --git a/cmake/floating_point.cmake b/cmake/floating_point.cmake
new file mode 100644
index 0000000..6db63ad
--- /dev/null
+++ b/cmake/floating_point.cmake
@@ -0,0 +1,56 @@
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+INCLUDE(CheckCSourceRuns)
+INCLUDE(CheckCXXSourceRuns)
+
+SET(code "
+ int main (int argc, char **argv)
+ {
+ double n[21] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,1 };
+ double m= 0, s= 0;
+ int i;
+ for(i= 0; i < 21; i++)
+ {
+ double m_kminusone= m;
+ m= m_kminusone + (n[i] - m_kminusone) / (double) (i + 2);
+ s= s + (n[i] - m_kminusone) * (n[i] - m);
+ }
+ /*
+ s should now be either 5e 74 d1 45 17 5d 14 40 or
+ 40 14 5d 17 45 d1 74 5e, depending on endianness. If the floating point
+ operations are over optimized, the least significant byte is 5d instead
+ of 5e.
+ */
+ return (*(unsigned char*)(&s) == 0x5e ||
+ *((unsigned char*)(&s) + 7) == 0x5e);
+ }"
+)
+
+SET(SAVE_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+SET(CMAKE_REQUIRED_FLAGS
+ "${CMAKE_REQUIRED_FLAGS} -O3 -fexpensive-optimizations"
+)
+
+IF(CMAKE_COMPILER_IS_GNUCC)
+ CHECK_C_SOURCE_RUNS("${code}" HAVE_C_FLOATING_POINT_OPTIMIZATION_PROBLEMS)
+ENDIF()
+
+IF(CMAKE_COMPILER_IS_GNUCXX)
+ CHECK_CXX_SOURCE_RUNS("${code}" HAVE_CXX_FLOATING_POINT_OPTIMIZATION_PROBLEMS)
+ENDIF()
+
+SET(CMAKE_REQUIRED_FLAGS "${SAVE_CMAKE_REQUIRED_FLAGS}")