summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
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;
}
}
}