diff options
-rw-r--r-- | src/asm2wasm.h | 7 | ||||
-rw-r--r-- | src/passes/MergeBlocks.cpp | 21 | ||||
-rw-r--r-- | test/passes/remove-unused-names_merge-blocks.txt | 174 | ||||
-rw-r--r-- | test/passes/remove-unused-names_merge-blocks.wast | 44 | ||||
-rw-r--r-- | test/unit.asm.js | 7 | ||||
-rw-r--r-- | test/unit.fromasm | 19 | ||||
-rw-r--r-- | test/unit.fromasm.clamp | 19 | ||||
-rw-r--r-- | test/unit.fromasm.clamp.no-opts | 19 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise | 19 | ||||
-rw-r--r-- | test/unit.fromasm.imprecise.no-opts | 19 | ||||
-rw-r--r-- | test/unit.fromasm.no-opts | 19 |
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) |