114 lines
4.1 KiB
Diff
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}")
|