diff options
author | Alon Zakai <azakai@google.com> | 2023-01-05 13:20:31 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-01-05 13:20:31 -0800 |
commit | d623ba4b075aa1d70113fc41172a9ed248e0011d (patch) | |
tree | 07b614fef329165f8effe1b6407e97de12e1427d /src | |
parent | 0293c4649204e11f7db5724dc9477aa1ef6aef18 (diff) | |
download | binaryen-d623ba4b075aa1d70113fc41172a9ed248e0011d.tar.gz binaryen-d623ba4b075aa1d70113fc41172a9ed248e0011d.tar.bz2 binaryen-d623ba4b075aa1d70113fc41172a9ed248e0011d.zip |
[Wasm GC] Fix non-nullable cast optimizations with multiple children (#5396)
This fixes an oversight in #5395
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index c2142fe6c..916991ecb 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -1606,7 +1606,38 @@ struct OptimizeInstructions // Either way we trap here, but refining the type may have benefits later. if (ref->type.isNullable()) { if (auto* cast = ref->dynCast<RefCast>()) { - cast->type = Type(cast->type.getHeapType(), NonNullable); + // Note that we must be the last child of the parent, otherwise effects + // in the middle may need to remain: + // + // (struct.set + // (ref.cast null + // (call .. + // + // The call here must execute before the trap in the struct.set. To + // avoid that problem, inspect all children after us. If there are no + // such children, then there is no problem; if there are, see below. + auto canOptimize = true; + auto seenRef = false; + for (auto* child : ChildIterator(curr)) { + if (child == ref) { + seenRef = true; + } else if (seenRef) { + // This is a child after the reference. Check it for effects. For + // simplicity, focus on the case of traps-never-happens: if we can + // assume no trap occurs in the parent, then there must not be a + // trap in the child either, unless control flow transfers and we + // might not reach the parent. + // TODO: handle more cases. + if (!getPassOptions().trapsNeverHappen || + effects(child).transfersControlFlow()) { + canOptimize = false; + break; + } + } + } + if (canOptimize) { + cast->type = Type(cast->type.getHeapType(), NonNullable); + } } } |