Skip to content

Commit e2dd078

Browse files
authored
Fix OptimizeInstructions on unreachable GC RMWs (#8485)
OptimizeInstructions lowers RMWs on non-shared GC data to sequences of non-atomic operations. It would previously do this even for expressions with unreachable children, which caused assertion failures when trying to make unreachable scratch locals. Bail out early and leave the optimization to DCE in this case.
1 parent 0f06b26 commit e2dd078

2 files changed

Lines changed: 71 additions & 0 deletions

File tree

src/passes/OptimizeInstructions.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2003,6 +2003,10 @@ struct OptimizeInstructions
20032003
if (curr->ref->type.getHeapType().isShared()) {
20042004
return;
20052005
}
2006+
if (curr->type == Type::unreachable) {
2007+
// Leave this to DCE.
2008+
return;
2009+
}
20062010

20072011
// Lower the RMW to its more basic operations. Breaking the atomic
20082012
// operation into several non-atomic operations is safe because no other
@@ -2100,6 +2104,11 @@ struct OptimizeInstructions
21002104
return;
21012105
}
21022106

2107+
if (curr->type == Type::unreachable) {
2108+
// Leave this to DCE.
2109+
return;
2110+
}
2111+
21032112
// Just like other RMW operations, lower to basic operations when operating
21042113
// on unshared memory.
21052114
auto ref = builder.addVar(getFunction(), curr->ref->type);

test/lit/passes/optimize-instructions-struct-rmw.wast

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,4 +1308,66 @@
13081308
(i32.const 2)
13091309
)
13101310
)
1311+
1312+
;; CHECK: (func $struct-rmw-unreachable-lowering (type $16) (param $0 (ref null $unshared-i32)) (result i32)
1313+
;; CHECK-NEXT: (struct.atomic.rmw.add $unshared-i32 0
1314+
;; CHECK-NEXT: (local.get $0)
1315+
;; CHECK-NEXT: (unreachable)
1316+
;; CHECK-NEXT: )
1317+
;; CHECK-NEXT: )
1318+
(func $struct-rmw-unreachable-lowering (param (ref null $unshared-i32)) (result i32)
1319+
;; Check that we skip lowering if an operand is unreachable.
1320+
(struct.atomic.rmw.add $unshared-i32 0
1321+
(local.get 0)
1322+
(unreachable)
1323+
)
1324+
)
1325+
1326+
;; CHECK: (func $struct-cmpxchg-unreachable-lowering (type $16) (param $0 (ref null $unshared-i32)) (result i32)
1327+
;; CHECK-NEXT: (struct.atomic.rmw.cmpxchg $unshared-i32 0
1328+
;; CHECK-NEXT: (local.get $0)
1329+
;; CHECK-NEXT: (i32.const 1)
1330+
;; CHECK-NEXT: (unreachable)
1331+
;; CHECK-NEXT: )
1332+
;; CHECK-NEXT: )
1333+
(func $struct-cmpxchg-unreachable-lowering (param (ref null $unshared-i32)) (result i32)
1334+
(struct.atomic.rmw.cmpxchg $unshared-i32 0
1335+
(local.get 0)
1336+
(i32.const 1)
1337+
(unreachable)
1338+
)
1339+
)
1340+
1341+
;; CHECK: (func $array-rmw-unreachable-lowering (type $19) (param $0 (ref null $array)) (result i32)
1342+
;; CHECK-NEXT: (array.atomic.rmw.add $array
1343+
;; CHECK-NEXT: (local.get $0)
1344+
;; CHECK-NEXT: (i32.const 0)
1345+
;; CHECK-NEXT: (unreachable)
1346+
;; CHECK-NEXT: )
1347+
;; CHECK-NEXT: )
1348+
(func $array-rmw-unreachable-lowering (param (ref null $array)) (result i32)
1349+
;; Check that we skip lowering if an operand is unreachable.
1350+
(array.atomic.rmw.add $array
1351+
(local.get 0)
1352+
(i32.const 0)
1353+
(unreachable)
1354+
)
1355+
)
1356+
1357+
;; CHECK: (func $cmpxchg-unreachable-lowering (type $19) (param $0 (ref null $array)) (result i32)
1358+
;; CHECK-NEXT: (array.atomic.rmw.cmpxchg $array
1359+
;; CHECK-NEXT: (local.get $0)
1360+
;; CHECK-NEXT: (i32.const 0)
1361+
;; CHECK-NEXT: (i32.const 1)
1362+
;; CHECK-NEXT: (unreachable)
1363+
;; CHECK-NEXT: )
1364+
;; CHECK-NEXT: )
1365+
(func $cmpxchg-unreachable-lowering (param (ref null $array)) (result i32)
1366+
(array.atomic.rmw.cmpxchg $array
1367+
(local.get 0)
1368+
(i32.const 0)
1369+
(i32.const 1)
1370+
(unreachable)
1371+
)
1372+
)
13111373
)

0 commit comments

Comments
 (0)