diff options
author | Heejin Ahn <aheejin@gmail.com> | 2021-10-21 16:44:58 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-21 16:44:58 -0700 |
commit | 1a7169113a65a401cd2ccfd3beb988b38cda9728 (patch) | |
tree | 3895fb800e66e80cf97628ce299d0065e6c217f6 /test/lit/passes/rse-eh.wast | |
parent | 4bac51d1d9a98e853fb7f75341820cda425393eb (diff) | |
download | binaryen-1a7169113a65a401cd2ccfd3beb988b38cda9728.tar.gz binaryen-1a7169113a65a401cd2ccfd3beb988b38cda9728.tar.bz2 binaryen-1a7169113a65a401cd2ccfd3beb988b38cda9728.zip |
[EH] Support try-delegate in CFGWalker (#4269)
This adds support for `try`-`delegate` to `CFGWalker`. This also adds a
single test for `catch`-less `try`.
Diffstat (limited to 'test/lit/passes/rse-eh.wast')
-rw-r--r-- | test/lit/passes/rse-eh.wast | 358 |
1 files changed, 358 insertions, 0 deletions
diff --git a/test/lit/passes/rse-eh.wast b/test/lit/passes/rse-eh.wast index e8b9570ed..8be0cfa82 100644 --- a/test/lit/passes/rse-eh.wast +++ b/test/lit/passes/rse-eh.wast @@ -452,4 +452,362 @@ ;; by one of the catches and it will set the local to 1. (local.set $x (i32.const 1)) ) + + ;; CHECK: (func $catchless-try + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (call $foo) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $catchless-try + (local $x i32) + (try + (do + (call $foo) + (local.set $x (i32.const 1)) + ) + ) + ;; The only way we end up here is when (call $foo) does not throw, because + ;; if (call $foo) throws, it will throw to the caller because it is within + ;; a catchless try. In that case the local.set after (call $foo) would have + ;; run before this, so this can be dropped. + (local.set $x (i32.const 1)) + ) + + ;; CHECK: (func $try-delegate0 + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $l0 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try2 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (throw $e + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $try-delegate0 + (local $x i32) + (try $l0 + (do + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (delegate $l0) + ) + ) + (catch_all) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ;; The innermost try has a delegate, which delegates to the outermost try's + ;; catch_all, which has the same local.set. So this can be dropped. + (local.set $x (i32.const 1)) + ) + + ;; CHECK: (func $try-delegate1 + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $l0 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try3 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (throw $e + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $try-delegate1 + (local $x i32) + (try $l0 + (do + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (delegate $l0) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ) + (catch_all) + ) + ;; The middle try's catch_all has the same local.set, but it is skipped + ;; because the innermost try-delegate delegates to the outer try while + ;; skipping the middle try-catch_all. So this should NOT be dropped. + (local.set $x (i32.const 1)) + ) + + ;; CHECK: (func $try-delegate2 + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $l0 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try4 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (throw $e + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate 2) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $try-delegate2 + (local $x i32) + (try $l0 + (do + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (delegate 2) ;; delegate to caller + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ;; The innermost try-delegate delegates to the caller, bypassing all + ;; local.sets in the middle and the outermost try-catch_alls. So this should + ;; NOT be dropped. (Instead this is unreachable, but that's DCE's work) + (local.set $x (i32.const 1)) + ) + + ;; CHECK: (func $try-delegate3 + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $l0 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $l1 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try5 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try6 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (throw $e + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $try-delegate3 + (local $x i32) + (try $l0 + (do + (try + (do + (try $l1 + (do + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (delegate $l1) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ) + (delegate $l0) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ) + (catch_all) + ) + ;; The innermost try delegates to $l1, which in turn delegates to $l0, + ;; skipping all local.sets in between. So this should NOT be dropped. + (local.set $x (i32.const 1)) + ) + + ;; CHECK: (func $try-delegate4 + ;; CHECK-NEXT: (local $x i32) + ;; CHECK-NEXT: (try $l0 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $l1 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try7 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (try $try8 + ;; CHECK-NEXT: (do + ;; CHECK-NEXT: (throw $e + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (delegate $l0) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (catch_all + ;; CHECK-NEXT: (local.set $x + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (i32.const 1) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $try-delegate4 + (local $x i32) + (try $l0 + (do + (try + (do + (try $l1 + (do + (try + (do + (try + (do + (throw $e (i32.const 0)) + ) + (delegate $l1) + ) + ) + (catch_all) + ) + ) + (delegate $l0) + ) + ) + (catch_all) + ) + ) + (catch_all + (local.set $x (i32.const 1)) + ) + ) + ;; The innermost try delegates to $l1, which in turn delgates to $l0, whose + ;; catch_all runs the same local.set. So this can be dropped. + (local.set $x (i32.const 1)) + ) ) |