diff options
author | Alon Zakai <azakai@google.com> | 2022-10-31 14:17:40 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-31 14:17:40 -0700 |
commit | 8c3ebda4d79383aed4c9e8c83f59f53363d1067a (patch) | |
tree | 55559ff21c9112c1aba040ade30f06b035f1eb7f /test | |
parent | 91ecf5088944de356b514641d99051244c20eec4 (diff) | |
download | binaryen-8c3ebda4d79383aed4c9e8c83f59f53363d1067a.tar.gz binaryen-8c3ebda4d79383aed4c9e8c83f59f53363d1067a.tar.bz2 binaryen-8c3ebda4d79383aed4c9e8c83f59f53363d1067a.zip |
Fix br_if fallthrough value (#5200)
The fallthrough there is trickier because the value is evaluated before the condition.
Unlike other fallthroughs, the value is not last, so we need to check if the condition
(which is after it) interferes with it.
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/simplify-locals_rse_fallthrough.wast | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/test/lit/passes/simplify-locals_rse_fallthrough.wast b/test/lit/passes/simplify-locals_rse_fallthrough.wast new file mode 100644 index 000000000..a9161a853 --- /dev/null +++ b/test/lit/passes/simplify-locals_rse_fallthrough.wast @@ -0,0 +1,47 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. +;; RUN: wasm-opt %s --simplify-locals --rse -S -o - \ +;; RUN: | filecheck %s + +(module + ;; CHECK: (func $no (param $x i32) (result i32) + ;; CHECK-NEXT: (i32.add + ;; CHECK-NEXT: (block $block (result i32) + ;; CHECK-NEXT: (local.tee $x + ;; CHECK-NEXT: (br_if $block + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.tee $x + ;; CHECK-NEXT: (i32.const 42) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $no (param $x i32) (result i32) + (i32.add + (block $block (result i32) + ;; This local.tee is necessary. It might seem that the br_if flows out + ;; $x, so we don't need to write that same value to $x once more. + ;; SimplifyLocals and RedundantSetElimination try to find such sets and + ;; remove them. But this set is necessary, since a tee of $x executes + ;; after that local.get. That is, the br_if flows out the *old* value of + ;; $x. What happens in practice is that we branch (since the condition + ;; is 42), and flow out the old $x, which gets tee'd into $x once more. + ;; As a result, the block flows out the original value of $x, and the + ;; local.get reads that same value, so the final add returns 2 times the + ;; original value of $x. For all that to happen, we need those + ;; optimization passes to *not* remove the outer local.tee. + (local.tee $x + (br_if $block + (local.get $x) + (local.tee $x + (i32.const 42) + ) + ) + ) + ) + (local.get $x) + ) + ) +) |