summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-08-06 14:00:55 -0700
committerAlon Zakai <alonzakai@gmail.com>2017-08-06 14:00:55 -0700
commite17202e4d20bf79bd285425bac606a31bf3a8131 (patch)
treebdb3eccb020f791d34e544b7fbb86d404b646ce4
parent323e0b489a2b26d144da440d8043189ebbf49db2 (diff)
downloadbinaryen-e17202e4d20bf79bd285425bac606a31bf3a8131.tar.gz
binaryen-e17202e4d20bf79bd285425bac606a31bf3a8131.tar.bz2
binaryen-e17202e4d20bf79bd285425bac606a31bf3a8131.zip
properly handle merging of blocks with concrete unreachable elements in the middle
-rw-r--r--src/passes/MergeBlocks.cpp16
-rw-r--r--test/passes/remove-unused-names_merge-blocks.txt17
-rw-r--r--test/passes/remove-unused-names_merge-blocks.wast12
3 files changed, 39 insertions, 6 deletions
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp
index 1ef34117e..619d7b5a5 100644
--- a/src/passes/MergeBlocks.cpp
+++ b/src/passes/MergeBlocks.cpp
@@ -220,16 +220,20 @@ static void optimizeBlock(Block* curr, Module* module, PassOptions& passOptions)
}
for (auto item : child->list) {
merged.push_back(item);
- if (item->type == unreachable) {
- // we don't need anything else from the child,
- // and it is always valid to end on an unreachable,
- // so stop there (otherwise, we need to be careful)
- break;
- }
}
for (size_t j = i + 1; j < curr->list.size(); j++) {
merged.push_back(curr->list[j]);
}
+ // if we merged a concrete element in the middle, drop it
+ if (!merged.empty()) {
+ auto* last = merged.back();
+ for (auto*& item : merged) {
+ if (item != last && isConcreteWasmType(item->type)) {
+ Builder builder(*module);
+ item = builder.makeDrop(item);
+ }
+ }
+ }
curr->list.swap(merged);
more = true;
changed = true;
diff --git a/test/passes/remove-unused-names_merge-blocks.txt b/test/passes/remove-unused-names_merge-blocks.txt
index 81386b10a..19f03c662 100644
--- a/test/passes/remove-unused-names_merge-blocks.txt
+++ b/test/passes/remove-unused-names_merge-blocks.txt
@@ -854,6 +854,9 @@
)
(func $concrete_finale_in_unreachable (type $5) (result f64)
(unreachable)
+ (drop
+ (f64.const 6.322092475576799e-96)
+ )
(f64.const -1)
)
(func $dont-move-unreachable (type $3)
@@ -910,5 +913,19 @@
(return
(i32.const 21536)
)
+ (block $label$15
+ (br $label$15)
+ )
+ (i32.const 19299)
+ )
+ (func $remove-br-after-unreachable (type $3)
+ (block $label$9
+ (drop
+ (block
+ (return)
+ (br $label$9)
+ )
+ )
+ )
)
)
diff --git a/test/passes/remove-unused-names_merge-blocks.wast b/test/passes/remove-unused-names_merge-blocks.wast
index bf1dc1fda..6f6dd92b9 100644
--- a/test/passes/remove-unused-names_merge-blocks.wast
+++ b/test/passes/remove-unused-names_merge-blocks.wast
@@ -1081,5 +1081,17 @@
)
)
)
+ (func $remove-br-after-unreachable
+ (block $label$9
+ (drop
+ (block
+ (block
+ (return)
+ (br $label$9) ;; removing this leads to the block becoming unreachable
+ )
+ )
+ )
+ )
+ )
)