Skip to content

Commit 10c876d

Browse files
authored
Do not precompute RMW ops on GC types (#8517)
These operations have side effects and their results depend on the current state of the heap, so they cannot be safely constant-folded even if the current field value is known at compile time.
1 parent 7113c49 commit 10c876d

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

scripts/test/fuzzing.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
'unsubtyping-cmpxchg.wast',
8484
'struct-atomic-threads.wast',
8585
'type-refining-gufa-rmw.wast',
86+
'precompute-gc-atomics-rmw.wast',
8687
# contains too many segments to run in a wasm VM
8788
'limit-segments_disable-bulk-memory.wast',
8889
# https://github.com/WebAssembly/binaryen/issues/7176

src/passes/Precompute.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ class PrecomputingExpressionRunner
143143
return getGCAllocation(curr, [&]() { return Super::visitStructNew(curr); });
144144
}
145145
Flow visitStructSet(StructSet* curr) { return Flow(NONCONSTANT_FLOW); }
146+
Flow visitStructRMW(StructRMW* curr) { return Flow(NONCONSTANT_FLOW); }
147+
Flow visitStructCmpxchg(StructCmpxchg* curr) {
148+
return Flow(NONCONSTANT_FLOW);
149+
}
146150
Flow visitStructGet(StructGet* curr) {
147151
if (curr->ref->type == Type::unreachable || curr->ref->type.isNull()) {
148152
return Flow(NONCONSTANT_FLOW);
@@ -184,6 +188,8 @@ class PrecomputingExpressionRunner
184188
[&]() { return Super::visitArrayNewFixed(curr); });
185189
}
186190
Flow visitArraySet(ArraySet* curr) { return Flow(NONCONSTANT_FLOW); }
191+
Flow visitArrayRMW(ArrayRMW* curr) { return Flow(NONCONSTANT_FLOW); }
192+
Flow visitArrayCmpxchg(ArrayCmpxchg* curr) { return Flow(NONCONSTANT_FLOW); }
187193
Flow visitArrayGet(ArrayGet* curr) {
188194
if (curr->ref->type == Type::unreachable || curr->ref->type.isNull()) {
189195
return Flow(NONCONSTANT_FLOW);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
2+
;; RUN: wasm-opt %s --precompute --all-features -S -o - | filecheck %s
3+
4+
;; We should not precompute RMW operations because they read from and write to
5+
;; the heap.
6+
7+
(module
8+
;; CHECK: (type $struct (sub (shared (struct (field (mut i64))))))
9+
(type $struct (sub (shared (struct (field (mut i64))))))
10+
;; CHECK: (type $array (sub (shared (array (mut i64)))))
11+
(type $array (sub (shared (array (mut i64)))))
12+
13+
;; CHECK: (global $struct (ref $struct) (struct.new $struct
14+
;; CHECK-NEXT: (i64.const -39)
15+
;; CHECK-NEXT: ))
16+
(global $struct (ref $struct)
17+
(struct.new $struct (i64.const -39))
18+
)
19+
;; CHECK: (global $array (ref $array) (array.new $array
20+
;; CHECK-NEXT: (i64.const -39)
21+
;; CHECK-NEXT: (i32.const 1)
22+
;; CHECK-NEXT: ))
23+
(global $array (ref $array)
24+
(array.new $array (i64.const -39) (i32.const 1))
25+
)
26+
27+
;; CHECK: (func $struct-rmw-xchg (type $0) (result i64)
28+
;; CHECK-NEXT: (struct.atomic.rmw.xchg acqrel acqrel $struct 0
29+
;; CHECK-NEXT: (global.get $struct)
30+
;; CHECK-NEXT: (i64.const 0)
31+
;; CHECK-NEXT: )
32+
;; CHECK-NEXT: )
33+
(func $struct-rmw-xchg (result i64)
34+
(struct.atomic.rmw.xchg acqrel acqrel $struct 0
35+
(global.get $struct)
36+
(i64.const 0)
37+
)
38+
)
39+
40+
;; CHECK: (func $struct-rmw-cmpxchg (type $0) (result i64)
41+
;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg acqrel acqrel $struct 0
42+
;; CHECK-NEXT: (global.get $struct)
43+
;; CHECK-NEXT: (i64.const -39)
44+
;; CHECK-NEXT: (i64.const 0)
45+
;; CHECK-NEXT: )
46+
;; CHECK-NEXT: )
47+
(func $struct-rmw-cmpxchg (result i64)
48+
(struct.atomic.rmw.cmpxchg acqrel acqrel $struct 0
49+
(global.get $struct)
50+
(i64.const -39)
51+
(i64.const 0)
52+
)
53+
)
54+
55+
;; CHECK: (func $array-rmw-xchg (type $0) (result i64)
56+
;; CHECK-NEXT: (array.atomic.rmw.xchg acqrel acqrel $array
57+
;; CHECK-NEXT: (global.get $array)
58+
;; CHECK-NEXT: (i32.const 0)
59+
;; CHECK-NEXT: (i64.const 0)
60+
;; CHECK-NEXT: )
61+
;; CHECK-NEXT: )
62+
(func $array-rmw-xchg (result i64)
63+
(array.atomic.rmw.xchg acqrel acqrel $array
64+
(global.get $array)
65+
(i32.const 0)
66+
(i64.const 0)
67+
)
68+
)
69+
70+
;; CHECK: (func $array-rmw-cmpxchg (type $0) (result i64)
71+
;; CHECK-NEXT: (array.atomic.rmw.cmpxchg acqrel acqrel $array
72+
;; CHECK-NEXT: (global.get $array)
73+
;; CHECK-NEXT: (i32.const 0)
74+
;; CHECK-NEXT: (i64.const -39)
75+
;; CHECK-NEXT: (i64.const 0)
76+
;; CHECK-NEXT: )
77+
;; CHECK-NEXT: )
78+
(func $array-rmw-cmpxchg (result i64)
79+
(array.atomic.rmw.cmpxchg acqrel acqrel $array
80+
(global.get $array)
81+
(i32.const 0)
82+
(i64.const -39)
83+
(i64.const 0)
84+
)
85+
)
86+
)

0 commit comments

Comments
 (0)