diff options
-rw-r--r-- | src/passes/LocalCSE.cpp | 25 | ||||
-rw-r--r-- | test/passes/local-cse.txt | 22 | ||||
-rw-r--r-- | test/passes/local-cse.wast | 21 |
3 files changed, 66 insertions, 2 deletions
diff --git a/src/passes/LocalCSE.cpp b/src/passes/LocalCSE.cpp index a458937db..12f0d9d93 100644 --- a/src/passes/LocalCSE.cpp +++ b/src/passes/LocalCSE.cpp @@ -92,14 +92,35 @@ struct LocalCSE : public WalkerPass<LinearExecutionWalker<LocalCSE>> { equivalences.clear(); } - void checkInvalidations(EffectAnalyzer& effects) { + // Checks invalidations due to a set of effects. Also optionally receive + // an expression that was just post-visited, and that also needs to be + // taken into account. + void checkInvalidations(EffectAnalyzer& effects, Expression* curr = nullptr) { // TODO: this is O(bad) std::vector<HashedExpression> invalidated; for (auto& sinkable : usables) { + // Check invalidations of the values we may want to use. if (effects.invalidates(sinkable.second.effects)) { invalidated.push_back(sinkable.first); } } + if (curr) { + // If we are a set, we have more to check: each of the usable + // values was from a set, and we did not consider the set in + // the loop above - just the values. So here we must check that + // sets do not interfere. (Note that due to flattening we + // have no risk of tees etc.) + if (auto* set = curr->dynCast<SetLocal>()) { + for (auto& sinkable : usables) { + // Check if the index is the same. Make sure to ignore + // our own value, which we may have just added! + if (sinkable.second.index == set->index && + sinkable.second.value != set->value) { + invalidated.push_back(sinkable.first); + } + } + } + } for (auto index : invalidated) { usables.erase(index); } @@ -129,7 +150,7 @@ struct LocalCSE : public WalkerPass<LinearExecutionWalker<LocalCSE>> { EffectAnalyzer effects(self->getPassOptions()); if (effects.checkPost(curr)) { - self->checkInvalidations(effects); + self->checkInvalidations(effects, curr); } self->expressionStack.pop_back(); diff --git a/test/passes/local-cse.txt b/test/passes/local-cse.txt new file mode 100644 index 000000000..970a13dd8 --- /dev/null +++ b/test/passes/local-cse.txt @@ -0,0 +1,22 @@ +(module + (type $0 (func (result i64))) + (func $i64-shifts (; 0 ;) (type $0) (result i64) + (local $temp i64) + (set_local $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (set_local $temp + (i64.const 9999) + ) + (set_local $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (get_local $temp) + ) +) diff --git a/test/passes/local-cse.wast b/test/passes/local-cse.wast new file mode 100644 index 000000000..23ea6ff68 --- /dev/null +++ b/test/passes/local-cse.wast @@ -0,0 +1,21 @@ +(module + (func $i64-shifts (result i64) + (local $temp i64) + (set_local $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (set_local $temp + (i64.const 9999) + ) + (set_local $temp + (i64.add + (i64.const 1) + (i64.const 2) + ) + ) + (get_local $temp) + ) +) |