diff options
author | Alon Zakai <azakai@google.com> | 2023-04-04 11:41:36 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-04 18:41:36 +0000 |
commit | db23ac7f02396dfcf13a1ef6a7c5665f19d91c35 (patch) | |
tree | d856f6d6d822a206390ef3574bb6a52dee1c5318 | |
parent | a802fbe07c270f510c87dfa93577bd4731c075f3 (diff) | |
download | binaryen-db23ac7f02396dfcf13a1ef6a7c5665f19d91c35.tar.gz binaryen-db23ac7f02396dfcf13a1ef6a7c5665f19d91c35.tar.bz2 binaryen-db23ac7f02396dfcf13a1ef6a7c5665f19d91c35.zip |
[Wasm GC] Fix CoalesceLocals ineffective tee removal with type changes (#5621)
When we remove a tee there, we must not change the type at all.
-rw-r--r-- | src/cfg/liveness-traversal.h | 11 | ||||
-rw-r--r-- | test/lit/passes/coalesce-locals-gc.wast | 28 |
2 files changed, 38 insertions, 1 deletions
diff --git a/src/cfg/liveness-traversal.h b/src/cfg/liveness-traversal.h index d9b310d6f..650ee4f47 100644 --- a/src/cfg/liveness-traversal.h +++ b/src/cfg/liveness-traversal.h @@ -152,7 +152,16 @@ struct LivenessWalker : public CFGWalker<SubType, VisitorType, Liveness> { // if it has side effects) if (!self->currBasicBlock) { if (curr->isTee()) { - *currp = curr->value; + // We can remove the tee, but must leave something of the exact same + // type. + auto originalType = curr->type; + if (originalType != curr->value->type) { + *currp = + Builder(*self->getModule()).makeBlock({curr->value}, originalType); + } else { + // No special handling, just use the value. + *currp = curr->value; + } } else { *currp = Builder(*self->getModule()).makeDrop(curr->value); } diff --git a/test/lit/passes/coalesce-locals-gc.wast b/test/lit/passes/coalesce-locals-gc.wast index 1a830b4a5..38840f1ea 100644 --- a/test/lit/passes/coalesce-locals-gc.wast +++ b/test/lit/passes/coalesce-locals-gc.wast @@ -250,4 +250,32 @@ ) ) ) + + ;; CHECK: (func $replace-struct-param (type $f64_ref?|$A|_=>_f32) (param $0 f64) (param $1 (ref null $A)) (result f32) + ;; CHECK-NEXT: (call $replace-struct-param + ;; CHECK-NEXT: (block (result f64) + ;; CHECK-NEXT: (unreachable) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (ref.cast null $A + ;; CHECK-NEXT: (block (result (ref null $A)) + ;; CHECK-NEXT: (struct.new_default $A) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $replace-struct-param (param $unused f64) (param $A (ref null $A)) (result f32) + ;; As above, but now the value is a struct reference and it is on a local.tee. + ;; Again, we should replace the local operation with something of identical + ;; type to avoid a validation error. + (call $replace-struct-param + (block (result f64) + (unreachable) + ) + (ref.cast null $A + (local.tee $A + (struct.new_default $A) + ) + ) + ) + ) ) |