summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2019-05-02 14:17:49 -0700
committerGitHub <noreply@github.com>2019-05-02 14:17:49 -0700
commit29e7e4483dc04ca8e882f12871c7eb395c82de00 (patch)
tree40b968dfef03b6cb4b877850bce1c2507e2bc8df
parentb394fcc887dbb2e02b5ff5b307004e4dc7ec2baf (diff)
downloadbinaryen-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.cpp2
-rw-r--r--src/wasm2js.h10
-rw-r--r--test/wasm2js.asserts.js2
-rw-r--r--test/wasm2js.traps.js2
-rw-r--r--test/wasm2js/conversions-modified.2asm.js.opt30
-rw-r--r--test/wasm2js/emscripten.2asm.js9
-rw-r--r--test/wasm2js/emscripten.2asm.js.opt12
-rw-r--r--test/wasm2js/emscripten.wast8
-rw-r--r--test/wasm2js/float-ops.2asm.js.opt26
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) {