summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2022-11-22 14:17:30 -0800
committerGitHub <noreply@github.com>2022-11-22 14:17:30 -0800
commitc834ac4c11ecbb4e17e81d3ebcb64a6c6f453818 (patch)
tree58677554dcf57ef32b2e8d93ab7f1f7310662804 /src
parent09ce29d4ab6fd03a9e777f7244154f504a6c0113 (diff)
downloadbinaryen-c834ac4c11ecbb4e17e81d3ebcb64a6c6f453818.tar.gz
binaryen-c834ac4c11ecbb4e17e81d3ebcb64a6c6f453818.tar.bz2
binaryen-c834ac4c11ecbb4e17e81d3ebcb64a6c6f453818.zip
[Wasm GC] Fix CoalesceLocals on tees that receive a refined type (#5289)
Same testcase as in #5287 but in another pass.
Diffstat (limited to 'src')
-rw-r--r--src/passes/CoalesceLocals.cpp25
1 files changed, 22 insertions, 3 deletions
diff --git a/src/passes/CoalesceLocals.cpp b/src/passes/CoalesceLocals.cpp
index 558be07ff..062449e95 100644
--- a/src/passes/CoalesceLocals.cpp
+++ b/src/passes/CoalesceLocals.cpp
@@ -523,7 +523,10 @@ void CoalesceLocals::applyIndices(std::vector<Index>& indices,
}
}
if (auto* subSet = set->value->dynCast<LocalSet>()) {
- if (subSet->index == set->index) {
+ // Only do so if not only the index matches but also the type. If the
+ // inner type is more refined, leave that for other passes.
+ if (subSet->index == set->index &&
+ subSet->value->type == subSet->type) {
set->value = subSet->value;
continue;
}
@@ -550,12 +553,28 @@ void CoalesceLocals::applyIndices(std::vector<Index>& indices,
if (!action.effective) {
// value may have no side effects, further optimizations can eliminate
// it
- *action.origin = set->value;
+ auto* value = set->value;
if (!set->isTee()) {
// we need to drop it
Drop* drop = ExpressionManipulator::convert<LocalSet, Drop>(set);
- drop->value = *action.origin;
+ drop->value = value;
*action.origin = drop;
+ } else {
+ // This is a tee, and so, as earlier in this function, we must be
+ // careful of subtyping. Above we simply avoided the problem by
+ // leaving it for other passes, but we do want to remove ineffective
+ // stores - nothing else does that as well as this pass. Instead,
+ // create a block to cast back to the original type, which avoids
+ // changing types here, and leave it to other passes to refine types
+ // and remove the block.
+ auto originalType = (*action.origin)->type;
+ if (originalType != set->value->type) {
+ (*action.origin) =
+ Builder(*getModule()).makeBlock({set->value}, originalType);
+ } else {
+ // No special handling, just use the value.
+ *action.origin = set->value;
+ }
}
continue;
}