Skip to content

Commit 13d9fb3

Browse files
authored
Update RMW fields indices in GTO (#8474)
When GTO removes a struct field, RMW operations on later fields need to have their field indices updated.
1 parent 66c7166 commit 13d9fb3

2 files changed

Lines changed: 66 additions & 0 deletions

File tree

src/passes/GlobalTypeOptimization.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,28 @@ struct GlobalTypeOptimization : public Pass {
660660
curr->index = newIndex;
661661
}
662662

663+
void visitStructRMW(StructRMW* curr) {
664+
if (curr->ref->type == Type::unreachable) {
665+
return;
666+
}
667+
668+
auto newIndex = getNewIndex(curr->ref->type.getHeapType(), curr->index);
669+
// We must not remove a field that is read from.
670+
assert(newIndex != RemovedField);
671+
curr->index = newIndex;
672+
}
673+
674+
void visitStructCmpxchg(StructCmpxchg* curr) {
675+
if (curr->ref->type == Type::unreachable) {
676+
return;
677+
}
678+
679+
auto newIndex = getNewIndex(curr->ref->type.getHeapType(), curr->index);
680+
// We must not remove a field that is read from.
681+
assert(newIndex != RemovedField);
682+
curr->index = newIndex;
683+
}
684+
663685
void visitFunction(Function* curr) {
664686
if (needEHFixups) {
665687
EHUtils::handleBlockNestedPops(curr, *getModule());

test/lit/passes/gto-removals-rmw.wast

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,47 @@
7474
)
7575
)
7676
)
77+
78+
;; When a field is removed, indexes in RMW and Cmpxchg should be updated.
79+
(module
80+
;; GTO should remove the first field because it is never read. The second
81+
;; field will then be shifted from index 1 to 0.
82+
;; CHECK: (rec
83+
;; CHECK-NEXT: (type $struct (shared (struct (field (mut i32)))))
84+
(type $struct (shared (struct (field (mut i64)) (field (mut i32)))))
85+
86+
;; CHECK: (type $1 (func (param (ref $struct))))
87+
88+
;; CHECK: (func $use-field (type $1) (param $ref (ref $struct))
89+
;; CHECK-NEXT: (drop
90+
;; CHECK-NEXT: (struct.atomic.rmw.and $struct 0
91+
;; CHECK-NEXT: (local.get $ref)
92+
;; CHECK-NEXT: (i32.const 1)
93+
;; CHECK-NEXT: )
94+
;; CHECK-NEXT: )
95+
;; CHECK-NEXT: (drop
96+
;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg $struct 0
97+
;; CHECK-NEXT: (local.get $ref)
98+
;; CHECK-NEXT: (i32.const 0)
99+
;; CHECK-NEXT: (i32.const 1)
100+
;; CHECK-NEXT: )
101+
;; CHECK-NEXT: )
102+
;; CHECK-NEXT: )
103+
(func $use-field (param $ref (ref $struct))
104+
;; Use field 1 with an atomic RMW.
105+
(drop
106+
(struct.atomic.rmw.and $struct 1
107+
(local.get $ref)
108+
(i32.const 1)
109+
)
110+
)
111+
;; Use field 1 with an atomic Cmpxchg.
112+
(drop
113+
(struct.atomic.rmw.cmpxchg $struct 1
114+
(local.get $ref)
115+
(i32.const 0)
116+
(i32.const 1)
117+
)
118+
)
119+
)
120+
)

0 commit comments

Comments
 (0)