Skip to content

Commit 0380ce9

Browse files
authored
[NFC] Handle atomic arrays in Heap2Local (#8549)
We previously had TODOs about handling atoimc arrays in the Array2Struct helper in the Heap2Local pass. However, we were already handling them correctly. When Array2Struct transformed an array get or set into a struct get or set, it did not previously preserve the memory order of the array access. But this tranformation only happens when the new struct access will also be subsequently optimized out, so the ordering does not matter. Update the code to preserve order anyway, since that is less surprising, and add some tests.
1 parent 74e21a6 commit 0380ce9

File tree

2 files changed

+107
-9
lines changed

2 files changed

+107
-9
lines changed

src/passes/Heap2Local.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1387,9 +1387,8 @@ struct Array2Struct : PostWalker<Array2Struct> {
13871387
}
13881388

13891389
// Convert the ArraySet into a StructSet.
1390-
// TODO: Handle atomic array accesses.
1391-
replaceCurrent(builder.makeStructSet(
1392-
index, curr->ref, curr->value, MemoryOrder::Unordered));
1390+
replaceCurrent(
1391+
builder.makeStructSet(index, curr->ref, curr->value, curr->order));
13931392
}
13941393

13951394
void visitArrayGet(ArrayGet* curr) {
@@ -1408,9 +1407,8 @@ struct Array2Struct : PostWalker<Array2Struct> {
14081407
}
14091408

14101409
// Convert the ArrayGet into a StructGet.
1411-
// TODO: Handle atomic array accesses.
14121410
replaceCurrent(builder.makeStructGet(
1413-
index, curr->ref, MemoryOrder::Unordered, curr->type, curr->signed_));
1411+
index, curr->ref, curr->order, curr->type, curr->signed_));
14141412
}
14151413

