Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/passes/Heap2Local.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,9 @@ struct Struct2Local : PostWalker<Struct2Local> {
builder.makeDrop(curr->expected),
builder.makeDrop(curr->replacement),
structGet});
if (block->type != curr->type) {
refinalize = true;
}
replaceCurrent(block);
return;
}
Expand Down Expand Up @@ -1226,6 +1229,9 @@ struct Struct2Local : PostWalker<Struct2Local> {
builder.makeDrop(curr->expected),
builder.makeDrop(curr->replacement),
arrayGet});
if (block->type != curr->type) {
refinalize = true;
}
replaceCurrent(block);
// Since `ref` must be an array and arrays are processed before structs,
// it is not possible that `ref` will be processed later. We therefore do
Expand Down
119 changes: 115 additions & 4 deletions test/lit/passes/heap2local-rmw.wast
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@

;; CHECK: (type $3 (func (param (ref null $struct)) (result (ref null $struct))))

;; CHECK: (type $4 (func (param (ref null $struct) (ref null $struct)) (result (ref null $struct))))
;; CHECK: (type $4 (func (param (ref $struct))))

;; CHECK: (type $5 (func (param i32) (result i32)))
;; CHECK: (type $5 (func (param (ref null $struct) (ref null $struct)) (result (ref null $struct))))

;; CHECK: (type $6 (func (param i32) (result i32)))

;; CHECK: (type $arr (array (mut i32)))
(type $arr (array (mut i32)))
Expand Down Expand Up @@ -81,6 +83,55 @@
)
)

;; CHECK: (func $no-escape-cmpxchg-expected-null-ref (type $4) (param $x (ref $struct))
;; CHECK-NEXT: (local $1 (ref null $struct))
;; CHECK-NEXT: (local $2 nullref)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref none))
;; CHECK-NEXT: (br_on_cast_fail $block (ref none) (ref none)
;; CHECK-NEXT: (block (result (ref none))
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block ;; (replaces unreachable StructGet we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $no-escape-cmpxchg-expected-null-ref (param $x (ref $struct))
;; When `ref` is null, replacing the cmpxchg with a struct.get refines the
;; result type from the replacement type `(ref $struct)` to `(ref none)`,
;; which requires refinalization.
(drop
(block $block (result (ref $struct))
(br_on_cast_fail $block (ref $struct) (ref $struct)
(struct.atomic.rmw.cmpxchg $struct 0
(ref.null none)
(struct.new_default $struct)
(local.get $x)
)
)
)
)
)

;; CHECK: (func $rmw-add-i32 (type $1) (result i32)
;; CHECK-NEXT: (local $0 i32)
;; CHECK-NEXT: (local $1 i32)
Expand Down Expand Up @@ -587,7 +638,7 @@
)
)

;; CHECK: (func $rmw-cmpxchg-ref (type $4) (param $0 (ref null $struct)) (param $1 (ref null $struct)) (result (ref null $struct))
;; CHECK: (func $rmw-cmpxchg-ref (type $5) (param $0 (ref null $struct)) (param $1 (ref null $struct)) (result (ref null $struct))
;; CHECK-NEXT: (local $2 (ref null $struct))
;; CHECK-NEXT: (local $3 (ref null $struct))
;; CHECK-NEXT: (local $4 eqref)
Expand Down Expand Up @@ -875,7 +926,7 @@
)
)

;; CHECK: (func $array-rmw-nonconstant-index (type $5) (param $idx i32) (result i32)
;; CHECK: (func $array-rmw-nonconstant-index (type $6) (param $idx i32) (result i32)
;; CHECK-NEXT: (array.atomic.rmw.add $arr
;; CHECK-NEXT: (array.new_fixed $arr 2
;; CHECK-NEXT: (i32.const 0)
Expand Down Expand Up @@ -1495,6 +1546,8 @@

;; CHECK: (type $1 (func (param (ref $array))))

;; CHECK: (type $2 (func (param (ref eq))))

;; CHECK: (func $array-cmpxchg-expected (type $1) (param $array (ref $array))
;; CHECK-NEXT: (local $1 eqref)
;; CHECK-NEXT: (local $2 (ref null $array))
Expand Down Expand Up @@ -1540,6 +1593,64 @@
)
)
)

;; CHECK: (func $array-cmpxchg-expected-null-ref (type $2) (param $x (ref eq))
;; CHECK-NEXT: (local $1 eqref)
;; CHECK-NEXT: (local $2 nullref)
;; CHECK-NEXT: (local $3 i32)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block $block (result (ref none))
;; CHECK-NEXT: (br_on_cast_fail $block (ref none) (ref none)
;; CHECK-NEXT: (block (result (ref none))
;; CHECK-NEXT: (local.set $2
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $3
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (block (result nullref)
;; CHECK-NEXT: (local.set $1
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (block ;; (replaces unreachable ArrayGet we can't emit)
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $2)
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (local.get $3)
;; CHECK-NEXT: )
;; CHECK-NEXT: (unreachable)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $array-cmpxchg-expected-null-ref (param $x (ref eq))
;; When `ref` is null, replacing the cmpxchg with an array.get refines the
;; result type from `(ref eq)` to `(ref none)`, requiring refinalization.
(drop
(block $block (result (ref eq))
(br_on_cast_fail $block (ref eq) (ref eq)
(array.atomic.rmw.cmpxchg $array
(ref.null none)
(i32.const 0)
(array.new_default $array
(i32.const 1)
)
(local.get $x)
)
)
)
)
)
)

(module
Expand Down
Loading