diff options
author | Alon Zakai <azakai@google.com> | 2019-05-02 14:17:49 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-02 14:17:49 -0700 |
commit | 29e7e4483dc04ca8e882f12871c7eb395c82de00 (patch) | |
tree | 40b968dfef03b6cb4b877850bce1c2507e2bc8df | |
parent | b394fcc887dbb2e02b5ff5b307004e4dc7ec2baf (diff) | |
download | binaryen-29e7e4483dc04ca8e882f12871c7eb395c82de00.tar.gz binaryen-29e7e4483dc04ca8e882f12871c7eb395c82de00.tar.bz2 binaryen-29e7e4483dc04ca8e882f12871c7eb395c82de00.zip |
wasm2js: ignore implicit traps (#2079)
We don't actually try to emit traps for loads, stores, invalid float to ints, etc., so when optimizing we may as well do so under the assumption those traps do not exist.
This lets us emit nice code for a select whose operands are loads, for example - otherwise, the values seem to have side effects.
-rw-r--r-- | src/tools/wasm2js.cpp | 2 | ||||
-rw-r--r-- | src/wasm2js.h | 10 | ||||
-rw-r--r-- | test/wasm2js.asserts.js | 2 | ||||
-rw-r--r-- | test/wasm2js.traps.js | 2 | ||||
-rw-r--r-- | test/wasm2js/conversions-modified.2asm.js.opt | 30 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js | 9 | ||||
-rw-r--r-- | test/wasm2js/emscripten.2asm.js.opt | 12 | ||||
-rw-r--r-- | test/wasm2js/emscripten.wast | 8 | ||||
-rw-r--r-- | test/wasm2js/float-ops.2asm.js.opt | 26 |
9 files changed, 41 insertions, 60 deletions
diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp index 823ab7f96..7ceb63ffc 100644 --- a/src/tools/wasm2js.cpp +++ b/src/tools/wasm2js.cpp @@ -603,7 +603,7 @@ void AssertionEmitter::emit() { } function i64Equal(actual_lo, actual_hi, expected_lo, expected_hi) { - return actual_lo == (expected_lo | 0) && actual_hi == (expected_hi | 0); + return (actual_lo | 0) == (expected_lo | 0) && (actual_hi | 0) == (expected_hi | 0); } )"; diff --git a/src/wasm2js.h b/src/wasm2js.h index f15e8f9b7..731bf0a8c 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -124,7 +124,15 @@ public: bool emscripten = false; }; - Wasm2JSBuilder(Flags f, PassOptions options) : flags(f), options(options) {} + Wasm2JSBuilder(Flags f, PassOptions options_) : flags(f), options(options_) { + // We don't try to model wasm's trapping precisely - if we did, each load + // and store would need to do a check. Given that, we can just ignore + // implicit traps like those when optimizing. (When not optimizing, it's + // nice to see codegen that matches wasm more precisely.) + if (options.optimizeLevel > 0) { + options.ignoreImplicitTraps = true; + } + } Ref processWasm(Module* wasm, Name funcName = ASM_FUNC); Ref processFunction(Module* wasm, Function* func, bool standalone = false); diff --git a/test/wasm2js.asserts.js b/test/wasm2js.asserts.js index 7cc3bde33..b48d06940 100644 --- a/test/wasm2js.asserts.js +++ b/test/wasm2js.asserts.js @@ -27,7 +27,7 @@ } function i64Equal(actual_lo, actual_hi, expected_lo, expected_hi) { - return actual_lo == (expected_lo | 0) && actual_hi == (expected_hi | 0); + return (actual_lo | 0) == (expected_lo | 0) && (actual_hi | 0) == (expected_hi | 0); } function asmFunc0(global, env, buffer) { diff --git a/test/wasm2js.traps.js b/test/wasm2js.traps.js index 81b3c8b74..756e97b58 100644 --- a/test/wasm2js.traps.js +++ b/test/wasm2js.traps.js @@ -27,7 +27,7 @@ } function i64Equal(actual_lo, actual_hi, expected_lo, expected_hi) { - return actual_lo == (expected_lo | 0) && actual_hi == (expected_hi | 0); + return (actual_lo | 0) == (expected_lo | 0) && (actual_hi | 0) == (expected_hi | 0); } function asmFunc0(global, env, buffer) { diff --git a/test/wasm2js/conversions-modified.2asm.js.opt b/test/wasm2js/conversions-modified.2asm.js.opt index 1f1fd7ac5..2a28ceeba 100644 --- a/test/wasm2js/conversions-modified.2asm.js.opt +++ b/test/wasm2js/conversions-modified.2asm.js.opt @@ -76,36 +76,14 @@ function asmFunc(global, env, buffer) { function $7($0) { $0 = Math_fround($0); - var $1 = 0, $2 = 0; - $2 = ~~$0 >>> 0; - if (Math_fround(Math_abs($0)) >= Math_fround(1.0)) { - if ($0 > Math_fround(0.0)) { - $1 = ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 / Math_fround(4294967296.0)))), Math_fround(4294967296.0))) >>> 0 - } else { - $1 = ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) / Math_fround(4294967296.0)))) >>> 0 - } - } else { - $1 = 0 - } - i64toi32_i32$HIGH_BITS = $1; - return $2 | 0; + i64toi32_i32$HIGH_BITS = Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ($0 > Math_fround(0.0) ? ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 / Math_fround(4294967296.0)))), Math_fround(4294967296.0))) >>> 0 : ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) / Math_fround(4294967296.0)))) >>> 0) : 0; + return ~~$0 >>> 0; } function $9($0) { $0 = +$0; - var $1 = 0, $2 = 0; - $2 = ~~$0 >>> 0; - if (Math_abs($0) >= 1.0) { - if ($0 > 0.0) { - $1 = ~~Math_min(Math_floor($0 / 4294967296.0), 4294967295.0) >>> 0 - } else { - $1 = ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) / 4294967296.0) >>> 0 - } - } else { - $1 = 0 - } - i64toi32_i32$HIGH_BITS = $1; - return $2 | 0; + i64toi32_i32$HIGH_BITS = Math_abs($0) >= 1.0 ? ($0 > 0.0 ? ~~Math_min(Math_floor($0 / 4294967296.0), 4294967295.0) >>> 0 : ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) / 4294967296.0) >>> 0) : 0; + return ~~$0 >>> 0; } function $11($0) { diff --git a/test/wasm2js/emscripten.2asm.js b/test/wasm2js/emscripten.2asm.js index 79da32b8f..664eb654a 100644 --- a/test/wasm2js/emscripten.2asm.js +++ b/test/wasm2js/emscripten.2asm.js @@ -80,6 +80,12 @@ function asmFunc(global, env, buffer) { return x - -5 | 0 | 0; } + function select(x) { + x = x | 0; + var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0, wasm2js_i32$2 = 0; + return (wasm2js_i32$0 = x, wasm2js_i32$1 = HEAP32[16 >> 2] | 0, wasm2js_i32$2 = x, wasm2js_i32$2 ? wasm2js_i32$0 : wasm2js_i32$1) | 0; + } + // EMSCRIPTEN_END_FUNCS; FUNCTION_TABLE[1] = foo; FUNCTION_TABLE[2] = bar; @@ -89,7 +95,8 @@ function asmFunc(global, env, buffer) { "other": other, "__growWasmMemory": __growWasmMemory, "exported": exported, - "sub_zero": sub_zero + "sub_zero": sub_zero, + "select": select }; } diff --git a/test/wasm2js/emscripten.2asm.js.opt b/test/wasm2js/emscripten.2asm.js.opt index ae1c9c53d..4426d7400 100644 --- a/test/wasm2js/emscripten.2asm.js.opt +++ b/test/wasm2js/emscripten.2asm.js.opt @@ -41,10 +41,6 @@ function asmFunc(global, env, buffer) { } function bar() { - HEAPU8[128 | 0]; - HEAP8[128 | 0]; - HEAPU16[128 >> 1]; - HEAP16[128 >> 1]; HEAP32[16 >> 2] = 3; HEAPF32[16 >> 2] = 7; HEAPF64[16 >> 3] = 11; @@ -66,6 +62,11 @@ function asmFunc(global, env, buffer) { return $0 + 5 | 0; } + function select($0) { + $0 = $0 | 0; + return ($0 ? $0 : HEAP32[16 >> 2]) | 0; + } + // EMSCRIPTEN_END_FUNCS; FUNCTION_TABLE[1] = foo; FUNCTION_TABLE[2] = bar; @@ -75,7 +76,8 @@ function asmFunc(global, env, buffer) { "other": other, "__growWasmMemory": __growWasmMemory, "exported": internal, - "sub_zero": sub_zero + "sub_zero": sub_zero, + "select": select }; } diff --git a/test/wasm2js/emscripten.wast b/test/wasm2js/emscripten.wast index 8f797f8fc..5731eacff 100644 --- a/test/wasm2js/emscripten.wast +++ b/test/wasm2js/emscripten.wast @@ -13,6 +13,7 @@ (export "__growWasmMemory" (func $__growWasmMemory)) (export "exported" (func $exported)) (export "sub-zero" (func $sub-zero)) + (export "select" (func $select)) (func $main (drop (call $syscall$6 (i32.const 1) (i32.const 2))) (drop (call $syscall$54 (i32.const 3) (i32.const 4))) @@ -90,5 +91,12 @@ (func $sub-zero (param $x i32) (result i32) (i32.sub (local.get $x) (i32.const -5)) ) + (func $select (param $x i32) (result i32) + (select + (local.get $x) + (i32.load (i32.const 16)) ;; we can ignore this implicit trap, no side effects + (local.get $x) + ) + ) ) diff --git a/test/wasm2js/float-ops.2asm.js.opt b/test/wasm2js/float-ops.2asm.js.opt index 4ef79e58a..130fe6bce 100644 --- a/test/wasm2js/float-ops.2asm.js.opt +++ b/test/wasm2js/float-ops.2asm.js.opt @@ -247,34 +247,12 @@ function asmFunc(global, env, buffer) { function $47($0) { $0 = Math_fround($0); - var $1_1 = 0, $2_1 = 0; - $2_1 = ~~$0 >>> 0; - if (Math_fround(Math_abs($0)) >= Math_fround(1.0)) { - if ($0 > Math_fround(0.0)) { - $1_1 = ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 / Math_fround(4294967296.0)))), Math_fround(4294967296.0))) >>> 0 - } else { - $1_1 = ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) / Math_fround(4294967296.0)))) >>> 0 - } - } else { - $1_1 = 0 - } - return !($2_1 | $1_1) | 0; + return !(~~$0 >>> 0 | (Math_fround(Math_abs($0)) >= Math_fround(1.0) ? ($0 > Math_fround(0.0) ? ~~Math_fround(Math_min(Math_fround(Math_floor(Math_fround($0 / Math_fround(4294967296.0)))), Math_fround(4294967296.0))) >>> 0 : ~~Math_fround(Math_ceil(Math_fround(Math_fround($0 - Math_fround(~~$0 >>> 0 >>> 0)) / Math_fround(4294967296.0)))) >>> 0) : 0)) | 0; } function $48($0) { $0 = +$0; - var $1_1 = 0, $2_1 = 0; - $2_1 = ~~$0 >>> 0; - if (Math_abs($0) >= 1.0) { - if ($0 > 0.0) { - $1_1 = ~~Math_min(Math_floor($0 / 4294967296.0), 4294967295.0) >>> 0 - } else { - $1_1 = ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) / 4294967296.0) >>> 0 - } - } else { - $1_1 = 0 - } - return !($2_1 | $1_1) | 0; + return !(~~$0 >>> 0 | (Math_abs($0) >= 1.0 ? ($0 > 0.0 ? ~~Math_min(Math_floor($0 / 4294967296.0), 4294967295.0) >>> 0 : ~~Math_ceil(($0 - +(~~$0 >>> 0 >>> 0)) / 4294967296.0) >>> 0) : 0)) | 0; } function legalstub$43($0, $1_1) { |