File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -514,13 +514,23 @@ struct GlobalTypeOptimization : public Pass {
514514 // operations here: the trap on a null ref happens after the value,
515515 // which might have side effects.
516516 Builder builder (*getModule ());
517- auto flipped = getResultOfFirst (curr->ref ,
518- builder.makeDrop (curr->value ),
519- getFunction (),
520- getModule (),
521- getPassOptions ());
522- replaceCurrent (
523- builder.makeDrop (builder.makeRefAs (RefAsNonNull, flipped)));
517+ auto * flipped = getResultOfFirst (curr->ref ,
518+ builder.makeDrop (curr->value ),
519+ getFunction (),
520+ getModule (),
521+ getPassOptions ());
522+ Expression* replacement =
523+ builder.makeDrop (builder.makeRefAs (RefAsNonNull, flipped));
524+ if (curr->order == MemoryOrder::SeqCst) {
525+ // If the removed set is sequentially consistent, we must insert a
526+ // seqcst fence to preserve the effect on the global order of seqcst
527+ // operations. No fence is necessary for release sets because there
528+ // are no reads for them to synchronize with given that we are
529+ // removing the field.
530+ replacement =
531+ builder.makeSequence (replacement, builder.makeAtomicFence ());
532+ }
533+ replaceCurrent (replacement);
524534 }
525535 }
526536
Original file line number Diff line number Diff line change 15641564 (export " globalB" (global $globalB ))
15651565)
15661566
1567+ ;; Removed atomic sets needs special handling.
1568+ (module
1569+ ;; CHECK: (rec
1570+ ;; CHECK-NEXT: (type $A (shared (struct)))
1571+ (type $A (shared (struct (mut i32 ))))
1572+
1573+ ;; CHECK: (type $1 (func (param (ref $A))))
1574+
1575+ ;; CHECK: (func $sets (type $1) (param $0 (ref $A))
1576+ ;; CHECK-NEXT: (drop
1577+ ;; CHECK-NEXT: (ref.as_non_null
1578+ ;; CHECK-NEXT: (block (result (ref $A))
1579+ ;; CHECK-NEXT: (drop
1580+ ;; CHECK-NEXT: (i32.const 1)
1581+ ;; CHECK-NEXT: )
1582+ ;; CHECK-NEXT: (local.get $0)
1583+ ;; CHECK-NEXT: )
1584+ ;; CHECK-NEXT: )
1585+ ;; CHECK-NEXT: )
1586+ ;; CHECK-NEXT: (drop
1587+ ;; CHECK-NEXT: (ref.as_non_null
1588+ ;; CHECK-NEXT: (block (result (ref $A))
1589+ ;; CHECK-NEXT: (drop
1590+ ;; CHECK-NEXT: (i32.const 1)
1591+ ;; CHECK-NEXT: )
1592+ ;; CHECK-NEXT: (local.get $0)
1593+ ;; CHECK-NEXT: )
1594+ ;; CHECK-NEXT: )
1595+ ;; CHECK-NEXT: )
1596+ ;; CHECK-NEXT: (block
1597+ ;; CHECK-NEXT: (drop
1598+ ;; CHECK-NEXT: (ref.as_non_null
1599+ ;; CHECK-NEXT: (block (result (ref $A))
1600+ ;; CHECK-NEXT: (drop
1601+ ;; CHECK-NEXT: (i32.const 1)
1602+ ;; CHECK-NEXT: )
1603+ ;; CHECK-NEXT: (local.get $0)
1604+ ;; CHECK-NEXT: )
1605+ ;; CHECK-NEXT: )
1606+ ;; CHECK-NEXT: )
1607+ ;; CHECK-NEXT: (atomic.fence)
1608+ ;; CHECK-NEXT: )
1609+ ;; CHECK-NEXT: )
1610+ (func $sets (param (ref $A ))
1611+ ;; Normal set is optimizable.
1612+ (struct.set $A 0
1613+ (local.get 0 )
1614+ (i32.const 1 )
1615+ )
1616+ ;; Release set is optimizable without a fence because there is no get to
1617+ ;; synchronize with.
1618+ (struct.atomic.set acqrel $A 0
1619+ (local.get 0 )
1620+ (i32.const 1 )
1621+ )
1622+ ;; This requires a fence to keep the effect on the global order of seqcst
1623+ ;; operations.
1624+ (struct.atomic.set $A 0
1625+ (local.get 0 )
1626+ (i32.const 1 )
1627+ )
1628+ )
1629+ )
You can’t perform that action at this time.
0 commit comments