summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/Vacuum.cpp15
-rw-r--r--test/lit/passes/vacuum-gc.wast103
-rw-r--r--test/passes/vacuum_all-features.txt6
-rw-r--r--test/wasm2js/left-to-right.2asm.js147
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;
}