aom_encoder: enable floating point exceptions
with --enable-debug (CONFIG_DEBUG) when available
BUG=aomedia:388
Change-Id: I5dd0718d6bd0ba17bc1b52d5842e250244d2d1d8
diff --git a/aom/src/aom_encoder.c b/aom/src/aom_encoder.c
index 41c70ef..ac84c88 100644
--- a/aom/src/aom_encoder.c
+++ b/aom/src/aom_encoder.c
@@ -13,9 +13,15 @@
* \brief Provides the high level interface to wrap encoder algorithms.
*
*/
+#include "./aom_config.h"
+
+#if HAVE_FEXCEPT
+#define _GNU_SOURCE
+#include <fenv.h>
+#endif
+
#include <limits.h>
#include <string.h>
-#include "aom_config.h"
#include "aom/internal/aom_codec_internal.h"
#define SAVE_STATUS(ctx, var) (ctx ? (ctx->err = var) : var)
@@ -168,23 +174,42 @@
return res;
}
+/* clang-format off */
+#define FLOATING_POINT_BEGIN_SCOPE do {
+#define FLOATING_POINT_END_SCOPE } while (0);
+/* clang-format on */
+
#if ARCH_X86 || ARCH_X86_64
/* On X86, disable the x87 unit's internal 80 bit precision for better
* consistency with the SSE unit's 64 bit precision.
*/
#include "aom_ports/x86.h"
-#define FLOATING_POINT_INIT() \
- do { \
- unsigned short x87_orig_mode = x87_set_double_precision();
-#define FLOATING_POINT_RESTORE() \
- x87_set_control_word(x87_orig_mode); \
- } \
- while (0)
-
+#define FLOATING_POINT_SET_PRECISION \
+ unsigned short x87_orig_mode = x87_set_double_precision();
+#define FLOATING_POINT_RESTORE_PRECISION x87_set_control_word(x87_orig_mode);
#else
-static void FLOATING_POINT_INIT() {}
-static void FLOATING_POINT_RESTORE() {}
-#endif
+#define FLOATING_POINT_SET_PRECISION
+#define FLOATING_POINT_RESTORE_PRECISION
+#endif // ARCH_X86 || ARCH_X86_64
+
+#if HAVE_FEXCEPT && CONFIG_DEBUG
+#define FLOATING_POINT_SET_EXCEPTIONS \
+ const int float_excepts = feenableexcept(FE_DIVBYZERO);
+#define FLOATING_POINT_RESTORE_EXCEPTIONS feenableexcept(float_excepts);
+#else
+#define FLOATING_POINT_SET_EXCEPTIONS
+#define FLOATING_POINT_RESTORE_EXCEPTIONS
+#endif // HAVE_FEXCEPT && CONFIG_DEBUG
+
+#define FLOATING_POINT_INIT \
+ FLOATING_POINT_BEGIN_SCOPE \
+ FLOATING_POINT_SET_PRECISION \
+ FLOATING_POINT_SET_EXCEPTIONS
+
+#define FLOATING_POINT_RESTORE \
+ FLOATING_POINT_RESTORE_EXCEPTIONS \
+ FLOATING_POINT_RESTORE_PRECISION \
+ FLOATING_POINT_END_SCOPE
aom_codec_err_t aom_codec_encode(aom_codec_ctx_t *ctx, const aom_image_t *img,
aom_codec_pts_t pts, unsigned long duration,
@@ -204,7 +229,7 @@
/* Execute in a normalized floating point environment, if the platform
* requires it.
*/
- FLOATING_POINT_INIT();
+ FLOATING_POINT_INIT
if (num_enc == 1)
res = ctx->iface->enc.encode(get_alg_priv(ctx), img, pts, duration, flags,
@@ -231,7 +256,7 @@
ctx++;
}
- FLOATING_POINT_RESTORE();
+ FLOATING_POINT_RESTORE
}
return SAVE_STATUS(ctx, res);
diff --git a/build/cmake/aom_config.h.cmake b/build/cmake/aom_config.h.cmake
index d565559..2e95e23 100644
--- a/build/cmake/aom_config.h.cmake
+++ b/build/cmake/aom_config.h.cmake
@@ -36,6 +36,7 @@
#define HAVE_AVX ${HAVE_AVX}
#define HAVE_AVX2 ${HAVE_AVX2}
#define HAVE_AOM_PORTS ${HAVE_AOM_PORTS}
+#define HAVE_FEXCEPT ${HAVE_FEXCEPT}
#define HAVE_PTHREAD_H ${HAVE_PTHREAD_H}
#define HAVE_UNISTD_H ${HAVE_UNISTD_H}
#define CONFIG_DEPENDENCY_TRACKING ${CONFIG_DEPENDENCY_TRACKING}
diff --git a/build/cmake/aom_config_defaults.cmake b/build/cmake/aom_config_defaults.cmake
index d457e58..441bdf3 100644
--- a/build/cmake/aom_config_defaults.cmake
+++ b/build/cmake/aom_config_defaults.cmake
@@ -36,6 +36,7 @@
set(HAVE_AVX 0 CACHE BOOL "Enables AVX optimizations.")
set(HAVE_AVX2 0 CACHE BOOL "Enables AVX2 optimizations.")
set(HAVE_AOM_PORTS 0 CACHE BOOL "Internal flag, deprecated.")
+set(HAVE_FEXCEPT 0 CACHE BOOL "Internal flag, GNU fenv.h present for target.")
set(HAVE_PTHREAD_H 0 CACHE BOOL "Internal flag, target pthread support.")
set(HAVE_UNISTD_H 0 CACHE BOOL "Internal flag, unistd.h present for target.")
set(CONFIG_DEPENDENCY_TRACKING 1 CACHE BOOL "Internal flag.")
diff --git a/build/cmake/aom_configure.cmake b/build/cmake/aom_configure.cmake
index 34e0142..31f826e 100644
--- a/build/cmake/aom_configure.cmake
+++ b/build/cmake/aom_configure.cmake
@@ -158,6 +158,17 @@
"CONFIG_ANS and CONFIG_DAALA_EC cannot be enabled together.")
endif ()
+if (NOT MSVC)
+ aom_push_var(CMAKE_REQUIRED_LIBRARIES "m")
+ aom_check_c_compiles("fenv_check"
+ "#define _GNU_SOURCE
+ #include <fenv.h>
+ void unused(void) {
+ (void)feenableexcept(FE_DIVBYZERO | FE_INVALID);
+ }" HAVE_FEXCEPT)
+ aom_pop_var(CMAKE_REQUIRED_LIBRARIES)
+endif()
+
# TODO(tomfinegan): consume trailing whitespace after configure_file() when
# target platform check produces empty INLINE and RESTRICT values (aka empty
# values require special casing).
diff --git a/build/cmake/compiler_tests.cmake b/build/cmake/compiler_tests.cmake
index e3c0e9a..e763597 100644
--- a/build/cmake/compiler_tests.cmake
+++ b/build/cmake/compiler_tests.cmake
@@ -21,6 +21,16 @@
set(AOM_CXX_PASSED_TESTS)
set(AOM_CXX_FAILED_TESTS)
+function(aom_push_var var new_value)
+ set(SAVED_${var} ${var} PARENT_SCOPE)
+ set(${var} ${new_value} PARENT_SCOPE)
+endfunction ()
+
+function(aom_pop_var var)
+ set(var ${SAVED_${var}} PARENT_SCOPE)
+ unset(SAVED_${var} PARENT_SCOPE)
+endfunction ()
+
# Confirms $test_source compiles and stores $test_name in one of
# $AOM_C_PASSED_TESTS or $AOM_C_FAILED_TESTS depending on out come. When the
# test passes $result_var is set to 1. When it fails $result_var is unset.
diff --git a/configure b/configure
index 5a24bed..ad240ba 100755
--- a/configure
+++ b/configure
@@ -238,6 +238,7 @@
HAVE_LIST="
${ARCH_EXT_LIST}
aom_ports
+ fexcept
pthread_h
unistd_h
wxwidgets
@@ -649,6 +650,12 @@
check_header unistd.h # for sysconf(3) and friends.
check_header aom/aom_integer.h -I${source_path} && enable_feature aom_ports
+
+ check_ld <<EOF && enable_feature fexcept
+#define _GNU_SOURCE
+#include <fenv.h>
+int main(void) { (void)feenableexcept(FE_DIVBYZERO | FE_INVALID); return 0; }
+EOF
}
process_toolchain() {