diff options
-rw-r--r-- | src/passes/Vacuum.cpp | 15 | ||||
-rw-r--r-- | test/lit/passes/vacuum-gc.wast | 103 | ||||
-rw-r--r-- | test/passes/vacuum_all-features.txt | 6 | ||||
-rw-r--r-- | test/wasm2js/left-to-right.2asm.js | 147 |
4 files changed, 216 insertions, 55 deletions
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp index 84ae5199c..7c394900d 100644 --- a/src/passes/Vacuum.cpp +++ b/src/passes/Vacuum.cpp @@ -19,6 +19,7 @@ // #include <ir/block-utils.h> +#include <ir/drop.h> #include <ir/effects.h> #include <ir/iteration.h> #include <ir/literal-utils.h> @@ -137,9 +138,17 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> { curr = childrenWithEffects[0]; continue; } - // TODO: with multiple children with side effects, we can perhaps figure - // out something clever, like a block with drops, or an i32.add for just - // two, etc. + // The result is not used, but multiple children have side effects, so we + // need to keep them around. We must also return something of the proper + // type - if we can do that, replace everything with the children + a + // dummy value of the proper type. + if (curr->type.isDefaultable()) { + auto* dummy = Builder(*getModule()) + .makeConstantExpression(Literal::makeZeros(curr->type)); + return getDroppedChildrenAndAppend( + curr, *getModule(), getPassOptions(), dummy); + } + // Otherwise, give up. return curr; } } diff --git a/test/lit/passes/vacuum-gc.wast b/test/lit/passes/vacuum-gc.wast index 6e70425a2..bbb0c4c64 100644 --- a/test/lit/passes/vacuum-gc.wast +++ b/test/lit/passes/vacuum-gc.wast @@ -3,6 +3,12 @@ (module ;; CHECK: (type ${} (struct )) + + ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (param i32 i32 funcref) (result anyref))) + (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects (param i32 i32 funcref) (result (ref null any)))) + ;; CHECK: (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects.non.null (param i32 i32 funcref) (result (ref any)))) + (import "binaryen-intrinsics" "call.without.effects" (func $call.without.effects.non.null (param i32 i32 funcref) (result (ref any)))) + (type ${} (struct)) ;; CHECK: (func $drop-ref-as (type $anyref_=>_none) (param $x anyref) @@ -90,4 +96,101 @@ ) ) ) + + ;; CHECK: (func $dropped-calls (type $none_=>_none) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-ref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-ref) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (block + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (call $call.without.effects.non.null + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: (call $helper-i32) + ;; CHECK-NEXT: (ref.func $helper-two-refs-non-null) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $dropped-calls + ;; The calls' outputs are used in a computation that itself has no effects, + ;; and is dropped, so we don't need it. But we can't remove the calls + ;; themselves, which should be all that remains, with drops of them (there + ;; will also be blocks, which merge-blocks would remove). + (drop + (i32.add + (call $helper-i32) + (call $helper-i32) + ) + ) + (drop + (ref.eq + (call $helper-ref) + (call $helper-ref) + ) + ) + ;; The call.without.effects can be removed, but not the two calls nested in + ;; it. + (drop + (call $call.without.effects + (call $helper-i32) + (call $helper-i32) + (ref.func $helper-two-refs) + ) + ) + ;; The non-null case however is tricky, and we do not handle it atm. TODO + (drop + (call $call.without.effects.non.null + (call $helper-i32) + (call $helper-i32) + (ref.func $helper-two-refs-non-null) + ) + ) + ) + + ;; CHECK: (func $helper-i32 (type $none_=>_i32) (result i32) + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + (func $helper-i32 (result i32) + (i32.const 1) + ) + + ;; CHECK: (func $helper-ref (type $none_=>_eqref) (result eqref) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $helper-ref (result eqref) + (unreachable) + ) + + ;; CHECK: (func $helper-two-refs (type $i32_i32_=>_anyref) (param $0 i32) (param $1 i32) (result anyref) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $helper-two-refs (param i32) (param i32) (result (ref null any)) + (unreachable) + ) + + ;; CHECK: (func $helper-two-refs-non-null (type $i32_i32_=>_ref|any|) (param $0 i32) (param $1 i32) (result (ref any)) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + (func $helper-two-refs-non-null (param i32) (param i32) (result (ref any)) + (unreachable) + ) ) diff --git a/test/passes/vacuum_all-features.txt b/test/passes/vacuum_all-features.txt index 739a86158..b4e4aea72 100644 --- a/test/passes/vacuum_all-features.txt +++ b/test/passes/vacuum_all-features.txt @@ -111,9 +111,11 @@ (drop (call $int) ) - (drop - (i32.add + (block + (drop (call $int) + ) + (drop (call $int) ) ) diff --git a/test/wasm2js/left-to-right.2asm.js b/test/wasm2js/left-to-right.2asm.js index a1c10e939..5bb552f34 100644 --- a/test/wasm2js/left-to-right.2asm.js +++ b/test/wasm2js/left-to-right.2asm.js @@ -242,19 +242,22 @@ function asmFunc(imports) { function $35() { reset(); - (i32_left() | 0) + (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $36() { reset(); - (i32_left() | 0) - (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $37() { reset(); - Math_imul(i32_left() | 0, i32_right() | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } @@ -284,97 +287,113 @@ function asmFunc(imports) { function $42() { reset(); - (i32_left() | 0) & (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $43() { reset(); - i32_left() | 0 | (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $44() { reset(); - (i32_left() | 0) ^ (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $45() { reset(); - (i32_left() | 0) << (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $46() { reset(); - (i32_left() | 0) >>> (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $47() { reset(); - (i32_left() | 0) >> (i32_right() | 0) | 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $48() { reset(); - (i32_left() | 0 | 0) == (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $49() { reset(); - (i32_left() | 0 | 0) != (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $50() { reset(); - (i32_left() | 0 | 0) < (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $51() { reset(); - (i32_left() | 0 | 0) <= (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $52() { reset(); - (i32_left() | 0) >>> 0 < (i32_right() | 0) >>> 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $53() { reset(); - (i32_left() | 0) >>> 0 <= (i32_right() | 0) >>> 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $54() { reset(); - (i32_left() | 0 | 0) > (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $55() { reset(); - (i32_left() | 0 | 0) >= (i32_right() | 0 | 0); + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $56() { reset(); - (i32_left() | 0) >>> 0 > (i32_right() | 0) >>> 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } function $57() { reset(); - (i32_left() | 0) >>> 0 >= (i32_right() | 0) >>> 0; + i32_left() | 0; + i32_right() | 0; return get() | 0 | 0; } @@ -413,9 +432,10 @@ function asmFunc(imports) { } function $63() { - var wasm2js_i32$0 = 0, wasm2js_i32$1 = 0, wasm2js_i32$2 = 0; reset(); - wasm2js_i32$0 = i32_left() | 0, wasm2js_i32$1 = i32_right() | 0, wasm2js_i32$2 = i32_bool() | 0, wasm2js_i32$2 ? wasm2js_i32$0 : wasm2js_i32$1; + i32_left() | 0; + i32_right() | 0; + i32_bool() | 0; return get() | 0 | 0; } @@ -995,79 +1015,92 @@ function asmFunc(imports) { function $94() { reset(); - Math_fround(Math_fround(f32_left()) + Math_fround(f32_right())); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $95() { reset(); - Math_fround(Math_fround(f32_left()) - Math_fround(f32_right())); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $96() { reset(); - Math_fround(Math_fround(f32_left()) * Math_fround(f32_right())); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $97() { reset(); - Math_fround(Math_fround(f32_left()) / Math_fround(f32_right())); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $98() { reset(); - (wasm2js_scratch_store_f32(Math_fround(f32_left())), wasm2js_scratch_load_i32(2)) & 2147483647 | 0 | ((wasm2js_scratch_store_f32(Math_fround(f32_right())), wasm2js_scratch_load_i32(2)) & -2147483648 | 0) | 0; + (wasm2js_scratch_store_f32(Math_fround(f32_left())), wasm2js_scratch_load_i32(2)) & 2147483647 | 0; + (wasm2js_scratch_store_f32(Math_fround(f32_right())), wasm2js_scratch_load_i32(2)) & -2147483648 | 0; return get() | 0 | 0; } function $99() { reset(); - Math_fround(f32_left()) == Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $100() { reset(); - Math_fround(f32_left()) != Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $101() { reset(); - Math_fround(f32_left()) < Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $102() { reset(); - Math_fround(f32_left()) <= Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $103() { reset(); - Math_fround(f32_left()) > Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $104() { reset(); - Math_fround(f32_left()) >= Math_fround(f32_right()); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $105() { reset(); - Math_fround(Math_min(Math_fround(f32_left()), Math_fround(f32_right()))); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } function $106() { reset(); - Math_fround(Math_max(Math_fround(f32_left()), Math_fround(f32_right()))); + Math_fround(f32_left()); + Math_fround(f32_right()); return get() | 0 | 0; } @@ -1092,33 +1125,38 @@ function asmFunc(imports) { } function $110() { - var wasm2js_f32$0 = Math_fround(0), wasm2js_f32$1 = Math_fround(0), wasm2js_i32$0 = 0; reset(); - wasm2js_f32$0 = Math_fround(f32_left()), wasm2js_f32$1 = Math_fround(f32_right()), wasm2js_i32$0 = f32_bool() | 0, wasm2js_i32$0 ? wasm2js_f32$0 : wasm2js_f32$1; + Math_fround(f32_left()); + Math_fround(f32_right()); + f32_bool() | 0; return get() | 0 | 0; } function $111() { reset(); - +f64_left() + +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $112() { reset(); - +f64_left() - +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $113() { reset(); - +f64_left() * +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $114() { reset(); - +f64_left() / +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } @@ -1154,49 +1192,57 @@ function asmFunc(imports) { function $116() { reset(); - +f64_left() == +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $117() { reset(); - +f64_left() != +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $118() { reset(); - +f64_left() < +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $119() { reset(); - +f64_left() <= +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $120() { reset(); - +f64_left() > +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $121() { reset(); - +f64_left() >= +f64_right(); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $122() { reset(); - Math_min(+f64_left(), +f64_right()); + +f64_left(); + +f64_right(); return get() | 0 | 0; } function $123() { reset(); - Math_max(+f64_left(), +f64_right()); + +f64_left(); + +f64_right(); return get() | 0 | 0; } @@ -1221,9 +1267,10 @@ function asmFunc(imports) { } function $127() { - var wasm2js_f64$0 = 0.0, wasm2js_f64$1 = 0.0, wasm2js_i32$0 = 0; reset(); - wasm2js_f64$0 = +f64_left(), wasm2js_f64$1 = +f64_right(), wasm2js_i32$0 = f64_bool() | 0, wasm2js_i32$0 ? wasm2js_f64$0 : wasm2js_f64$1; + +f64_left(); + +f64_right(); + f64_bool() | 0; return get() | 0 | 0; } |