diff options
author | Alon Zakai <azakai@google.com> | 2022-05-31 14:45:42 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-05-31 21:45:42 +0000 |
commit | 6257a5857a42fec6b86352b03c1e92dcb7a490ea (patch) | |
tree | 26169d49d4f095e0f84d0d9d9e01a691e1173e2b /src | |
parent | c4988562f9ed04400fc348bf99d5709cf063d96e (diff) | |
download | binaryen-6257a5857a42fec6b86352b03c1e92dcb7a490ea.tar.gz binaryen-6257a5857a42fec6b86352b03c1e92dcb7a490ea.tar.bz2 binaryen-6257a5857a42fec6b86352b03c1e92dcb7a490ea.zip |
[WasmGC] Fix try-catch and non-nullable local sets in values in SimplifyLocals (#4705)
Followup to #4703, this also handles the case where there is a non-
nullable local.set in the value of a nullable one, which we also cannot
optimize.
Fixes #4702
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/SimplifyLocals.cpp | 22 |
1 files changed, 17 insertions, 5 deletions
diff --git a/src/passes/SimplifyLocals.cpp b/src/passes/SimplifyLocals.cpp index 5cf3b8241..159f09963 100644 --- a/src/passes/SimplifyLocals.cpp +++ b/src/passes/SimplifyLocals.cpp @@ -306,8 +306,12 @@ struct SimplifyLocals for (auto& [index, info] : self->sinkables) { // Expressions that may throw cannot be moved into a try (which might // catch them, unlike before the move). - // - // Also, non-nullable local.sets cannot be moved into a try, as that may + if (info.effects.throws()) { + invalidated.push_back(index); + continue; + } + + // Non-nullable local.sets cannot be moved into a try, as that may // change dominance from the perspective of the spec // // (local.set $x X) @@ -338,9 +342,17 @@ struct SimplifyLocals // dominance). To stay compliant with the spec, however, we must not // move code regardless of whether ".." can throw - we must simply keep // the set outside of the try. - if (info.effects.throws() || - self->getFunction()->getLocalType(index).isNonNullable()) { - invalidated.push_back(index); + // + // The problem described can also occur on the *value* and not the set + // itself. For example, |X| above could be a local.set of a non-nullable + // local. For that reason we must scan it all. + if (self->getModule()->features.hasGCNNLocals()) { + for (auto* set : FindAll<LocalSet>(*info.item).list) { + if (self->getFunction()->getLocalType(set->index).isNonNullable()) { + invalidated.push_back(index); + break; + } + } } } for (auto index : invalidated) { |