summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/passes/MergeBlocks.cpp50
-rw-r--r--test/example/c-api-kitchen-sink.c4
-rw-r--r--test/example/c-api-relooper-unreachable-if.cpp4
-rw-r--r--test/example/c-api-unused-mem.cpp4
-rw-r--r--test/lit/passes/merge-blocks.wast31
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
+ )
+ )
+ )
+)