summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2021-03-10 16:06:19 -0800
committerGitHub <noreply@github.com>2021-03-11 00:06:19 +0000
commitd369cd6474364e5797e40af94676339af03723a9 (patch)
tree2441fb6aec7ae185a73804fe61298854ee3495d9 /src/passes/OptimizeInstructions.cpp
parent9202df3864d2d8f09f191f61a964a08c30d10821 (diff)
downloadbinaryen-d369cd6474364e5797e40af94676339af03723a9.tar.gz
binaryen-d369cd6474364e5797e40af94676339af03723a9.tar.bz2
binaryen-d369cd6474364e5797e40af94676339af03723a9.zip
Make unreachable a subtype of everything (#3673)
Since in principle an unreachable expression can be used in any position. An exception to this rule is in OptimizeInstructions, which avoids replacing concrete expressions with unreachable expressions so that it doesn't need to refinalize any expressions. Notably, Type::getLeastUpperBound was already treating unreachable as the bottom type.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp42
1 files changed, 19 insertions, 23 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index d4df08d18..f5718654e 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -860,32 +860,28 @@ struct OptimizeInstructions
}
if (iff->condition->type != Type::unreachable &&
ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) {
- // sides are identical, fold
- // if we can replace the if with one arm, and no side effects in the
- // condition, do that
- auto needCondition = effects(iff->condition).hasSideEffects();
- auto isSubType = Type::isSubType(iff->ifTrue->type, iff->type);
- if (isSubType && !needCondition) {
+ // The sides are identical, so fold. If we can replace the If with one
+ // arm and there are no side effects in the condition, replace it. But
+ // make sure not to change a concrete expression to an unreachable
+ // expression because we want to avoid having to refinalize.
+ bool needCondition = effects(iff->condition).hasSideEffects();
+ bool wouldBecomeUnreachable =
+ iff->type.isConcrete() && iff->ifTrue->type == Type::unreachable;
+ Builder builder(*getModule());
+ if (!wouldBecomeUnreachable && !needCondition) {
return iff->ifTrue;
+ } else if (!wouldBecomeUnreachable) {
+ return builder.makeSequence(builder.makeDrop(iff->condition),
+ iff->ifTrue);
} else {
- Builder builder(*getModule());
- if (isSubType) {
- return builder.makeSequence(builder.makeDrop(iff->condition),
- iff->ifTrue);
- } else {
- // the types diff. as the condition is reachable, that means the
- // if must be concrete while the arm is not
- assert(iff->type.isConcrete() &&
- iff->ifTrue->type == Type::unreachable);
- // emit a block with a forced type
- auto* ret = builder.makeBlock();
- if (needCondition) {
- ret->list.push_back(builder.makeDrop(iff->condition));
- }
- ret->list.push_back(iff->ifTrue);
- ret->finalize(iff->type);
- return ret;
+ // Emit a block with the original concrete type.
+ auto* ret = builder.makeBlock();
+ if (needCondition) {
+ ret->list.push_back(builder.makeDrop(iff->condition));
}
+ ret->list.push_back(iff->ifTrue);
+ ret->finalize(iff->type);
+ return ret;
}
}
}