Skip to content

Commit f8261ba

Browse files
authored
Optimize ref.as_non_null removal effect computation (#5479)
Followup to #5474
1 parent 6a2ec34 commit f8261ba

2 files changed

Lines changed: 40 additions & 8 deletions

File tree

src/passes/OptimizeInstructions.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,21 +1500,27 @@ struct OptimizeInstructions
15001500
// We need to see if a child with side effects exists after |input|.
15011501
// If there is such a child, it is a problem as mentioned above (it
15021502
// is fine for such a child to appear *before* |input|, as then we
1503-
// wouldn't be reordering effects).
1503+
// wouldn't be reordering effects). Thus, all we need to do is
1504+
// accumulate the effects in children after |input|, as we want to
1505+
// move the trap across those.
15041506
bool seenInput = false;
1507+
EffectAnalyzer crossedEffects(options, *getModule());
15051508
for (auto* child : ChildIterator(parent)) {
15061509
if (child == input) {
15071510
seenInput = true;
15081511
} else if (seenInput) {
1509-
// TODO We could ignore trap effects here (since traps are ok to
1510-
// reorder) and also local effects (since a change to a var
1511-
// would not be noticeable, unlike say a global).
1512-
if (EffectAnalyzer(options, *getModule(), child)
1513-
.hasSideEffects()) {
1514-
return;
1515-
}
1512+
crossedEffects.walk(child);
15161513
}
15171514
}
1515+
1516+
// Check if the effects we cross interfere with the effects of the
1517+
// trap we want to move. (We use a shallow effect analyzer since we
1518+
// will only move the ref.as_non_null itself.)
1519+
ShallowEffectAnalyzer movingEffects(options, *getModule(), input);
1520+
if (crossedEffects.invalidates(movingEffects)) {
1521+
return;
1522+
}
1523+
15181524
// If we got here, we've checked the siblings and found no problem.
15191525
checkedSiblings = true;
15201526
}

test/lit/passes/optimize-instructions-gc-tnh.wast

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,7 @@
608608
)
609609

610610
;; TNH: (func $null.cast-other.effects (type $ref?|$struct|_=>_none) (param $x (ref null $struct))
611+
;; TNH-NEXT: (local $i i32)
611612
;; TNH-NEXT: (struct.set $struct 0
612613
;; TNH-NEXT: (local.get $x)
613614
;; TNH-NEXT: (call $import)
@@ -616,8 +617,15 @@
616617
;; TNH-NEXT: (local.get $x)
617618
;; TNH-NEXT: (i32.const 10)
618619
;; TNH-NEXT: )
620+
;; TNH-NEXT: (struct.set $struct 0
621+
;; TNH-NEXT: (local.get $x)
622+
;; TNH-NEXT: (local.tee $i
623+
;; TNH-NEXT: (i32.const 10)
624+
;; TNH-NEXT: )
625+
;; TNH-NEXT: )
619626
;; TNH-NEXT: )
620627
;; NO_TNH: (func $null.cast-other.effects (type $ref?|$struct|_=>_none) (param $x (ref null $struct))
628+
;; NO_TNH-NEXT: (local $i i32)
621629
;; NO_TNH-NEXT: (struct.set $struct 0
622630
;; NO_TNH-NEXT: (ref.as_non_null
623631
;; NO_TNH-NEXT: (local.get $x)
@@ -628,8 +636,15 @@
628636
;; NO_TNH-NEXT: (local.get $x)
629637
;; NO_TNH-NEXT: (i32.const 10)
630638
;; NO_TNH-NEXT: )
639+
;; NO_TNH-NEXT: (struct.set $struct 0
640+
;; NO_TNH-NEXT: (local.get $x)
641+
;; NO_TNH-NEXT: (local.tee $i
642+
;; NO_TNH-NEXT: (i32.const 10)
643+
;; NO_TNH-NEXT: )
644+
;; NO_TNH-NEXT: )
631645
;; NO_TNH-NEXT: )
632646
(func $null.cast-other.effects (param $x (ref null $struct))
647+
(local $i i32)
633648
(struct.set $struct 0
634649
;; We cannot remove this ref.as_non_null, even though the struct.set will
635650
;; trap if the ref is null, because that would move the trap from before
@@ -648,6 +663,17 @@
648663
)
649664
(i32.const 10)
650665
)
666+
(struct.set $struct 0
667+
;; This one can be removed even without TNH, even though there are effects
668+
;; in it. A tee only has local effects, which do not interfere with a
669+
;; trap.
670+
(ref.as_non_null
671+
(local.get $x)
672+
)
673+
(local.tee $i
674+
(i32.const 10)
675+
)
676+
)
651677
)
652678

653679
;; Helper functions.

0 commit comments

Comments
 (0)