Skip to content
Merged
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
22 changes: 22 additions & 0 deletions src/passes/GlobalTypeOptimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -660,6 +660,28 @@ struct GlobalTypeOptimization : public Pass {
curr->index = newIndex;
}

void visitStructRMW(StructRMW* curr) {
if (curr->ref->type == Type::unreachable) {
return;
}

auto newIndex = getNewIndex(curr->ref->type.getHeapType(), curr->index);
// We must not remove a field that is read from.
assert(newIndex != RemovedField);
curr->index = newIndex;
}

void visitStructCmpxchg(StructCmpxchg* curr) {
if (curr->ref->type == Type::unreachable) {
return;
}

auto newIndex = getNewIndex(curr->ref->type.getHeapType(), curr->index);
// We must not remove a field that is read from.
assert(newIndex != RemovedField);
curr->index = newIndex;
}

void visitFunction(Function* curr) {
if (needEHFixups) {
EHUtils::handleBlockNestedPops(curr, *getModule());
Expand Down
44 changes: 44 additions & 0 deletions test/lit/passes/gto-removals-rmw.wast
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,47 @@
)
)
)

;; When a field is removed, indexes in RMW and Cmpxchg should be updated.
(module
;; GTO should remove the first field because it is never read. The second
;; field will then be shifted from index 1 to 0.
;; CHECK: (rec
;; CHECK-NEXT: (type $struct (shared (struct (field (mut i32)))))
(type $struct (shared (struct (field (mut i64)) (field (mut i32)))))

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

;; CHECK: (func $use-field (type $1) (param $ref (ref $struct))
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.atomic.rmw.and $struct 0
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg $struct 0
;; CHECK-NEXT: (local.get $ref)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $use-field (param $ref (ref $struct))
;; Use field 1 with an atomic RMW.
(drop
(struct.atomic.rmw.and $struct 1
(local.get $ref)
(i32.const 1)
)
)
;; Use field 1 with an atomic Cmpxchg.
(drop
(struct.atomic.rmw.cmpxchg $struct 1
(local.get $ref)
(i32.const 0)
(i32.const 1)
)
)
)
)
Loading