diff options
author | Alon Zakai <azakai@google.com> | 2021-07-29 15:15:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-29 22:15:48 +0000 |
commit | c5b945bb4c83192218d7706ea23d5ea91a82d65c (patch) | |
tree | 8a0bc79dd847d6cf4ccde482ba0ff373b9e89df3 /src/passes/OptimizeInstructions.cpp | |
parent | be119e310624aa332fb476613a6e970fe214ec83 (diff) | |
download | binaryen-c5b945bb4c83192218d7706ea23d5ea91a82d65c.tar.gz binaryen-c5b945bb4c83192218d7706ea23d5ea91a82d65c.tar.bz2 binaryen-c5b945bb4c83192218d7706ea23d5ea91a82d65c.zip |
[Wasm GC] Optimize repeated identical ref.casts (#4039)
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 2e6a2d48d..7d9111e0b 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1172,7 +1172,10 @@ struct OptimizeInstructions if (curr->type == Type::unreachable) { return; } - if (getPassOptions().ignoreImplicitTraps) { + + auto passOptions = getPassOptions(); + + if (passOptions.ignoreImplicitTraps) { // A ref.cast traps when the RTTs do not line up, which can be of one of // two sorts of issues: // 1. The value being cast is not even a subtype of the cast type. In @@ -1204,6 +1207,32 @@ struct OptimizeInstructions } } + auto features = getModule()->features; + + // Repeated identical ref.cast operations are unnecessary, if using the + // exact same rtt - the result will be the same. Find the immediate child + // cast, if there is one, and see if it is identical. + // TODO: Look even further through incompatible casts? + auto* ref = curr->ref; + while (!ref->is<RefCast>()) { + auto* last = ref; + // RefCast falls through the value, so instead of calling getFallthrough() + // to look through all fallthroughs, we must iterate manually. Keep going + // until we reach either the end of things falling-through, or a cast. + ref = Properties::getImmediateFallthrough(ref, passOptions, features); + if (ref == last) { + break; + } + } + if (auto* child = ref->dynCast<RefCast>()) { + // Check if the casts are identical. + if (ExpressionAnalyzer::equal(curr->rtt, child->rtt) && + !EffectAnalyzer(passOptions, features, curr->rtt).hasSideEffects()) { + replaceCurrent(curr->ref); + return; + } + } + // ref.cast can be reordered with ref.as_non_null, // // (ref.cast (ref.as_non_null ..)) @@ -1345,7 +1374,7 @@ private: bool areConsecutiveInputsEqual(Expression* left, Expression* right) { // First, check for side effects. If there are any, then we can't even // assume things like local.get's of the same index being identical. - PassOptions passOptions = getPassOptions(); + auto passOptions = getPassOptions(); if (EffectAnalyzer(passOptions, getModule()->features, left) .hasSideEffects() || EffectAnalyzer(passOptions, getModule()->features, right) |