summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-07-19 14:38:24 -0700
committerGitHub <noreply@github.com>2021-07-19 14:38:24 -0700
commitfb9de9d391a7272548dcc41cd8229076189d7398 (patch)
treea1d5c3610ca8c3ec9b82e3f451e857b6470f75ac /src
parentf98eb3463cdfb1ad6a97dc0c4ba6d6d99f77e706 (diff)
downloadbinaryen-fb9de9d391a7272548dcc41cd8229076189d7398.tar.gz
binaryen-fb9de9d391a7272548dcc41cd8229076189d7398.tar.bz2
binaryen-fb9de9d391a7272548dcc41cd8229076189d7398.zip
RemoveUnusedBrs: Do not create a select with a multivalue result (#4005)
The spec disallows that. Fixes #3990
Diffstat (limited to 'src')
-rw-r--r--src/passes/RemoveUnusedBrs.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/src/passes/RemoveUnusedBrs.cpp b/src/passes/RemoveUnusedBrs.cpp
index 5631c9d5f..157cfc1f3 100644
--- a/src/passes/RemoveUnusedBrs.cpp
+++ b/src/passes/RemoveUnusedBrs.cpp
@@ -97,6 +97,12 @@ static bool tooCostlyToRunUnconditionally(const PassOptions& passOptions,
return total >= TOO_MUCH;
}
+static bool canEmitSelectWithArms(Expression* ifTrue, Expression* ifFalse) {
+ // A select only allows a single value in its arms in the spec:
+ // https://webassembly.github.io/spec/core/valid/instructions.html#xref-syntax-instructions-syntax-instr-parametric-mathsf-select-t-ast
+ return ifTrue->type.isSingle() && ifFalse->type.isSingle();
+}
+
struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
bool isFunctionParallel() override { return true; }
@@ -1023,7 +1029,8 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
EffectAnalyzer(passOptions, features, curr)
.hasSideEffects();
list[0] = old;
- if (canReorder && !hasSideEffects) {
+ if (canReorder && !hasSideEffects &&
+ canEmitSelectWithArms(br->value, curr)) {
ExpressionManipulator::nop(list[0]);
replaceCurrent(
builder.makeSelect(br->condition, br->value, curr));
@@ -1044,8 +1051,11 @@ struct RemoveUnusedBrs : public WalkerPass<PostWalker<RemoveUnusedBrs>> {
// Convert an if into a select, if possible and beneficial to do so.
Select* selectify(If* iff) {
- if (!iff->ifFalse || !iff->ifTrue->type.isSingle() ||
- !iff->ifFalse->type.isSingle()) {
+ // Only an if-else can be turned into a select.
+ if (!iff->ifFalse) {
+ return nullptr;
+ }
+ if (!canEmitSelectWithArms(iff->ifTrue, iff->ifFalse)) {
return nullptr;
}
if (iff->condition->type == Type::unreachable) {