diff options
author | Keith Winstein <keithw@cs.stanford.edu> | 2022-07-11 17:12:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-11 17:12:49 -0700 |
commit | a7d484ef3d1f64649dd9f48cb1d5434f0fda561b (patch) | |
tree | 817862cfd2bbf1ac5290b9d0a55087ad6ccf8ebc /wasm2c/examples | |
parent | 4132e35b51849678ac9e5592089e00057f260ccf (diff) | |
download | wabt-a7d484ef3d1f64649dd9f48cb1d5434f0fda561b.tar.gz wabt-a7d484ef3d1f64649dd9f48cb1d5434f0fda561b.tar.bz2 wabt-a7d484ef3d1f64649dd9f48cb1d5434f0fda561b.zip |
wasm2c: run tests with -O2 on non-Windows (#1939)
Enable optimization when compiling the wasm2c output on non-Windows platforms (effectively GCC and clang). This required:
- Preventing load instructions from being optimized away if their value is unused (using inline assembly with an input operand and empty code). This is necessary to force an OOB trap on platforms that use mprotect and the signal handler to detect OOB.
- Disabling tail-call optimization in the compiler, to make sure that infinite recursion traps. (This required bumping the version of macOS in GitHub Actions to get a new-enough AppleClang. We should revert this back to 'macos-latest' as soon as that becomes the default.)
- Using NaN-quieting versions of a bunch of FP ops that were previously only used on Windows, and adding floor/ceil and promotion/demotion.
- Using the '-frounding-math' and '-fsignaling-nans' compiler flags to tell GCC and clang not to fold certain FP ops (e.g. subtracting zero, multiplying by 1).
Fixes #1925.
Diffstat (limited to 'wasm2c/examples')
-rw-r--r-- | wasm2c/examples/fac/fac.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/wasm2c/examples/fac/fac.c b/wasm2c/examples/fac/fac.c index 30f1e9bb..106d7768 100644 --- a/wasm2c/examples/fac/fac.c +++ b/wasm2c/examples/fac/fac.c @@ -36,6 +36,12 @@ #define MEMCHECK(mem, a, t) RANGE_CHECK(mem, a, sizeof(t)) #endif +#ifdef __GNUC__ +#define wasm_asm __asm__ +#else +#define wasm_asm(X) +#endif + #if WABT_BIG_ENDIAN static inline void load_data(void* dest, const void* src, size_t n) { size_t i = 0; @@ -58,6 +64,7 @@ static inline void load_data(void* dest, const void* src, size_t n) { t1 result; \ wasm_rt_memcpy(&result, &mem->data[mem->size - addr - sizeof(t1)], \ sizeof(t1)); \ + wasm_asm("" ::"r"(result)); \ return (t3)(t2)result; \ } @@ -82,6 +89,7 @@ static inline void load_data(void* dest, const void* src, size_t n) { MEMCHECK(mem, addr, t1); \ t1 result; \ wasm_rt_memcpy(&result, &mem->data[addr], sizeof(t1)); \ + wasm_asm("" ::"r"(result)); \ return (t3)(t2)result; \ } @@ -319,6 +327,128 @@ DEFINE_REINTERPRET(i32_reinterpret_f32, f32, u32) DEFINE_REINTERPRET(f64_reinterpret_i64, u64, f64) DEFINE_REINTERPRET(i64_reinterpret_f64, f64, u64) +static float quiet_nanf(float x) { + uint32_t tmp; + memcpy(&tmp, &x, 4); + tmp |= 0x7fc00000lu; + memcpy(&x, &tmp, 4); + return x; +} + +static double quiet_nan(double x) { + uint64_t tmp; + memcpy(&tmp, &x, 8); + tmp |= 0x7ff8000000000000llu; + memcpy(&x, &tmp, 8); + return x; +} + +static double wasm_quiet(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return x; +} + +static float wasm_quietf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return x; +} + +static double wasm_floor(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return floor(x); +} + +static float wasm_floorf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return floorf(x); +} + +static double wasm_ceil(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return ceil(x); +} + +static float wasm_ceilf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return ceilf(x); +} + +static double wasm_trunc(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return trunc(x); +} + +static float wasm_truncf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return truncf(x); +} + +static float wasm_nearbyintf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return nearbyintf(x); +} + +static double wasm_nearbyint(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return nearbyint(x); +} + +static float wasm_fabsf(float x) { + if (UNLIKELY(isnan(x))) { + uint32_t tmp; + memcpy(&tmp, &x, 4); + tmp = tmp & ~(1 << 31); + memcpy(&x, &tmp, 4); + return x; + } + return fabsf(x); +} + +static double wasm_fabs(double x) { + if (UNLIKELY(isnan(x))) { + uint64_t tmp; + memcpy(&tmp, &x, 8); + tmp = tmp & ~(1ll << 63); + memcpy(&x, &tmp, 8); + return x; + } + return fabs(x); +} + +static double wasm_sqrt(double x) { + if (UNLIKELY(isnan(x))) { + return quiet_nan(x); + } + return sqrt(x); +} + +static float wasm_sqrtf(float x) { + if (UNLIKELY(isnan(x))) { + return quiet_nanf(x); + } + return sqrtf(x); +} + static u32 func_types[1]; static void init_func_types(void) { func_types[0] = wasm_rt_register_func_type(1, 1, WASM_RT_I32, WASM_RT_I32); |