Skip to content

Commit 2a4c278

Browse files
committed
Followup to #6061
1 parent fad0698 commit 2a4c278

File tree

2 files changed

+18
-16
lines changed

2 files changed

+18
-16
lines changed

src/passes/OnceReduction.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -486,14 +486,16 @@ struct OnceReduction : public Pass {
486486
ExpressionManipulator::nop(body);
487487
continue;
488488
}
489-
if (list.size() != 3) {
490-
// Something non-trivial; too many items for us to consider.
491-
continue;
492-
}
493-
auto* payload = list[2];
494-
if (auto* call = payload->dynCast<Call>()) {
489+
// The early-exit logic is the first item, followed by the global setting,
490+
// and we've ruled out the case of there being nothing else after those,
491+
// so there are at least 3 items.
492+
assert(list.size() >= 3);
493+
// We consider the first item in the payload. Anything further would be
494+
// much more difficult to analyze.
495+
auto* payloadStart = list[2];
496+
if (auto* call = payloadStart->dynCast<Call>()) {
495497
if (optInfo.onceFuncs.at(call->target).is()) {
496-
// All this "once" function does is call another. We do not need the
498+
// This "once" function immediately calls another. We do not need the
497499
// early-exit logic in this one, then, because of the following
498500
// reasoning. We are comparing these forms:
499501
//
@@ -502,27 +504,29 @@ struct OnceReduction : public Pass {
502504
// if (!foo$once) return; // two lines of
503505
// foo$once = 1; // early-exit code
504506
// bar();
507+
// ..
505508
// }
506509
//
507510
// to
508511
//
509512
// // AFTER
510513
// function foo() {
511514
// bar();
515+
// ..
512516
// }
513517
//
514518
// The question is whether different behavior can be observed between
515519
// those two. There are two cases, when we enter foo:
516520
//
517-
// 1. foo has been called before. Then we early-exit in BEFORE, and
521+
// 1. foo has been entered before. Then we early-exit in BEFORE, and
518522
// in AFTER we call bar which will early-exit (since foo was
519523
// called, which means bar was at least entered, which set its
520524
// global; bar might be on the stack, if it called foo, so it has
521525
// not necessarily fully executed - this is a tricky situation to
522526
// handle in general, like recursive imports of modules in various
523527
// languages - but we do know bar has been *entered*, which means
524528
// the global was set).
525-
// 2. foo has never been called before. In this case in BEFORE we set
529+
// 2. foo has never been entered before. In this case in BEFORE we set
526530
// the global and call bar, and in AFTER we also call bar.
527531
//
528532
// Thus, the behavior is the same, and we can remove the early-exit

test/lit/passes/once-reduction.wast

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,13 +1591,8 @@
15911591

15921592

15931593
;; CHECK: (func $once (type $0)
1594-
;; CHECK-NEXT: (if
1595-
;; CHECK-NEXT: (global.get $once)
1596-
;; CHECK-NEXT: (return)
1597-
;; CHECK-NEXT: )
1598-
;; CHECK-NEXT: (global.set $once
1599-
;; CHECK-NEXT: (i32.const 1)
1600-
;; CHECK-NEXT: )
1594+
;; CHECK-NEXT: (nop)
1595+
;; CHECK-NEXT: (nop)
16011596
;; CHECK-NEXT: (call $once.1)
16021597
;; CHECK-NEXT: (call $once.2)
16031598
;; CHECK-NEXT: (call $import
@@ -1610,6 +1605,9 @@
16101605
(return)
16111606
)
16121607
(global.set $once (i32.const 1))
1608+
;; We immediately call another "once" function, so we can remove the early-
1609+
;; exit logic before us. (Note that $once.1 and $once.2 call us, but there
1610+
;; we cannot remove anything because of the risk of infinite looping.)
16131611
(call $once.1)
16141612
;; We cannot remove this second call. While $once.1 calls $once.2, we may
16151613
;; be in this situation: a call started at $once.1, which calls $once

0 commit comments

Comments
 (0)