diff options
-rw-r--r-- | src/passes/MergeBlocks.cpp | 50 | ||||
-rw-r--r-- | test/example/c-api-kitchen-sink.c | 4 | ||||
-rw-r--r-- | test/example/c-api-relooper-unreachable-if.cpp | 4 | ||||
-rw-r--r-- | test/example/c-api-unused-mem.cpp | 4 | ||||
-rw-r--r-- | test/lit/passes/merge-blocks.wast | 31 |
5 files changed, 62 insertions, 31 deletions
diff --git a/src/passes/MergeBlocks.cpp b/src/passes/MergeBlocks.cpp index ef0ead133..7e8819309 100644 --- a/src/passes/MergeBlocks.cpp +++ b/src/passes/MergeBlocks.cpp @@ -84,7 +84,9 @@ namespace wasm { // Looks for reasons we can't remove the values from breaks to an origin // For example, if there is a switch targeting us, we can't do it - we can't // remove the value from other targets -struct ProblemFinder : public ControlFlowWalker<ProblemFinder> { +struct ProblemFinder + : public ControlFlowWalker<ProblemFinder, + UnifiedExpressionVisitor<ProblemFinder>> { Name origin; bool foundProblem = false; // count br_ifs, and dropped br_ifs. if they don't match, then a br_if flow @@ -95,38 +97,36 @@ struct ProblemFinder : public ControlFlowWalker<ProblemFinder> { ProblemFinder(PassOptions& passOptions) : passOptions(passOptions) {} - void visitBreak(Break* curr) { - if (curr->name == origin) { - if (curr->condition) { - brIfs++; - } - // if the value has side effects, we can't remove it - if (EffectAnalyzer(passOptions, getModule()->features, curr->value) - .hasSideEffects()) { - foundProblem = true; + void visitExpression(Expression* curr) { + if (auto* drop = curr->dynCast<Drop>()) { + if (auto* br = drop->value->dynCast<Break>()) { + if (br->name == origin && br->condition) { + droppedBrIfs++; + } } + return; } - } - void visitDrop(Drop* curr) { - if (auto* br = curr->value->dynCast<Break>()) { - if (br->name == origin && br->condition) { - droppedBrIfs++; + if (auto* br = curr->dynCast<Break>()) { + if (br->name == origin) { + if (br->condition) { + brIfs++; + } + // if the value has side effects, we can't remove it + if (EffectAnalyzer(passOptions, getModule()->features, br->value) + .hasSideEffects()) { + foundProblem = true; + } } - } - } - - void visitSwitch(Switch* curr) { - if (curr->default_ == origin) { - foundProblem = true; return; } - for (auto& target : curr->targets) { - if (target == origin) { + + // Any other branch type - switch, br_on, etc. - is not handled yet. + BranchUtils::operateOnScopeNameUses(curr, [&](Name& name) { + if (name == origin) { foundProblem = true; - return; } - } + }); } bool found() { diff --git a/test/example/c-api-kitchen-sink.c b/test/example/c-api-kitchen-sink.c index 32b6fe6d9..9e6366d36 100644 --- a/test/example/c-api-kitchen-sink.c +++ b/test/example/c-api-kitchen-sink.c @@ -870,7 +870,7 @@ void test_core() { // Memory. One per module const char* segments[] = { "hello, world", "I am passive" }; - bool segmentPassive[] = { false, true }; + bool segmentPassive[] = {false, true}; BinaryenExpressionRef segmentOffsets[] = { BinaryenConst(module, BinaryenLiteralInt32(10)), NULL }; BinaryenIndex segmentSizes[] = { 12, 12 }; BinaryenSetMemory(module, 1, 256, "mem", segments, segmentPassive, segmentOffsets, segmentSizes, 2, 1); @@ -1367,7 +1367,7 @@ void test_for_each() { const char* segments[] = { "hello, world", "segment data 2" }; const uint32_t expected_offsets[] = { 10, 125 }; - bool segmentPassive[] = { false, false }; + bool segmentPassive[] = {false, false}; BinaryenIndex segmentSizes[] = { 12, 14 }; BinaryenExpressionRef segmentOffsets[] = { diff --git a/test/example/c-api-relooper-unreachable-if.cpp b/test/example/c-api-relooper-unreachable-if.cpp index 5e93d9d16..babafac5a 100644 --- a/test/example/c-api-relooper-unreachable-if.cpp +++ b/test/example/c-api-relooper-unreachable-if.cpp @@ -16,7 +16,7 @@ int main() { BinaryenModuleAutoDrop(the_module); { const char* segments[] = { 0 }; - bool segmentPassive[] = { false }; + bool segmentPassive[] = {false}; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); @@ -437,7 +437,7 @@ int main() { { const char* segments[] = { 0 }; BinaryenExpressionRef segmentOffsets[] = { 0 }; - bool segmentPassive[] = { false }; + bool segmentPassive[] = {false}; BinaryenIndex segmentSizes[] = { 0 }; BinaryenSetMemory(the_module, 1, 1, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); } diff --git a/test/example/c-api-unused-mem.cpp b/test/example/c-api-unused-mem.cpp index c540d15c1..2121d8bde 100644 --- a/test/example/c-api-unused-mem.cpp +++ b/test/example/c-api-unused-mem.cpp @@ -17,7 +17,7 @@ int main() { BinaryenModuleAutoDrop(the_module); { const char* segments[] = { 0 }; - bool segmentPassive[] = { false }; + bool segmentPassive[] = {false}; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; BinaryenSetMemory(the_module, 256, 256, "memory", segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); @@ -60,7 +60,7 @@ int main() { BinaryenAddFunctionExport(the_module, "main", "main"); { const char* segments[] = { 0 }; - bool segmentPassive[] = { false }; + bool segmentPassive[] = {false}; BinaryenExpressionRef segmentOffsets[] = { 0 }; BinaryenIndex segmentSizes[] = { 0 }; BinaryenSetMemory(the_module, 1024, 1024, NULL, segments, segmentPassive, segmentOffsets, segmentSizes, 0, 0); diff --git a/test/lit/passes/merge-blocks.wast b/test/lit/passes/merge-blocks.wast new file mode 100644 index 000000000..0a1defab5 --- /dev/null +++ b/test/lit/passes/merge-blocks.wast @@ -0,0 +1,31 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s --merge-blocks -all -S -o - \ +;; RUN: | filecheck %s + +(module + (type $anyref_=>_none (func (param anyref))) + ;; CHECK: (func $br_on_to_drop + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (block $label$1 (result (ref null i31)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (br_on_i31 $label$1 + ;; CHECK-NEXT: (ref.null any) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.null i31) + (func $br_on_to_drop + (nop) ;; ensure a block at the function level + (drop + (block $label$1 (result (ref null i31)) ;; this block type must stay, we + ;; cannot remove it due to the br_on + (drop + (br_on_i31 $label$1 + (ref.null any) + ) + ) + (ref.null i31) ;; this must not end up dropped + ) + ) + ) +) |