14161414
void visitArrayRMW(ArrayRMW* curr) {

test/lit/passes/heap2local.wast

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4615,8 +4615,10 @@
46154615

46164616
;; CHECK: (type $struct (shared (struct (field (mut i32)))))
46174617
(type $struct (shared (struct (field (mut i32)))))
4618+
;; CHECK: (type $array (shared (array (mut i32))))
4619+
(type $array (shared (array (field (mut i32)))))
46184620

4619-
;; CHECK: (func $acqrel (type $0)
4621+
;; CHECK: (func $acqrel-struct (type $0)
46204622
;; CHECK-NEXT: (local $0 (ref null $struct))
46214623
;; CHECK-NEXT: (local $1 i32)
46224624
;; CHECK-NEXT: (drop
@@ -4644,7 +4646,7 @@
46444646
;; CHECK-NEXT: )
46454647
;; CHECK-NEXT: )
46464648
;; CHECK-NEXT: )
4647-
(func $acqrel
4649+
(func $acqrel-struct
46484650
(local (ref null $struct))
46494651
(local.set 0
46504652
(struct.new_default $struct)
@@ -4662,7 +4664,56 @@
46624664
)
46634665
)
46644666

4665-
;; CHECK: (func $seqcst (type $0)
4667+
;; CHECK: (func $acqrel-array (type $0)
4668+
;; CHECK-NEXT: (local $0 (ref null $array))
4669+
;; CHECK-NEXT: (local $1 i32)
4670+
;; CHECK-NEXT: (drop
4671+
;; CHECK-NEXT: (block (result (ref null (shared none)))
4672+
;; CHECK-NEXT: (local.set $1
4673+
;; CHECK-NEXT: (i32.const 0)
4674+
;; CHECK-NEXT: )
4675+
;; CHECK-NEXT: (ref.null (shared none))
4676+
;; CHECK-NEXT: )
4677+
;; CHECK-NEXT: )
4678+
;; CHECK-NEXT: (drop
4679+
;; CHECK-NEXT: (block (result i32)
4680+
;; CHECK-NEXT: (drop
4681+
;; CHECK-NEXT: (ref.null (shared none))
4682+
;; CHECK-NEXT: )
4683+
;; CHECK-NEXT: (local.get $1)
4684+
;; CHECK-NEXT: )
4685+
;; CHECK-NEXT: )
4686+
;; CHECK-NEXT: (block
4687+
;; CHECK-NEXT: (drop
4688+
;; CHECK-NEXT: (ref.null (shared none))
4689+
;; CHECK-NEXT: )
4690+
;; CHECK-NEXT: (local.set $1
4691+
;; CHECK-NEXT: (i32.const 1)
4692+
;; CHECK-NEXT: )
4693+
;; CHECK-NEXT: )
4694+
;; CHECK-NEXT: )
4695+
(func $acqrel-array
4696+
(local (ref null $array))
4697+
(local.set 0
4698+
(array.new_default $array
4699+
(i32.const 1)
4700+
)
4701+
)
4702+
;; Same as with the struct. We can optimize.
4703+
(drop
4704+
(array.atomic.get acqrel $array
4705+
(local.get 0)
4706+
(i32.const 0)
4707+
)
4708+
)
4709+
(array.atomic.set acqrel $array
4710+
(local.get 0)
4711+
(i32.const 0)
4712+
(i32.const 1)
4713+
)
4714+
)
4715+
4716+
;; CHECK: (func $seqcst-struct (type $0)
46664717
;; CHECK-NEXT: (local $0 (ref null $struct))
46674718
;; CHECK-NEXT: (local $1 i32)
46684719
;; CHECK-NEXT: (drop
@@ -4690,7 +4741,7 @@
46904741
;; CHECK-NEXT: )
46914742
;; CHECK-NEXT: )
46924743
;; CHECK-NEXT: )
4693-
(func $seqcst
4744+
(func $seqcst-struct
46944745
(local (ref null $struct))
46954746
(local.set 0
46964747
(struct.new_default $struct)
@@ -4707,4 +4758,53 @@
47074758
(i32.const 0)
47084759
)
47094760
)
4761+
4762+
;; CHECK: (func $seqcst-array (type $0)
4763+
;; CHECK-NEXT: (local $0 (ref null $array))
4764+
;; CHECK-NEXT: (local $1 i32)
4765+
;; CHECK-NEXT: (drop
4766+
;; CHECK-NEXT: (block (result (ref null (shared none)))
4767+
;; CHECK-NEXT: (local.set $1
4768+
;; CHECK-NEXT: (i32.const 0)
4769+
;; CHECK-NEXT: )
4770+
;; CHECK-NEXT: (ref.null (shared none))
4771+
;; CHECK-NEXT: )
4772+
;; CHECK-NEXT: )
4773+
;; CHECK-NEXT: (drop
4774+
;; CHECK-NEXT: (block (result i32)
4775+
;; CHECK-NEXT: (drop
4776+
;; CHECK-NEXT: (ref.null (shared none))
4777+
;; CHECK-NEXT: )
4778+
;; CHECK-NEXT: (local.get $1)
4779+
;; CHECK-NEXT: )
4780+
;; CHECK-NEXT: )
4781+
;; CHECK-NEXT: (block
4782+
;; CHECK-NEXT: (drop
4783+
;; CHECK-NEXT: (ref.null (shared none))
4784+
;; CHECK-NEXT: )
4785+
;; CHECK-NEXT: (local.set $1
4786+
;; CHECK-NEXT: (i32.const 1)
4787+
;; CHECK-NEXT: )
4788+
;; CHECK-NEXT: )
4789+
;; CHECK-NEXT: )
4790+
(func $seqcst-array
4791+
(local (ref null $array))
4792+
(local.set 0
4793+
(array.new_default $array
4794+
(i32.const 1)
4795+
)
4796+
)
4797+
;; Same as with the struct. We can optimize.
4798+
(drop
4799+
(array.atomic.get seqcst $array
4800+
(local.get 0)
4801+
(i32.const 0)
4802+
)
4803+
)
4804+
(array.atomic.set seqcst $array
4805+
(local.get 0)
4806+
(i32.const 0)
4807+
(i32.const 1)
4808+
)
4809+
)
47104810
)

0 commit comments

Comments
 (0)