Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/passes/Precompute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,13 @@ class PrecomputingExpressionRunner
if (hasEffects) {
// Visit, so we recompute the effects. (This is rare, see comment
// above.)
visitFunc();
auto flow = visitFunc();
// Also check the result of the effects - if it is non-constant, we
// cannot use it. (This can happen during propagation, when we see that
// other inputs exist to something we depend on.)
if (flow.breaking()) {
return flow;
}
}
// Refer to the same canonical GCData that we already created.
return Literal(data, curr->type.getHeapType());
Expand Down
89 changes: 89 additions & 0 deletions test/lit/passes/precompute-gc-loop.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.

;; RUN: wasm-opt %s --remove-unused-names --precompute-propagate --fuzz-exec -all -S -o - \
;; RUN: | filecheck %s

(module
;; CHECK: (type $struct (sub (struct (field i32))))
(type $struct (sub (struct (field i32))))

;; CHECK: (func $loop-different (type $1)
;; CHECK-NEXT: (local $struct (ref null $struct))
;; CHECK-NEXT: (local $int i32)
;; CHECK-NEXT: (local.set $int
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (loop $loop
;; CHECK-NEXT: (local.set $struct
;; CHECK-NEXT: (struct.new $struct
;; CHECK-NEXT: (local.get $int)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.set $int
;; CHECK-NEXT: (i32.const 1)
;; CHECK-NEXT: )
;; CHECK-NEXT: (br_if $loop
;; CHECK-NEXT: (i32.eqz
;; CHECK-NEXT: (block $block1 (result i32)
;; CHECK-NEXT: (block $block
;; CHECK-NEXT: (drop
;; CHECK-NEXT: (br_on_null $block
;; CHECK-NEXT: (local.get $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (br $block1
;; CHECK-NEXT: (struct.get $struct 0
;; CHECK-NEXT: (local.get $struct)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $loop-different
(local $struct (ref null $struct))
(local $int i32)
;; This int is set before the loop, and read at the loop top. The value there
;; is *not* 0, because we set a new value in the loop, which takes effect in
;; later iterations.
(local.set $int
(i32.const 0)
)
(loop $loop
(local.set $struct
(struct.new $struct
(local.get $int)
)
)
(local.set $int
(i32.const 1)
)

;; The rest of the code is needed to prevent the testcase from getting
;; optimized trivially away. This br should not be optimized away or
;; simplfied - it executes in the first loop iteration but not the second.
(br_if $loop
(i32.eqz
(block $block1 (result i32)
(block $block
(drop
(br_on_null $block
(local.get $struct)
)
)
(br $block1
(struct.get $struct 0
(local.get $struct)
)
)
)
(i32.const 0)
)
)
)
)
)
)
Loading