File tree Expand file tree Collapse file tree 2 files changed +80
-7
lines changed Expand file tree Collapse file tree 2 files changed +80
-7
lines changed Original file line number Diff line number Diff line change @@ -514,13 +514,23 @@ struct GlobalTypeOptimization : public Pass {
514
514
// operations here: the trap on a null ref happens after the value,
515
515
// which might have side effects.
516
516
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);
524
534
}
525
535
}
526
536
Original file line number Diff line number Diff line change 1564
1564
(export " globalB" (global $globalB ))
1565
1565
)
1566
1566
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