diff --git a/src/settings_internal.js b/src/settings_internal.js index ae89b4b194730..d475180b40954 100644 --- a/src/settings_internal.js +++ b/src/settings_internal.js @@ -260,6 +260,11 @@ var ASYNCIFY_IMPORTS_EXCEPT_JS_LIBS = []; var WARN_DEPRECATED = true; +// Enable fast math optimizations in wasm-opt when -ffast-math is passed. +// This enables aggressive floating-point optimizations that may violate +// IEEE 754 semantics but can improve performance. +var FAST_MATH = 0; + // WebGL 2 provides new garbage-free entry points to call to WebGL. Use // those always when possible. // We currently set this to false for certain browser when large memory sizes diff --git a/test/test_other.py b/test/test_other.py index ddcd572e56a23..1d287fadad283 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -15202,6 +15202,14 @@ def has_defined_function(file, func): self.assertIn('foo.cpp', out) self.assertIn('/emsdk/emscripten/system/lib/libc/musl/src/string/strcmp.c', out) + def test_binaryen_fast_math(self): + # Use a simple input; contents don't matter for -v flag inspection + err = self.run_process([EMCC, test_file('hello_world.c'), '-v', '-O2', '-ffast-math'], stderr=PIPE).stderr + self.assertContained('--fast-math', err) + + err_no_fast = self.run_process([EMCC, test_file('hello_world.c'), '-v', '-O2'], stderr=PIPE).stderr + self.assertNotContained('--fast-math', err_no_fast) + def test_relocatable(self): # This setting is due for removal: # https://github.com/emscripten-core/emscripten/issues/25262 diff --git a/tools/cmdline.py b/tools/cmdline.py index 0afc105aa24e7..6fa339962d7ab 100644 --- a/tools/cmdline.py +++ b/tools/cmdline.py @@ -301,9 +301,8 @@ def consume_arg_file(): settings.SHRINK_LEVEL = 0 settings.DEBUG_LEVEL = max(settings.DEBUG_LEVEL, 1) elif requested_level == 'fast': - # TODO(https://github.com/emscripten-core/emscripten/issues/21497): - # If we ever map `-ffast-math` to `wasm-opt --fast-math` then - # then we should enable that too here. + # -Ofast typically includes -ffast-math semantics + settings.FAST_MATH = 1 requested_level = 3 settings.SHRINK_LEVEL = 0 else: @@ -552,6 +551,8 @@ def consume_arg_file(): settings.WASM_EXCEPTIONS = 1 elif arg == '-fignore-exceptions': settings.DISABLE_EXCEPTION_CATCHING = 1 + elif arg == '-ffast-math': + settings.FAST_MATH = 1 elif check_arg('--default-obj-ext'): exit_with_error('--default-obj-ext is no longer supported by emcc') elif arg.startswith('-fsanitize=cfi'): diff --git a/tools/link.py b/tools/link.py index 040764ccc5e72..0dc696e988ec2 100644 --- a/tools/link.py +++ b/tools/link.py @@ -392,6 +392,8 @@ def get_binaryen_passes(): passes += ['--pass-arg=post-emscripten-side-module'] if optimizing: passes += [building.opt_level_to_str(settings.OPT_LEVEL, settings.SHRINK_LEVEL)] + if settings.FAST_MATH: + passes += ['--fast-math'] # when optimizing, use the fact that low memory is never used (1024 is a # hardcoded value in the binaryen pass). we also cannot do it when the stack # is first, as then the stack is in the low memory that should be unused.