summaryrefslogtreecommitdiff
path: root/src/passes/RemoveUnusedBrs.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/RemoveUnusedBrs.cpp')
-rw-r--r--src/passes/RemoveUnusedBrs.cpp52
1 files changed, 52 insertions, 0 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 9f753024d..c8c2277dc 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -276,6 +276,8 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
}
// TODO: if-else can be turned into a br_if as well, if one of the sides is a dead end
+ // we handle the case of a returned value to a set_local later down, see
+ // visitSetLocal.
}
// override scan to add a pre and a post check task to all nodes
@@ -661,6 +663,56 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
}
}
+ void visitSetLocal(SetLocal* curr) {
+ // Undo an if return value into a local, if one arm is a br, as we
+ // prefer a br_if:
+ // (set_local $x
+ // (if (result i32)
+ // (..condition..)
+ // (br $somewhere)
+ // (..result)
+ // )
+ // )
+ // =>
+ // (br_if $somewhere
+ // (..condition..)
+ // )
+ // (set_local $x
+ // (..result)
+ // )
+ // TODO: handle a condition in the br? need to watch for side effects
+ auto* iff = curr->value->dynCast<If>();
+ if (!iff) return;
+ if (!isConcreteType(iff->type)) return;
+ auto tryToOptimize = [&](Expression* one, Expression* two, bool flipCondition) {
+ if (one->type == unreachable && two->type != unreachable) {
+ if (auto* br = one->dynCast<Break>()) {
+ if (ExpressionAnalyzer::isSimple(br)) {
+ // Wonderful, do it!
+ Builder builder(*getModule());
+ br->condition = iff->condition;
+ if (flipCondition) {
+ br->condition = builder.makeUnary(EqZInt32, br->condition);
+ }
+ br->finalize();
+ curr->value = two;
+ replaceCurrent(
+ builder.makeSequence(
+ br,
+ curr
+ )
+ );
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+ if (!tryToOptimize(iff->ifTrue, iff->ifFalse, false)) {
+ tryToOptimize(iff->ifFalse, iff->ifTrue, true);
+ }
+ }
+
// (br_if)+ => br_table
// we look for the specific pattern of
// (br_if ..target1..