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.cpp80
1 files changed, 52 insertions, 28 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 28eaf0fba..7c14c4172 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -2294,14 +2294,57 @@ private:
// Information about our locals
std::vector<LocalInfo> localInfo;
+ // Checks if the first is a local.tee and the second a local.get of that same
+ // index. This is useful in the methods right below us, as it is a common
+ // pattern where two consecutive inputs are equal despite being syntactically
+ // different.
+ bool areMatchingTeeAndGet(Expression* left, Expression* right) {
+ if (auto* set = left->dynCast<LocalSet>()) {
+ if (auto* get = right->dynCast<LocalGet>()) {
+ if (set->isTee() && get->index == set->index) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
// Check if two consecutive inputs to an instruction are equal. As they are
// consecutive, no code can execeute in between them, which simplies the
// problem here (and which is the case we care about in this pass, which does
// simple peephole optimizations - all we care about is a single instruction
// at a time, and its inputs).
- //
- // This also checks that the inputs are removable (but we do not assume the
- // caller will always remove them).
+ bool areConsecutiveInputsEqual(Expression* left, Expression* right) {
+ // When we look for a tee/get pair, we can consider the fallthrough values
+ // for the first, as the fallthrough happens last (however, we must use
+ // NoTeeBrIf as we do not want to look through the tee). We cannot do this
+ // on the second, however, as there could be effects in the middle.
+ // TODO: Use effects here perhaps.
+ auto& passOptions = getPassOptions();
+ left =
+ Properties::getFallthrough(left,
+ passOptions,
+ *getModule(),
+ Properties::FallthroughBehavior::NoTeeBrIf);
+ if (areMatchingTeeAndGet(left, right)) {
+ return true;
+ }
+
+ // Ignore extraneous things and compare them syntactically. We can also
+ // look at the full fallthrough for both sides now.
+ left = Properties::getFallthrough(left, passOptions, *getModule());
+ right = Properties::getFallthrough(right, passOptions, *getModule());
+ if (!ExpressionAnalyzer::equal(left, right)) {
+ return false;
+ }
+
+ // To be equal, they must also be known to return the same result
+ // deterministically.
+ return !Properties::isGenerative(left, getModule()->features);
+ }
+
+ // Similar to areConsecutiveInputsEqual() but also checks if we can remove
+ // them (but we do not assume the caller will always remove them).
bool areConsecutiveInputsEqualAndRemovable(Expression* left,
Expression* right) {
// First, check for side effects. If there are any, then we can't even
@@ -2316,18 +2359,7 @@ private:
return false;
}
- // Ignore extraneous things and compare them structurally.
- left = Properties::getFallthrough(left, passOptions, *getModule());
- right = Properties::getFallthrough(right, passOptions, *getModule());
- if (!ExpressionAnalyzer::equal(left, right)) {
- return false;
- }
- // To be equal, they must also be known to return the same result
- // deterministically.
- if (Properties::isGenerative(left, getModule()->features)) {
- return false;
- }
- return true;
+ return areConsecutiveInputsEqual(left, right);
}
// Check if two consecutive inputs to an instruction are equal and can also be
@@ -2341,25 +2373,17 @@ private:
// side effects at all in the middle. For example, a Const in between is ok.
bool areConsecutiveInputsEqualAndFoldable(Expression* left,
Expression* right) {
- if (auto* set = left->dynCast<LocalSet>()) {
- if (auto* get = right->dynCast<LocalGet>()) {
- if (set->isTee() && get->index == set->index) {
- return true;
- }
- }
+ // TODO: We could probably consider fallthrough values for left, at least
+ // (since we fold into it).
+ if (areMatchingTeeAndGet(left, right)) {
+ return true;
}
+
// stronger property than we need - we can not only fold
// them but remove them entirely.
return areConsecutiveInputsEqualAndRemovable(left, right);
}
- // Similar to areConsecutiveInputsEqualAndFoldable, but only checks that they
- // are equal (and not that they are foldable).
- bool areConsecutiveInputsEqual(Expression* left, Expression* right) {
- // TODO: optimize cases that must be equal but are *not* foldable.
- return areConsecutiveInputsEqualAndFoldable(left, right);
- }
-
// Canonicalizing the order of a symmetric binary helps us
// write more concise pattern matching code elsewhere.
void canonicalize(Binary* binary) {