summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/asm2wasm.h7
-rw-r--r--src/passes/MergeBlocks.cpp21
-rw-r--r--test/passes/remove-unused-names_merge-blocks.txt174
-rw-r--r--test/passes/remove-unused-names_merge-blocks.wast44
-rw-r--r--test/unit.asm.js7
-rw-r--r--test/unit.fromasm19
-rw-r--r--test/unit.fromasm.clamp19
-rw-r--r--test/unit.fromasm.clamp.no-opts19
-rw-r--r--test/unit.fromasm.imprecise19
-rw-r--r--test/unit.fromasm.imprecise.no-opts19
-rw-r--r--test/unit.fromasm.no-opts19
11 files changed, 307 insertions, 60 deletions
diff --git a/src/asm2wasm.h b/src/asm2wasm.h
index 2245bd2b5..e2b1802b5 100644
--- a/src/asm2wasm.h
+++ b/src/asm2wasm.h
@@ -1397,7 +1397,12 @@ void Asm2WasmBuilder::processAsm(Ref ast) {
void visitCallIndirect(CallIndirect* curr) {
// we already call into target = something + offset, where offset is a callImport with the name of the table. replace that with the table offset
// note that for an ftCall or mftCall, we have no asm.js mask, so have nothing to do here
- auto* add = curr->target->dynCast<Binary>();
+ auto* target = curr->target;
+ // might be a block with a fallthrough
+ if (auto* block = target->dynCast<Block>()) {
+ target = block->list.back();
+ }
+ auto* add = target->dynCast<Binary>();
if (!add) return;
if (add->right->is<CallImport>()) {
auto* offset = add->right->cast<CallImport>();
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index bce5798a5..bc5fea6fb 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -288,11 +288,14 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
}
void visitSelect(Select* curr) {
+ // TODO: for now, just stop when we see any side effect. instead, we could
+ // check effects carefully for reordering
Block* outer = nullptr;
- outer = optimize(curr, curr->ifTrue, outer);
if (EffectAnalyzer(getPassOptions(), curr->ifTrue).hasSideEffects()) return;
- outer = optimize(curr, curr->ifFalse, outer);
+ outer = optimize(curr, curr->ifTrue, outer);
if (EffectAnalyzer(getPassOptions(), curr->ifFalse).hasSideEffects()) return;
+ outer = optimize(curr, curr->ifFalse, outer);
+ if (EffectAnalyzer(getPassOptions(), curr->condition).hasSideEffects()) return;
optimize(curr, curr->condition, outer);
}
@@ -308,11 +311,13 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
}
template<typename T>
- void handleCall(T* curr, Block* outer = nullptr) {
+ void handleCall(T* curr) {
+ Block* outer = nullptr;
for (Index i = 0; i < curr->operands.size(); i++) {
- outer = optimize(curr, curr->operands[i], outer);
if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) return;
+ outer = optimize(curr, curr->operands[i], outer);
}
+ return;
}
void visitCall(Call* curr) {
@@ -324,9 +329,13 @@ struct MergeBlocks : public WalkerPass<PostWalker<MergeBlocks>> {
}
void visitCallIndirect(CallIndirect* curr) {
- auto* outer = optimize(curr, curr->target);
+ Block* outer = nullptr;
+ for (Index i = 0; i < curr->operands.size(); i++) {
+ if (EffectAnalyzer(getPassOptions(), curr->operands[i]).hasSideEffects()) return;
+ outer = optimize(curr, curr->operands[i], outer);
+ }
if (EffectAnalyzer(getPassOptions(), curr->target).hasSideEffects()) return;
- handleCall(curr, outer);
+ optimize(curr, curr->target, outer);
}
};
diff --git a/test/passes/remove-unused-names_merge-blocks.txt b/test/passes/remove-unused-names_merge-blocks.txt
index d9186a46e..bc42f2766 100644
--- a/test/passes/remove-unused-names_merge-blocks.txt
+++ b/test/passes/remove-unused-names_merge-blocks.txt
@@ -412,26 +412,34 @@
)
)
)
- (unreachable)
- (drop
- (i32.const 30)
- )
- (drop
- (i32.const 50)
- )
(drop
(select
- (i32.const 20)
- (i32.const 40)
- (i32.const 60)
+ (block (result i32)
+ (unreachable)
+ (i32.const 20)
+ )
+ (block (result i32)
+ (drop
+ (i32.const 30)
+ )
+ (i32.const 40)
+ )
+ (block (result i32)
+ (drop
+ (i32.const 50)
+ )
+ (i32.const 60)
+ )
)
)
(drop
- (i32.const 10)
- )
- (drop
(select
- (unreachable)
+ (block (result i32)
+ (drop
+ (i32.const 10)
+ )
+ (unreachable)
+ )
(block (result i32)
(drop
(i32.const 30)
@@ -449,27 +457,33 @@
(drop
(i32.const 10)
)
- (unreachable)
- (drop
- (i32.const 50)
- )
(drop
(select
(i32.const 20)
- (i32.const 40)
- (i32.const 60)
+ (block
+ (unreachable)
+ (i32.const 40)
+ )
+ (block (result i32)
+ (drop
+ (i32.const 50)
+ )
+ (i32.const 60)
+ )
)
)
(drop
(i32.const 10)
)
(drop
- (i32.const 30)
- )
- (drop
(select
(i32.const 20)
- (unreachable)
+ (block
+ (drop
+ (i32.const 30)
+ )
+ (unreachable)
+ )
(block (result i32)
(drop
(i32.const 50)
@@ -484,12 +498,14 @@
(drop
(i32.const 30)
)
- (unreachable)
(drop
(select
(i32.const 20)
(i32.const 40)
- (i32.const 60)
+ (block
+ (unreachable)
+ (i32.const 60)
+ )
)
)
(drop
@@ -499,13 +515,15 @@
(i32.const 30)
)
(drop
- (i32.const 50)
- )
- (drop
(select
(i32.const 20)
(i32.const 40)
- (unreachable)
+ (block
+ (drop
+ (i32.const 50)
+ )
+ (unreachable)
+ )
)
)
)
@@ -590,19 +608,25 @@
(i32.const 20)
(i32.const 40)
)
- (unreachable)
- (drop
- (i32.const 20)
- )
(call $call-ii
- (i32.const 10)
- (i32.const 30)
- )
- (drop
- (i32.const 10)
+ (block (result i32)
+ (unreachable)
+ (i32.const 10)
+ )
+ (block (result i32)
+ (drop
+ (i32.const 20)
+ )
+ (i32.const 30)
+ )
)
(call $call-ii
- (unreachable)
+ (block (result i32)
+ (drop
+ (i32.const 10)
+ )
+ (unreachable)
+ )
(block (result i32)
(drop
(i32.const 20)
@@ -613,20 +637,24 @@
(drop
(i32.const 10)
)
- (unreachable)
(call $call-ii
(i32.const 20)
- (i32.const 30)
+ (block
+ (unreachable)
+ (i32.const 30)
+ )
)
(drop
(i32.const 10)
)
- (drop
- (i32.const 30)
- )
(call $call-ii
(i32.const 20)
- (unreachable)
+ (block
+ (drop
+ (i32.const 30)
+ )
+ (unreachable)
+ )
)
(drop
(i32.const 10)
@@ -654,22 +682,19 @@
(i32.const 50)
)
(drop
- (i32.const 50)
- )
- (drop
(i32.const 10)
)
(drop
(i32.const 30)
)
+ (drop
+ (i32.const 50)
+ )
(call_indirect $ii
(i32.const 20)
(i32.const 40)
(i32.const 60)
)
- (drop
- (i32.const 50)
- )
(call_indirect $ii
(unreachable)
(block (result i32)
@@ -678,7 +703,50 @@
)
(i32.const 40)
)
- (i32.const 60)
+ (block (result i32)
+ (drop
+ (i32.const 50)
+ )
+ (i32.const 60)
+ )
+ )
+ (drop
+ (i32.const 31)
+ )
+ (call_indirect $ii
+ (i32.const 41)
+ (unreachable)
+ (block (result i32)
+ (drop
+ (i32.const 51)
+ )
+ (i32.const 61)
+ )
+ )
+ (drop
+ (i32.const 32)
+ )
+ (drop
+ (i32.const 52)
+ )
+ (call_indirect $ii
+ (i32.const 42)
+ (i32.const 62)
+ (unreachable)
+ )
+ )
+ (func $mix-select (type $i) (param $x i32)
+ (drop
+ (select
+ (get_local $x)
+ (get_local $x)
+ (block (result i32)
+ (set_local $x
+ (i32.const 1)
+ )
+ (i32.const 2)
+ )
+ )
)
)
(func $block-type-change (type $3)
diff --git a/test/passes/remove-unused-names_merge-blocks.wast b/test/passes/remove-unused-names_merge-blocks.wast
index f301bbc2e..346dc78f8 100644
--- a/test/passes/remove-unused-names_merge-blocks.wast
+++ b/test/passes/remove-unused-names_merge-blocks.wast
@@ -854,6 +854,50 @@
(i32.const 60)
)
)
+ (call_indirect $ii
+ (block $block21 (result i32)
+ (drop
+ (i32.const 31)
+ )
+ (i32.const 41)
+ )
+ (unreachable)
+ (block $block22 (result i32)
+ (drop
+ (i32.const 51)
+ )
+ (i32.const 61)
+ )
+ )
+ (call_indirect $ii
+ (block $block21 (result i32)
+ (drop
+ (i32.const 32)
+ )
+ (i32.const 42)
+ )
+ (block $block22 (result i32)
+ (drop
+ (i32.const 52)
+ )
+ (i32.const 62)
+ )
+ (unreachable)
+ )
+ )
+ (func $mix-select (param $x i32)
+ (drop
+ (select
+ (get_local $x)
+ (get_local $x)
+ (block (result i32)
+ (set_local $x ;; cannot be moved before the gets
+ (i32.const 1)
+ )
+ (i32.const 2)
+ )
+ )
+ )
)
(func $block-type-change (type $3)
(local $0 f64)
diff --git a/test/unit.asm.js b/test/unit.asm.js
index 0bd0ab21b..22e180078 100644
--- a/test/unit.asm.js
+++ b/test/unit.asm.js
@@ -709,12 +709,19 @@ function asm(global, env, buffer) {
i1 = (FUNCTION_TABLE_vi[1 & 7](0), 1);
}
+ function emterpretify_assertions_safeHeap() {
+ var i1 = 0;
+ // assignment into the function table param, optimizer can do things there
+ FUNCTION_TABLE_vi[(Int = 1) & 7](i1 | 0);
+ }
+
function keepAlive() {
sqrts(3.14159);
f2u(100.0);
f2s(100.0);
autoDrop(52) | 0;
indirectInSequence();
+ emterpretify_assertions_safeHeap();
}
function v() {
diff --git a/test/unit.fromasm b/test/unit.fromasm
index c869e2398..68f5920ee 100644
--- a/test/unit.fromasm
+++ b/test/unit.fromasm
@@ -1169,6 +1169,24 @@
(i32.const 17)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $0 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $0)
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (i32.add
+ (i32.and
+ (get_global $Int)
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1191,6 +1209,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $vi (param $0 i32)
(nop)
diff --git a/test/unit.fromasm.clamp b/test/unit.fromasm.clamp
index 370e66c4d..1442ea947 100644
--- a/test/unit.fromasm.clamp
+++ b/test/unit.fromasm.clamp
@@ -1193,6 +1193,24 @@
(i32.const 17)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $0 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $0)
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (i32.add
+ (i32.and
+ (get_global $Int)
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1215,6 +1233,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $vi (param $0 i32)
(nop)
diff --git a/test/unit.fromasm.clamp.no-opts b/test/unit.fromasm.clamp.no-opts
index 8ff26568e..37456128f 100644
--- a/test/unit.fromasm.clamp.no-opts
+++ b/test/unit.fromasm.clamp.no-opts
@@ -1977,6 +1977,24 @@
)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $i1 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $i1)
+ (i32.add
+ (i32.and
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (get_global $Int)
+ )
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1999,6 +2017,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $v
(nop)
diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise
index 45912cffb..ea664d5f0 100644
--- a/test/unit.fromasm.imprecise
+++ b/test/unit.fromasm.imprecise
@@ -1142,6 +1142,24 @@
(i32.const 17)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $0 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $0)
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (i32.add
+ (i32.and
+ (get_global $Int)
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1164,6 +1182,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $vi (param $0 i32)
(nop)
diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts
index 3747f2c90..227cf5e79 100644
--- a/test/unit.fromasm.imprecise.no-opts
+++ b/test/unit.fromasm.imprecise.no-opts
@@ -1937,6 +1937,24 @@
)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $i1 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $i1)
+ (i32.add
+ (i32.and
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (get_global $Int)
+ )
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1959,6 +1977,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $v
(nop)
diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts
index dba91cfcd..878011cef 100644
--- a/test/unit.fromasm.no-opts
+++ b/test/unit.fromasm.no-opts
@@ -1953,6 +1953,24 @@
)
)
)
+ (func $emterpretify_assertions_safeHeap
+ (local $i1 i32)
+ (call_indirect $FUNCSIG$vi
+ (get_local $i1)
+ (i32.add
+ (i32.and
+ (block (result i32)
+ (set_global $Int
+ (i32.const 1)
+ )
+ (get_global $Int)
+ )
+ (i32.const 7)
+ )
+ (i32.const 16)
+ )
+ )
+ )
(func $keepAlive
(drop
(call $sqrts
@@ -1975,6 +1993,7 @@
)
)
(call $indirectInSequence)
+ (call $emterpretify_assertions_safeHeap)
)
(func $v
(nop)