diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2021-03-10 16:06:19 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-11 00:06:19 +0000 |
commit | d369cd6474364e5797e40af94676339af03723a9 (patch) | |
tree | 2441fb6aec7ae185a73804fe61298854ee3495d9 /src/passes/OptimizeInstructions.cpp | |
parent | 9202df3864d2d8f09f191f61a964a08c30d10821 (diff) | |
download | binaryen-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.cpp | 42 |
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; } } } |