summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2017-05-17 11:29:11 -0700
committerGitHub <noreply@github.com>2017-05-17 11:29:11 -0700
commitbb1c44a3f975bf8fb72216b9c04bcd34e31bd815 (patch)
tree90c6dc049931981ef28bc4728113528b1627595b /src
parent443cfe929d094e34d8d84270965c738743d06585 (diff)
downloadbinaryen-bb1c44a3f975bf8fb72216b9c04bcd34e31bd815.tar.gz
binaryen-bb1c44a3f975bf8fb72216b9c04bcd34e31bd815.tar.bz2
binaryen-bb1c44a3f975bf8fb72216b9c04bcd34e31bd815.zip
optimize if and select in the case their values are identical (#1013)
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index c1787b57d..50a7c5589 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -596,6 +596,18 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
std::swap(iff->ifTrue, iff->ifFalse);
}
}
+ if (ExpressionAnalyzer::equal(iff->ifTrue, iff->ifFalse)) {
+ // sides are identical, fold
+ if (!EffectAnalyzer(getPassOptions(), iff->condition).hasSideEffects()) {
+ return iff->ifTrue;
+ } else {
+ Builder builder(*getModule());
+ return builder.makeSequence(
+ builder.makeDrop(iff->condition),
+ iff->ifTrue
+ );
+ }
+ }
}
} else if (auto* select = curr->dynCast<Select>()) {
select->condition = optimizeBoolean(select->condition);
@@ -609,6 +621,33 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions,
std::swap(select->ifTrue, select->ifFalse);
}
}
+ if (ExpressionAnalyzer::equal(select->ifTrue, select->ifFalse)) {
+ // sides are identical, fold
+ EffectAnalyzer value(getPassOptions(), select->ifTrue);
+ if (value.hasSideEffects()) {
+ // at best we don't need the condition, but need to execute the value
+ // twice. a block is larger than a select by 2 bytes, and
+ // we must drop one value, so 3, while we save the condition,
+ // so it's not clear this is worth it, TODO
+ } else {
+ // value has no side effects
+ EffectAnalyzer condition(getPassOptions(), select->condition);
+ if (!condition.hasSideEffects()) {
+ return select->ifTrue;
+ } else {
+ // the condition is last, so we need a new local, and it may be
+ // a bad idea to use a block like we do for an if. Do it only if we
+ // can reorder
+ if (!condition.invalidates(value)) {
+ Builder builder(*getModule());
+ return builder.makeSequence(
+ builder.makeDrop(select->condition),
+ select->ifTrue
+ );
+ }
+ }
+ }
+ }
} else if (auto* br = curr->dynCast<Break>()) {
if (br->condition) {
br->condition = optimizeBoolean(br->condition);