summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/pass.h6
-rw-r--r--src/passes/OptimizeInstructions.cpp5
-rw-r--r--src/wasm2js.h3
-rw-r--r--test/wasm2js/target_js.2asm.js27
-rw-r--r--test/wasm2js/target_js.2asm.js.opt27
-rw-r--r--test/wasm2js/target_js.wast13
6 files changed, 80 insertions, 1 deletions
diff --git a/src/pass.h b/src/pass.h
index 4ab0a8c34..36d49f7b7 100644
--- a/src/pass.h
+++ b/src/pass.h
@@ -217,6 +217,12 @@ struct PassOptions {
bool closedWorld = false;
// Whether to try to preserve debug info through, which are special calls.
bool debugInfo = false;
+ // Whether we are targeting JS. In that case we want to avoid emitting things
+ // in the optimizer that do not translate well to JS, or that could cause us
+ // to need extra lowering work or even a loop (where we optimize to something
+ // that needs lowering, then we lower it, then we can optimize it again to the
+ // original form).
+ bool targetJS = false;
// Arbitrary string arguments from the commandline, which we forward to
// passes.
std::unordered_map<std::string, std::string> arguments;
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index e61373711..ad51d7cd4 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -3669,7 +3669,10 @@ private:
{
// ~(1 << x) aka (1 << x) ^ -1 ==> rotl(-2, x)
Expression* x;
- if (matches(curr, binary(Xor, binary(Shl, ival(1), any(&x)), ival(-1)))) {
+ // Note that we avoid this in JS mode, as emitting a rotation would
+ // require lowering that rotation for JS in another cycle of work.
+ if (matches(curr, binary(Xor, binary(Shl, ival(1), any(&x)), ival(-1))) &&
+ !getPassOptions().targetJS) {
curr->op = Abstract::getBinary(type, RotL);
right->value = Literal::makeFromInt32(-2, type);
curr->left = right;
diff --git a/src/wasm2js.h b/src/wasm2js.h
index 982184510..db394c36c 100644
--- a/src/wasm2js.h
+++ b/src/wasm2js.h
@@ -173,8 +173,11 @@ public:
// 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.)
+ // It is also important to prevent the optimizer from adding new things that
+ // require additional lowering, as we could hit a cycle.
if (options.optimizeLevel > 0) {
options.ignoreImplicitTraps = true;
+ options.targetJS = true;
}
}
diff --git a/test/wasm2js/target_js.2asm.js b/test/wasm2js/target_js.2asm.js
new file mode 100644
index 000000000..f9f4b4a67
--- /dev/null
+++ b/test/wasm2js/target_js.2asm.js
@@ -0,0 +1,27 @@
+
+function asmFunc(imports) {
+ var Math_imul = Math.imul;
+ var Math_fround = Math.fround;
+ var Math_abs = Math.abs;
+ var Math_clz32 = Math.clz32;
+ var Math_min = Math.min;
+ var Math_max = Math.max;
+ var Math_floor = Math.floor;
+ var Math_ceil = Math.ceil;
+ var Math_trunc = Math.trunc;
+ var Math_sqrt = Math.sqrt;
+ var nan = NaN;
+ var infinity = Infinity;
+ function func(x) {
+ x = x | 0;
+ return (1 << x | 0) ^ -1 | 0 | 0;
+ }
+
+ return {
+ "func": func
+ };
+}
+
+var retasmFunc = asmFunc({
+});
+export var func = retasmFunc.func;
diff --git a/test/wasm2js/target_js.2asm.js.opt b/test/wasm2js/target_js.2asm.js.opt
new file mode 100644
index 000000000..12e1a475b
--- /dev/null
+++ b/test/wasm2js/target_js.2asm.js.opt
@@ -0,0 +1,27 @@
+
+function asmFunc(imports) {
+ var Math_imul = Math.imul;
+ var Math_fround = Math.fround;
+ var Math_abs = Math.abs;
+ var Math_clz32 = Math.clz32;
+ var Math_min = Math.min;
+ var Math_max = Math.max;
+ var Math_floor = Math.floor;
+ var Math_ceil = Math.ceil;
+ var Math_trunc = Math.trunc;
+ var Math_sqrt = Math.sqrt;
+ var nan = NaN;
+ var infinity = Infinity;
+ function func($0) {
+ $0 = $0 | 0;
+ return 1 << $0 ^ -1;
+ }
+
+ return {
+ "func": func
+ };
+}
+
+var retasmFunc = asmFunc({
+});
+export var func = retasmFunc.func;
diff --git a/test/wasm2js/target_js.wast b/test/wasm2js/target_js.wast
new file mode 100644
index 000000000..27373f98e
--- /dev/null
+++ b/test/wasm2js/target_js.wast
@@ -0,0 +1,13 @@
+(module
+ (func $func (export "func") (param $x i32) (result i32)
+ ;; Do not turn xor into something that does not express well in JS
+ ;; when optimizing.
+ (i32.xor
+ (i32.shl
+ (i32.const 1)
+ (local.get $x)
+ )
+ (i32.const -1)
+ )
+ )
+)