summaryrefslogtreecommitdiff
path: root/src/passes
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes')
-rw-r--r--src/passes/LocalCSE.cpp50
-rw-r--r--src/passes/OptimizeInstructions.cpp2
2 files changed, 41 insertions, 11 deletions
diff --git a/src/passes/LocalCSE.cpp b/src/passes/LocalCSE.cpp
index 52346030c..bb017e938 100644
--- a/src/passes/LocalCSE.cpp
+++ b/src/passes/LocalCSE.cpp
@@ -330,6 +330,40 @@ struct Scanner
return false;
}
+ // We will fully compute effects later, but consider shallow effects at this
+ // early time to ignore things that cannot be optimized later, because we
+ // use a greedy algorithm. Specifically, imagine we see this:
+ //
+ // (call
+ // (i32.add
+ // ..
+ // )
+ // )
+ //
+ // If we considered the call relevant then we'd start to look for that
+ // larger pattern that contains the add, but then when we find that it
+ // cannot be optimized later it is too late for the add. (Instead of
+ // checking effects here we could perhaps add backtracking, but that sounds
+ // more complex.)
+ //
+ // We use |hasNonTrapSideEffects| because if a trap occurs the optimization
+ // remains valid: both this and the copy of it would trap, which means the
+ // first traps and the second isn't reached anyhow.
+ //
+ // (We don't stash these effects because we may compute many of them here,
+ // and only need the few for those patterns that repeat.)
+ if (ShallowEffectAnalyzer(options, *getModule(), curr)
+ .hasNonTrapSideEffects()) {
+ return false;
+ }
+
+ // We also cannot optimize away something that is intrinsically
+ // nondeterministic: even if it has no side effects, if it may return a
+ // different result each time, and then we cannot optimize away repeats.
+ if (Properties::isShallowlyGenerative(curr)) {
+ return false;
+ }
+
// If the size is at least 3, then if we have two of them we have 6,
// and so adding one set+one get and removing one of the items itself
// is not detrimental, and may be beneficial.
@@ -438,16 +472,12 @@ struct Checker
// none of them.)
effects.trap = false;
- // We also cannot optimize away something that is intrinsically
- // nondeterministic: even if it has no side effects, if it may return a
- // different result each time, then we cannot optimize away repeats.
- if (effects.hasSideEffects() ||
- Properties::isGenerative(curr, getModule()->features)) {
- requestInfos.erase(curr);
- } else {
- activeOriginals.emplace(
- curr, ActiveOriginalInfo{info.requests, std::move(effects)});
- }
+ // Note that we've already checked above that this has no side effects or
+ // generativity: if we got here, then it is good to go from the
+ // perspective of this expression itself (but may be invalidated by other
+ // code in between, see above).
+ activeOriginals.emplace(
+ curr, ActiveOriginalInfo{info.requests, std::move(effects)});
} else if (info.original) {
// The original may have already been invalidated. If so, remove our info
// as well.
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 3486fe82a..1a474be2c 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -2508,7 +2508,7 @@ private:
// To be equal, they must also be known to return the same result
// deterministically.
- return !Properties::isGenerative(left, getModule()->features);
+ return !Properties::isGenerative(left);
}
// Similar to areConsecutiveInputsEqual() but also checks if we can remove