diff options
author | Alon Zakai <azakai@google.com> | 2023-08-08 16:04:25 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-08-08 16:04:25 -0700 |
commit | 0fc7b883d373924717ceccf71a6a759c97a8fb08 (patch) | |
tree | 610dc2ca3dd656f3ff5aa8cfa2ce7135099c67fa /test | |
parent | ef17febfd7106ee5330c01c66fbf8d3f6fdc0e03 (diff) | |
download | binaryen-0fc7b883d373924717ceccf71a6a759c97a8fb08.tar.gz binaryen-0fc7b883d373924717ceccf71a6a759c97a8fb08.tar.bz2 binaryen-0fc7b883d373924717ceccf71a6a759c97a8fb08.zip |
OptimizeCasts: Connect adjacent blocks in LinearExecutionWalker (#5866)
Followup to #5860, this does the same for (part of) OptimizeCasts.
As there, this is valid because it's ok if we branch away. This part of the pass
picks a different local to get when it knows locals have the same values but one
is more refined. It is ok to add a tee earlier even if it isn't used later.
Diffstat (limited to 'test')
-rw-r--r-- | test/lit/passes/optimize-casts-noeh.wast | 18 | ||||
-rw-r--r-- | test/lit/passes/optimize-casts.wast | 83 |
2 files changed, 80 insertions, 21 deletions
diff --git a/test/lit/passes/optimize-casts-noeh.wast b/test/lit/passes/optimize-casts-noeh.wast index 46d92953d..6cd6fa704 100644 --- a/test/lit/passes/optimize-casts-noeh.wast +++ b/test/lit/passes/optimize-casts-noeh.wast @@ -34,26 +34,28 @@ ) ) - ;; CHECK: (func $not-past-return_call (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK: (func $yes-past-return_call (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK-NEXT: (local $1 (ref $A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast $A - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (ref.cast $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (return_call $none) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $not-past-return_call (param $x (ref struct)) + (func $yes-past-return_call (param $x (ref struct)) (drop (ref.cast $A (local.get $x) ) ) - ;; The call_return in the middle stops us from helping the last get. We - ;; could still optimize in this case, however, with more precision (since - ;; after we branch out it doesn't matter what we have below). + ;; The call_return in the middle does not stop us from optimizing, since + ;; after we branch out it doesn't matter what we have below. (return_call $none) (drop (local.get $x) diff --git a/test/lit/passes/optimize-casts.wast b/test/lit/passes/optimize-casts.wast index 83cde8a4b..254daedc4 100644 --- a/test/lit/passes/optimize-casts.wast +++ b/test/lit/passes/optimize-casts.wast @@ -177,28 +177,30 @@ ) ) - ;; CHECK: (func $not-past-call (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK: (func $yes-past-call (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK-NEXT: (local $1 (ref $A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast $A - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (ref.cast $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (call $get) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) - (func $not-past-call (param $x (ref struct)) + (func $yes-past-call (param $x (ref struct)) (drop (ref.cast $A (local.get $x) ) ) - ;; The call in the middle stops us from helping the last get, since a call - ;; might branch out. TODO we could still optimize in this case, with more - ;; precision (since if we branch out it doesn't matter what we have below). + ;; The call in the middle does not stops us from helping the last get, since + ;; if we branch out it doesn't matter what we have below. (drop (call $get) ) @@ -208,16 +210,19 @@ ) ;; CHECK: (func $not-past-call_ref (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK-NEXT: (local $1 (ref $A)) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (ref.cast $A - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.tee $1 + ;; CHECK-NEXT: (ref.cast $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (call_ref $void ;; CHECK-NEXT: (ref.func $void) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop - ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: (local.get $1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $not-past-call_ref (param $x (ref struct)) @@ -226,8 +231,7 @@ (local.get $x) ) ) - ;; As in the last function, the call in the middle stops us from helping the - ;; last get (this time with a call_ref). + ;; As in the last function, but a call_ref. (call_ref $void (ref.func $void) ) @@ -236,6 +240,59 @@ ) ) + ;; CHECK: (func $not-backwards-past-call (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call $void) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $not-backwards-past-call (param $x (ref struct)) + ;; As above, but here we would like to move a cast *earlier*. We must not do + ;; that past a possible branch. + (drop + (local.get $x) + ) + (call $void) + (drop + (ref.cast $A + (local.get $x) + ) + ) + ) + + ;; CHECK: (func $not-backwards-past-call_ref (type $ref|struct|_=>_none) (param $x (ref struct)) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (call_ref $void + ;; CHECK-NEXT: (ref.func $void) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (ref.cast $A + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $not-backwards-past-call_ref (param $x (ref struct)) + ;; As above, but with a call_ref. + (drop + (local.get $x) + ) + (call_ref $void + (ref.func $void) + ) + (drop + (ref.cast $A + (local.get $x) + ) + ) + ) + ;; CHECK: (func $best (type $ref|struct|_=>_none) (param $x (ref struct)) ;; CHECK-NEXT: (local $1 (ref $A)) ;; CHECK-NEXT: (local $2 (ref $B)) |