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